From dfffcc7c0a9208e00065378c6a59167a817c51f7 Mon Sep 17 00:00:00 2001 From: Christopher Wilcox Date: Tue, 4 Feb 2020 00:30:48 +0000 Subject: [PATCH] chore(): remove now split repos (#10326) Removes source from monorepo for billingbudgets, IAM, pubsub, redis, speech, talent, trace, vision, video intelligence --- README.rst | 24 +- billingbudgets/.coveragerc | 19 - billingbudgets/.flake8 | 14 - billingbudgets/.repo-metadata.json | 13 - billingbudgets/CHANGELOG.md | 24 - billingbudgets/LICENSE | 201 - billingbudgets/MANIFEST.in | 5 - billingbudgets/README.rst | 77 - billingbudgets/docs/README.rst | 1 - billingbudgets/docs/_static/custom.css | 4 - billingbudgets/docs/_templates/layout.html | 50 - billingbudgets/docs/changelog.md | 1 - billingbudgets/docs/conf.py | 363 -- billingbudgets/docs/gapic/v1beta1/api.rst | 6 - billingbudgets/docs/gapic/v1beta1/types.rst | 5 - billingbudgets/docs/index.rst | 19 - billingbudgets/google/__init__.py | 24 - billingbudgets/google/cloud/__init__.py | 24 - .../google/cloud/billing_budgets.py | 25 - .../cloud/billing_budgets_v1beta1/__init__.py | 41 - .../billing_budgets_v1beta1/gapic/__init__.py | 0 .../gapic/budget_service_client.py | 618 -- .../gapic/budget_service_client_config.py | 48 - .../billing_budgets_v1beta1/gapic/enums.py | 55 - .../gapic/transports/__init__.py | 0 .../budget_service_grpc_transport.py | 178 - .../billing_budgets_v1beta1/proto/__init__.py | 0 .../proto/budget_model.proto | 180 - .../proto/budget_model_pb2.py | 765 --- .../proto/budget_model_pb2_grpc.py | 2 - .../proto/budget_service.proto | 161 - .../proto/budget_service_pb2.py | 628 -- .../proto/budget_service_pb2_grpc.py | 125 - .../cloud/billing_budgets_v1beta1/types.py | 47 - billingbudgets/noxfile.py | 160 - billingbudgets/setup.cfg | 3 - billingbudgets/setup.py | 75 - billingbudgets/synth.metadata | 159 - billingbudgets/synth.py | 71 - .../test_budget_service_client_v1beta1.py | 261 - iam/.coveragerc | 19 - iam/.flake8 | 14 - iam/.repo-metadata.json | 12 - iam/CHANGELOG.md | 73 - iam/LICENSE | 201 - iam/MANIFEST.in | 5 - iam/README.rst | 85 - iam/docs/README.rst | 1 - iam/docs/_static/custom.css | 4 - iam/docs/_templates/layout.html | 50 - iam/docs/changelog.md | 1 - iam/docs/conf.py | 357 - iam/docs/gapic/v1/api.rst | 6 - iam/docs/gapic/v1/types.rst | 5 - iam/docs/index.rst | 20 - iam/google/__init__.py | 24 - iam/google/cloud/__init__.py | 24 - iam/google/cloud/iam_credentials.py | 24 - .../cloud/iam_credentials_v1/__init__.py | 39 - .../iam_credentials_v1/gapic/__init__.py | 0 .../gapic/iam_credentials_client.py | 590 -- .../gapic/iam_credentials_client_config.py | 43 - .../gapic/transports/__init__.py | 0 .../iam_credentials_grpc_transport.py | 163 - .../iam_credentials_v1/proto/__init__.py | 0 .../iam_credentials_v1/proto/common.proto | 189 - .../iam_credentials_v1/proto/common_pb2.py | 846 --- .../proto/common_pb2_grpc.py | 2 - .../proto/iamcredentials.proto | 78 - .../proto/iamcredentials_pb2.py | 109 - .../proto/iamcredentials_pb2_grpc.py | 116 - iam/google/cloud/iam_credentials_v1/types.py | 45 - iam/noxfile.py | 160 - iam/setup.cfg | 3 - iam/setup.py | 79 - iam/synth.metadata | 156 - iam/synth.py | 76 - .../v1/test_iam_credentials_client_v1.py | 225 - pubsub/.coveragerc | 19 - pubsub/.flake8 | 14 - pubsub/.repo-metadata.json | 13 - pubsub/CHANGELOG.md | 610 -- pubsub/LICENSE | 201 - pubsub/MANIFEST.in | 5 - pubsub/README.rst | 229 - pubsub/docs/README.rst | 1 - pubsub/docs/_static/custom.css | 4 - pubsub/docs/_templates/layout.html | 50 - pubsub/docs/changelog.md | 1 - pubsub/docs/conf.py | 356 - pubsub/docs/index.rst | 22 - pubsub/docs/publisher/api/client.rst | 6 - pubsub/docs/publisher/api/futures.rst | 6 - pubsub/docs/publisher/index.rst | 138 - pubsub/docs/subscriber/api/client.rst | 6 - pubsub/docs/subscriber/api/futures.rst | 6 - pubsub/docs/subscriber/api/message.rst | 5 - pubsub/docs/subscriber/api/scheduler.rst | 6 - pubsub/docs/subscriber/index.rst | 190 - pubsub/docs/types.rst | 5 - pubsub/google/__init__.py | 24 - pubsub/google/cloud/__init__.py | 24 - pubsub/google/cloud/pubsub.py | 25 - pubsub/google/cloud/pubsub_v1/__init__.py | 30 - pubsub/google/cloud/pubsub_v1/_gapic.py | 71 - pubsub/google/cloud/pubsub_v1/exceptions.py | 20 - pubsub/google/cloud/pubsub_v1/futures.py | 186 - .../google/cloud/pubsub_v1/gapic/__init__.py | 0 .../cloud/pubsub_v1/gapic/publisher_client.py | 1095 ---- .../gapic/publisher_client_config.py | 99 - .../pubsub_v1/gapic/subscriber_client.py | 1885 ------ .../gapic/subscriber_client_config.py | 138 - .../pubsub_v1/gapic/transports/__init__.py | 0 .../transports/publisher_grpc_transport.py | 260 - .../transports/subscriber_grpc_transport.py | 434 -- .../google/cloud/pubsub_v1/proto/__init__.py | 0 .../google/cloud/pubsub_v1/proto/pubsub.proto | 1067 --- .../cloud/pubsub_v1/proto/pubsub_pb2.py | 4694 -------------- .../cloud/pubsub_v1/proto/pubsub_pb2_grpc.py | 573 -- .../cloud/pubsub_v1/publisher/__init__.py | 20 - .../pubsub_v1/publisher/_batch/__init__.py | 0 .../cloud/pubsub_v1/publisher/_batch/base.py | 169 - .../pubsub_v1/publisher/_batch/thread.py | 339 - .../cloud/pubsub_v1/publisher/client.py | 308 - .../cloud/pubsub_v1/publisher/exceptions.py | 29 - .../cloud/pubsub_v1/publisher/futures.py | 52 - .../cloud/pubsub_v1/subscriber/__init__.py | 20 - .../subscriber/_protocol/__init__.py | 0 .../subscriber/_protocol/dispatcher.py | 197 - .../subscriber/_protocol/heartbeater.py | 70 - .../subscriber/_protocol/helper_threads.py | 112 - .../subscriber/_protocol/histogram.py | 154 - .../pubsub_v1/subscriber/_protocol/leaser.py | 193 - .../subscriber/_protocol/requests.py | 33 - .../_protocol/streaming_pull_manager.py | 659 -- .../cloud/pubsub_v1/subscriber/client.py | 230 - .../cloud/pubsub_v1/subscriber/futures.py | 53 - .../cloud/pubsub_v1/subscriber/message.py | 257 - .../cloud/pubsub_v1/subscriber/scheduler.py | 123 - pubsub/google/cloud/pubsub_v1/types.py | 128 - pubsub/noxfile.py | 160 - pubsub/pylint.config.py | 32 - pubsub/setup.cfg | 3 - pubsub/setup.py | 90 - pubsub/synth.metadata | 39 - pubsub/synth.py | 195 - pubsub/tests/system.py | 639 -- .../gapic/v1/test_system_publisher_v1.py | 30 - pubsub/tests/unit/__init__.py | 0 .../unit/gapic/v1/test_publisher_client_v1.py | 478 -- .../gapic/v1/test_subscriber_client_v1.py | 843 --- .../pubsub_v1/publisher/batch/test_base.py | 78 - .../pubsub_v1/publisher/batch/test_thread.py | 421 -- .../publisher/test_futures_publisher.py | 32 - .../publisher/test_publisher_client.py | 267 - .../pubsub_v1/subscriber/test_dispatcher.py | 261 - .../subscriber/test_futures_subscriber.py | 66 - .../pubsub_v1/subscriber/test_heartbeater.py | 125 - .../subscriber/test_helper_threads.py | 118 - .../pubsub_v1/subscriber/test_histogram.py | 84 - .../unit/pubsub_v1/subscriber/test_leaser.py | 225 - .../unit/pubsub_v1/subscriber/test_message.py | 172 - .../pubsub_v1/subscriber/test_scheduler.py | 56 - .../subscriber/test_streaming_pull_manager.py | 826 --- .../subscriber/test_subscriber_client.py | 108 - pubsub/tests/unit/pubsub_v1/test__gapic.py | 63 - pubsub/tests/unit/pubsub_v1/test_futures.py | 148 - pubsub/tests/unit/test_pubsub.py | 22 - redis/.coveragerc | 19 - redis/.flake8 | 14 - redis/.repo-metadata.json | 13 - redis/CHANGELOG.md | 104 - redis/LICENSE | 201 - redis/MANIFEST.in | 5 - redis/README.rst | 88 - redis/docs/README.rst | 1 - redis/docs/_static/custom.css | 4 - redis/docs/_templates/layout.html | 50 - redis/docs/conf.py | 359 - redis/docs/gapic/v1/api.rst | 6 - redis/docs/gapic/v1/types.rst | 5 - redis/docs/gapic/v1beta1/api.rst | 6 - redis/docs/gapic/v1beta1/types.rst | 5 - redis/docs/index.rst | 11 - redis/google/__init__.py | 24 - redis/google/cloud/__init__.py | 24 - redis/google/cloud/redis.py | 25 - redis/google/cloud/redis_v1/__init__.py | 41 - redis/google/cloud/redis_v1/gapic/__init__.py | 0 .../redis_v1/gapic/cloud_redis_client.py | 1031 --- .../gapic/cloud_redis_client_config.py | 63 - redis/google/cloud/redis_v1/gapic/enums.py | 81 - .../redis_v1/gapic/transports/__init__.py | 0 .../transports/cloud_redis_grpc_transport.py | 256 - redis/google/cloud/redis_v1/proto/__init__.py | 0 .../cloud/redis_v1/proto/cloud_redis.proto | 579 -- .../cloud/redis_v1/proto/cloud_redis_pb2.py | 2313 ------- .../redis_v1/proto/cloud_redis_pb2_grpc.py | 235 - redis/google/cloud/redis_v1/types.py | 48 - redis/google/cloud/redis_v1beta1/__init__.py | 41 - .../cloud/redis_v1beta1/gapic/__init__.py | 0 .../redis_v1beta1/gapic/cloud_redis_client.py | 1033 --- .../gapic/cloud_redis_client_config.py | 63 - .../google/cloud/redis_v1beta1/gapic/enums.py | 81 - .../gapic/transports/__init__.py | 0 .../transports/cloud_redis_grpc_transport.py | 256 - .../cloud/redis_v1beta1/proto/__init__.py | 0 .../redis_v1beta1/proto/cloud_redis.proto | 555 -- .../redis_v1beta1/proto/cloud_redis_pb2.py | 2130 ------ .../proto/cloud_redis_pb2_grpc.py | 235 - redis/google/cloud/redis_v1beta1/types.py | 48 - redis/noxfile.py | 160 - redis/setup.cfg | 3 - redis/setup.py | 88 - redis/synth.metadata | 202 - redis/synth.py | 104 - .../gapic/v1/test_cloud_redis_client_v1.py | 639 -- .../test_cloud_redis_client_v1beta1.py | 641 -- speech/.coveragerc | 19 - speech/.flake8 | 14 - speech/.repo-metadata.json | 13 - speech/CHANGELOG.md | 251 - speech/LICENSE | 201 - speech/MANIFEST.in | 5 - speech/README.rst | 109 - speech/docs/README.rst | 1 - speech/docs/_static/custom.css | 4 - speech/docs/_templates/layout.html | 50 - speech/docs/changelog.md | 1 - speech/docs/conf.py | 356 - speech/docs/gapic/v1/api.rst | 6 - speech/docs/gapic/v1/types.rst | 5 - speech/docs/gapic/v1p1beta1/api.rst | 6 - speech/docs/gapic/v1p1beta1/types.rst | 5 - speech/docs/index.rst | 282 - speech/google/__init__.py | 22 - speech/google/cloud/__init__.py | 22 - speech/google/cloud/speech.py | 25 - speech/google/cloud/speech_v1/__init__.py | 30 - .../google/cloud/speech_v1/gapic/__init__.py | 0 speech/google/cloud/speech_v1/gapic/enums.py | 196 - .../cloud/speech_v1/gapic/speech_client.py | 412 -- .../speech_v1/gapic/speech_client_config.py | 38 - .../speech_v1/gapic/transports/__init__.py | 0 .../gapic/transports/speech_grpc_transport.py | 160 - speech/google/cloud/speech_v1/helpers.py | 102 - .../google/cloud/speech_v1/proto/__init__.py | 0 .../cloud/speech_v1/proto/cloud_speech.proto | 759 --- .../cloud/speech_v1/proto/cloud_speech_pb2.py | 2640 -------- .../speech_v1/proto/cloud_speech_pb2_grpc.py | 93 - speech/google/cloud/speech_v1/types.py | 48 - .../google/cloud/speech_v1p1beta1/__init__.py | 30 - .../cloud/speech_v1p1beta1/gapic/__init__.py | 0 .../cloud/speech_v1p1beta1/gapic/enums.py | 200 - .../speech_v1p1beta1/gapic/speech_client.py | 412 -- .../gapic/speech_client_config.py | 38 - .../gapic/transports/__init__.py | 0 .../gapic/transports/speech_grpc_transport.py | 160 - .../cloud/speech_v1p1beta1/proto/__init__.py | 0 .../speech_v1p1beta1/proto/cloud_speech.proto | 816 --- .../proto/cloud_speech_pb2.py | 2823 -------- .../proto/cloud_speech_pb2_grpc.py | 93 - speech/google/cloud/speech_v1p1beta1/types.py | 48 - speech/noxfile.py | 180 - speech/pylint.config.py | 25 - speech/samples/resources/brooklyn_bridge.flac | Bin 52410 -> 0 bytes speech/samples/resources/brooklyn_bridge.mp3 | Bin 29928 -> 0 bytes speech/samples/resources/brooklyn_bridge.raw | Bin 57958 -> 0 bytes speech/samples/resources/brooklyn_bridge.wav | Bin 319574 -> 0 bytes speech/samples/resources/commercial_mono.wav | Bin 724844 -> 0 bytes speech/samples/resources/hello.raw | Bin 16114 -> 0 bytes speech/samples/resources/hello.wav | Bin 44494 -> 0 bytes speech/samples/resources/multi.flac | Bin 228398 -> 0 bytes speech/samples/resources/multi.wav | Bin 909356 -> 0 bytes speech/samples/v1/speech_transcribe_async.py | 90 - .../samples/v1/speech_transcribe_async_gcs.py | 91 - ..._transcribe_async_word_time_offsets_gcs.py | 98 - .../v1/speech_transcribe_enhanced_model.py | 85 - .../v1/speech_transcribe_model_selection.py | 77 - .../speech_transcribe_model_selection_gcs.py | 78 - .../v1/speech_transcribe_multichannel.py | 86 - .../v1/speech_transcribe_multichannel_gcs.py | 85 - speech/samples/v1/speech_transcribe_sync.py | 86 - .../samples/v1/speech_transcribe_sync_gcs.py | 87 - speech/samples/v1/test/samples.manifest.yaml | 38 - .../v1/test/speech_transcribe_async.test.yaml | 28 - .../speech_transcribe_async_gcs.test.yaml | 28 - ...ribe_async_word_time_offsets_gcs.test.yaml | 37 - ...speech_transcribe_enhanced_model.test.yaml | 29 - ...peech_transcribe_model_selection.test.yaml | 52 - ...h_transcribe_model_selection_gcs.test.yaml | 52 - .../speech_transcribe_multichannel.test.yaml | 31 - ...eech_transcribe_multichannel_gcs.test.yaml | 32 - .../v1/test/speech_transcribe_sync.test.yaml | 28 - .../test/speech_transcribe_sync_gcs.test.yaml | 28 - .../v1p1beta1/speech_adaptation_beta.py | 100 - .../v1p1beta1/speech_contexts_classes_beta.py | 93 - .../v1p1beta1/speech_quickstart_beta.py | 85 - ...speech_transcribe_auto_punctuation_beta.py | 82 - .../speech_transcribe_diarization_beta.py | 97 - .../speech_transcribe_multilanguage_beta.py | 91 - ...ch_transcribe_recognition_metadata_beta.py | 92 - ...h_transcribe_word_level_confidence_beta.py | 88 - .../v1p1beta1/test/samples.manifest.yaml | 32 - .../test/speech_adaptation_beta.test.yaml | 11 - .../speech_contexts_classes_beta.test.yaml | 11 - .../test/speech_quickstart_beta.test.yaml | 11 - ...transcribe_auto_punctuation_beta.test.yaml | 28 - ...eech_transcribe_diarization_beta.test.yaml | 40 - ...ch_transcribe_multilanguage_beta.test.yaml | 33 - ...scribe_recognition_metadata_beta.test.yaml | 27 - ...cribe_word_level_confidence_beta.test.yaml | 35 - speech/setup.cfg | 3 - speech/setup.py | 86 - speech/synth.metadata | 361 -- speech/synth.py | 66 - .../system/gapic/v1/test_system_speech_v1.py | 94 - .../v1p1beta1/test_system_speech_v1p1beta1.py | 96 - .../unit/gapic/v1/test_speech_client_v1.py | 244 - .../v1p1beta1/test_speech_client_v1p1beta1.py | 244 - speech/tests/unit/test_helpers.py | 53 - talent/.coveragerc | 19 - talent/.flake8 | 14 - talent/.repo-metadata.json | 13 - talent/CHANGELOG.md | 85 - talent/LICENSE | 201 - talent/MANIFEST.in | 5 - talent/README.rst | 78 - talent/docs/README.rst | 1 - talent/docs/_static/custom.css | 4 - talent/docs/_templates/layout.html | 50 - talent/docs/changelog.md | 1 - talent/docs/conf.py | 356 - talent/docs/gapic/v4beta1/api.rst | 6 - talent/docs/gapic/v4beta1/types.rst | 5 - talent/docs/index.rst | 20 - talent/google/__init__.py | 24 - talent/google/cloud/__init__.py | 24 - talent/google/cloud/talent.py | 41 - .../google/cloud/talent_v4beta1/__init__.py | 87 - .../cloud/talent_v4beta1/gapic/__init__.py | 0 .../gapic/application_service_client.py | 635 -- .../application_service_client_config.py | 48 - .../gapic/company_service_client.py | 659 -- .../gapic/company_service_client_config.py | 48 - .../talent_v4beta1/gapic/completion_client.py | 339 - .../gapic/completion_client_config.py | 28 - .../cloud/talent_v4beta1/gapic/enums.py | 1153 ---- .../gapic/event_service_client.py | 298 - .../gapic/event_service_client_config.py | 28 - .../gapic/job_service_client.py | 1725 ----- .../gapic/job_service_client_config.py | 73 - .../gapic/profile_service_client.py | 1009 --- .../gapic/profile_service_client_config.py | 53 - .../gapic/tenant_service_client.py | 636 -- .../gapic/tenant_service_client_config.py | 48 - .../gapic/transports/__init__.py | 0 .../application_service_grpc_transport.py | 178 - .../company_service_grpc_transport.py | 177 - .../transports/completion_grpc_transport.py | 125 - .../event_service_grpc_transport.py | 130 - .../transports/job_service_grpc_transport.py | 268 - .../profile_service_grpc_transport.py | 197 - .../tenant_service_grpc_transport.py | 176 - .../cloud/talent_v4beta1/proto/__init__.py | 0 .../talent_v4beta1/proto/application.proto | 185 - .../talent_v4beta1/proto/application_pb2.py | 570 -- .../proto/application_pb2_grpc.py | 2 - .../proto/application_service.proto | 182 - .../proto/application_service_pb2.py | 661 -- .../proto/application_service_pb2_grpc.py | 123 - .../cloud/talent_v4beta1/proto/batch.proto | 26 - .../cloud/talent_v4beta1/proto/batch_pb2.py | 39 - .../talent_v4beta1/proto/batch_pb2_grpc.py | 2 - .../cloud/talent_v4beta1/proto/common.proto | 1074 --- .../cloud/talent_v4beta1/proto/common_pb2.py | 3140 --------- .../talent_v4beta1/proto/common_pb2_grpc.py | 2 - .../cloud/talent_v4beta1/proto/company.proto | 120 - .../cloud/talent_v4beta1/proto/company_pb2.py | 454 -- .../talent_v4beta1/proto/company_pb2_grpc.py | 2 - .../proto/company_service.proto | 215 - .../proto/company_service_pb2.py | 688 -- .../proto/company_service_pb2_grpc.py | 122 - .../proto/completion_service.proto | 173 - .../proto/completion_service_pb2.py | 539 -- .../proto/completion_service_pb2_grpc.py | 50 - .../cloud/talent_v4beta1/proto/event.proto | 235 - .../cloud/talent_v4beta1/proto/event_pb2.py | 600 -- .../talent_v4beta1/proto/event_pb2_grpc.py | 2 - .../talent_v4beta1/proto/event_service.proto | 76 - .../talent_v4beta1/proto/event_service_pb2.py | 171 - .../proto/event_service_pb2_grpc.py | 58 - .../cloud/talent_v4beta1/proto/filters.proto | 781 --- .../cloud/talent_v4beta1/proto/filters_pb2.py | 2897 --------- .../talent_v4beta1/proto/filters_pb2_grpc.py | 2 - .../talent_v4beta1/proto/histogram.proto | 54 - .../talent_v4beta1/proto/histogram_pb2.py | 260 - .../proto/histogram_pb2_grpc.py | 2 - .../cloud/talent_v4beta1/proto/job.proto | 351 - .../cloud/talent_v4beta1/proto/job_pb2.py | 1282 ---- .../talent_v4beta1/proto/job_pb2_grpc.py | 2 - .../talent_v4beta1/proto/job_service.proto | 913 --- .../talent_v4beta1/proto/job_service_pb2.py | 2581 -------- .../proto/job_service_pb2_grpc.py | 232 - .../cloud/talent_v4beta1/proto/profile.proto | 784 --- .../cloud/talent_v4beta1/proto/profile_pb2.py | 3588 ---------- .../talent_v4beta1/proto/profile_pb2_grpc.py | 2 - .../proto/profile_service.proto | 512 -- .../proto/profile_service_pb2.py | 1470 ----- .../proto/profile_service_pb2_grpc.py | 147 - .../cloud/talent_v4beta1/proto/tenant.proto | 87 - .../cloud/talent_v4beta1/proto/tenant_pb2.py | 217 - .../talent_v4beta1/proto/tenant_pb2_grpc.py | 2 - .../talent_v4beta1/proto/tenant_service.proto | 177 - .../proto/tenant_service_pb2.py | 644 -- .../proto/tenant_service_pb2_grpc.py | 121 - talent/google/cloud/talent_v4beta1/types.py | 102 - talent/noxfile.py | 160 - talent/setup.cfg | 3 - talent/setup.py | 86 - talent/synth.metadata | 366 -- talent/synth.py | 40 - ...test_application_service_client_v4beta1.py | 314 - .../test_company_service_client_v4beta1.py | 317 - .../v4beta1/test_completion_client_v4beta1.py | 106 - .../test_event_service_client_v4beta1.py | 110 - .../test_job_service_client_v4beta1.py | 588 -- .../test_profile_service_client_v4beta1.py | 356 - .../test_tenant_service_client_v4beta1.py | 258 - trace/.coveragerc | 19 - trace/.flake8 | 14 - trace/.repo-metadata.json | 13 - trace/CHANGELOG.md | 183 - trace/LICENSE | 201 - trace/MANIFEST.in | 5 - trace/PUBLISHING.rst | 46 - trace/README.rst | 112 - trace/docs/README.rst | 1 - trace/docs/_static/custom.css | 4 - trace/docs/_templates/layout.html | 50 - trace/docs/changelog.md | 1 - trace/docs/conf.py | 357 - trace/docs/gapic/v1/api.rst | 6 - trace/docs/gapic/v1/types.rst | 5 - trace/docs/gapic/v2/api.rst | 6 - trace/docs/gapic/v2/types.rst | 5 - trace/docs/index.rst | 34 - trace/docs/starting.html | 8 - trace/google/__init__.py | 1 - trace/google/cloud/__init__.py | 1 - trace/google/cloud/trace.py | 21 - trace/google/cloud/trace/__init__.py | 34 - trace/google/cloud/trace/_gapic.py | 321 - trace/google/cloud/trace/client.py | 247 - trace/google/cloud/trace/v1/__init__.py | 21 - trace/google/cloud/trace/v1/_gapic.py | 200 - trace/google/cloud/trace/v1/client.py | 177 - trace/google/cloud/trace_v1/__init__.py | 45 - trace/google/cloud/trace_v1/gapic/__init__.py | 0 trace/google/cloud/trace_v1/gapic/enums.py | 60 - .../trace_v1/gapic/trace_service_client.py | 503 -- .../gapic/trace_service_client_config.py | 38 - .../trace_v1/gapic/transports/__init__.py | 0 .../trace_service_grpc_transport.py | 155 - trace/google/cloud/trace_v1/proto/__init__.py | 0 trace/google/cloud/trace_v1/proto/trace.proto | 304 - .../google/cloud/trace_v1/proto/trace_pb2.py | 1108 ---- .../cloud/trace_v1/proto/trace_pb2_grpc.py | 96 - .../google/cloud/trace_v1/proto/tracing.proto | 59 - trace/google/cloud/trace_v1/types.py | 50 - trace/google/cloud/trace_v2/__init__.py | 45 - trace/google/cloud/trace_v2/gapic/__init__.py | 0 trace/google/cloud/trace_v2/gapic/enums.py | 53 - .../trace_v2/gapic/trace_service_client.py | 464 -- .../gapic/trace_service_client_config.py | 33 - .../trace_v2/gapic/transports/__init__.py | 0 .../trace_service_grpc_transport.py | 138 - trace/google/cloud/trace_v2/proto/__init__.py | 0 trace/google/cloud/trace_v2/proto/trace.proto | 344 - .../google/cloud/trace_v2/proto/trace_pb2.py | 1926 ------ .../cloud/trace_v2/proto/trace_pb2_grpc.py | 2 - .../google/cloud/trace_v2/proto/tracing.proto | 79 - .../cloud/trace_v2/proto/tracing_pb2.py | 181 - .../cloud/trace_v2/proto/tracing_pb2_grpc.py | 79 - trace/google/cloud/trace_v2/types.py | 58 - trace/noxfile.py | 160 - trace/setup.cfg | 3 - trace/setup.py | 90 - trace/synth.metadata | 268 - trace/synth.py | 54 - trace/tests/__init__.py | 13 - .../gapic/v1/test_system_trace_service_v1.py | 30 - .../v1/test_system_trace_service_v1_vpcsc.py | 72 - .../gapic/v2/test_system_trace_service_v2.py | 30 - .../v2/test_system_trace_service_v2_vpcsc.py | 47 - .../gapic/v1/test_trace_service_client_v1.py | 183 - .../gapic/v2/test_trace_service_client_v2.py | 155 - trace/tests/unit/v1/test__gapic_v1.py | 247 - trace/tests/unit/v1/test_client_v1.py | 284 - trace/tests/unit/v2/test__gapic_v2.py | 292 - trace/tests/unit/v2/test_client_v2.py | 162 - videointelligence/.coveragerc | 19 - videointelligence/.flake8 | 14 - videointelligence/.repo-metadata.json | 13 - videointelligence/CHANGELOG.md | 270 - videointelligence/LICENSE | 201 - videointelligence/MANIFEST.in | 5 - videointelligence/README.rst | 106 - videointelligence/docs/README.rst | 1 - videointelligence/docs/_static/custom.css | 4 - videointelligence/docs/_templates/layout.html | 49 - videointelligence/docs/changelog.md | 1 - videointelligence/docs/conf.py | 363 -- videointelligence/docs/gapic/v1/api.rst | 6 - videointelligence/docs/gapic/v1/types.rst | 5 - videointelligence/docs/gapic/v1beta2/api.rst | 6 - .../docs/gapic/v1beta2/types.rst | 5 - .../docs/gapic/v1p1beta1/api.rst | 6 - .../docs/gapic/v1p1beta1/types.rst | 5 - .../docs/gapic/v1p2beta1/api.rst | 6 - .../docs/gapic/v1p2beta1/types.rst | 5 - .../docs/gapic/v1p3beta1/api.rst | 6 - .../docs/gapic/v1p3beta1/types.rst | 5 - videointelligence/docs/index.rst | 56 - videointelligence/google/__init__.py | 24 - videointelligence/google/cloud/__init__.py | 24 - .../google/cloud/videointelligence.py | 25 - .../cloud/videointelligence_v1/__init__.py | 32 - .../videointelligence_v1/gapic/__init__.py | 0 .../cloud/videointelligence_v1/gapic/enums.py | 82 - .../gapic/transports/__init__.py | 0 ...deo_intelligence_service_grpc_transport.py | 137 - .../video_intelligence_service_client.py | 306 - ...ideo_intelligence_service_client_config.py | 28 - .../videointelligence_v1/proto/__init__.py | 0 .../proto/video_intelligence.proto | 745 --- .../proto/video_intelligence_pb2.py | 4186 ------------ .../proto/video_intelligence_pb2_grpc.py | 56 - .../cloud/videointelligence_v1/types.py | 48 - .../videointelligence_v1beta2/__init__.py | 34 - .../gapic/__init__.py | 0 .../videointelligence_v1beta2/gapic/enums.py | 76 - .../gapic/transports/__init__.py | 0 ...deo_intelligence_service_grpc_transport.py | 137 - .../video_intelligence_service_client.py | 306 - ...ideo_intelligence_service_client_config.py | 28 - .../proto/__init__.py | 0 .../proto/video_intelligence.proto | 396 -- .../proto/video_intelligence_pb2.py | 2321 ------- .../proto/video_intelligence_pb2_grpc.py | 56 - .../cloud/videointelligence_v1beta2/types.py | 48 - .../videointelligence_v1p1beta1/__init__.py | 34 - .../gapic/__init__.py | 0 .../gapic/enums.py | 76 - .../gapic/transports/__init__.py | 0 ...deo_intelligence_service_grpc_transport.py | 137 - .../video_intelligence_service_client.py | 308 - ...ideo_intelligence_service_client_config.py | 28 - .../proto/__init__.py | 0 .../proto/video_intelligence.proto | 434 -- .../proto/video_intelligence_pb2.py | 2422 ------- .../proto/video_intelligence_pb2_grpc.py | 56 - .../videointelligence_v1p1beta1/types.py | 48 - .../videointelligence_v1p2beta1/__init__.py | 34 - .../gapic/__init__.py | 0 .../gapic/enums.py | 78 - .../gapic/transports/__init__.py | 0 ...deo_intelligence_service_grpc_transport.py | 137 - .../video_intelligence_service_client.py | 308 - ...ideo_intelligence_service_client_config.py | 28 - .../proto/__init__.py | 0 .../proto/video_intelligence.proto | 467 -- .../proto/video_intelligence_pb2.py | 2711 -------- .../proto/video_intelligence_pb2_grpc.py | 56 - .../videointelligence_v1p2beta1/types.py | 48 - .../videointelligence_v1p3beta1/__init__.py | 51 - .../gapic/__init__.py | 0 .../gapic/enums.py | 107 - ...aming_video_intelligence_service_client.py | 254 - ...ideo_intelligence_service_client_config.py | 28 - .../gapic/transports/__init__.py | 0 ...deo_intelligence_service_grpc_transport.py | 130 - ...deo_intelligence_service_grpc_transport.py | 137 - .../video_intelligence_service_client.py | 308 - ...ideo_intelligence_service_client_config.py | 28 - .../proto/__init__.py | 0 .../proto/video_intelligence.proto | 989 --- .../proto/video_intelligence_pb2.py | 5760 ----------------- .../proto/video_intelligence_pb2_grpc.py | 102 - .../videointelligence_v1p3beta1/types.py | 48 - videointelligence/noxfile.py | 168 - videointelligence/pylint.config.py | 25 - videointelligence/setup.cfg | 3 - videointelligence/setup.py | 86 - videointelligence/synth.metadata | 79 - videointelligence/synth.py | 71 - videointelligence/tests/system.py | 109 - ...st_video_intelligence_service_client_v1.py | 123 - ...deo_intelligence_service_client_v1beta2.py | 123 - ...o_intelligence_service_client_v1p1beta1.py | 123 - ...o_intelligence_service_client_v1p2beta1.py | 123 - ...o_intelligence_service_client_v1p3beta1.py | 115 - ...o_intelligence_service_client_v1p3beta1.py | 123 - vision/.coveragerc | 19 - vision/.flake8 | 14 - vision/.repo-metadata.json | 13 - vision/CHANGELOG.md | 281 - vision/LICENSE | 201 - vision/MANIFEST.in | 5 - vision/README.rst | 112 - vision/docs/README.rst | 1 - vision/docs/_static/custom.css | 4 - vision/docs/_templates/layout.html | 50 - vision/docs/changelog.md | 1 - vision/docs/conf.py | 363 -- vision/docs/gapic/v1/api.rst | 6 - vision/docs/gapic/v1/types.rst | 5 - vision/docs/gapic/v1p2beta1/api.rst | 6 - vision/docs/gapic/v1p2beta1/types.rst | 5 - vision/docs/gapic/v1p3beta1/api.rst | 6 - vision/docs/gapic/v1p3beta1/types.rst | 5 - vision/docs/gapic/v1p4beta1/api.rst | 6 - vision/docs/gapic/v1p4beta1/types.rst | 5 - vision/docs/index.rst | 126 - vision/google/__init__.py | 22 - vision/google/cloud/__init__.py | 22 - vision/google/cloud/vision.py | 22 - .../google/cloud/vision_helpers/__init__.py | 83 - .../google/cloud/vision_helpers/decorators.py | 109 - vision/google/cloud/vision_v1/__init__.py | 51 - .../google/cloud/vision_v1/gapic/__init__.py | 0 vision/google/cloud/vision_v1/gapic/enums.py | 255 - .../vision_v1/gapic/image_annotator_client.py | 594 -- .../gapic/image_annotator_client_config.py | 43 - .../vision_v1/gapic/product_search_client.py | 2026 ------ .../gapic/product_search_client_config.py | 118 - .../vision_v1/gapic/transports/__init__.py | 0 .../image_annotator_grpc_transport.py | 191 - .../product_search_grpc_transport.py | 510 -- .../google/cloud/vision_v1/proto/__init__.py | 0 .../cloud/vision_v1/proto/geometry.proto | 71 - .../cloud/vision_v1/proto/geometry_pb2.py | 371 -- .../vision_v1/proto/geometry_pb2_grpc.py | 2 - .../vision_v1/proto/image_annotator.proto | 1045 --- .../vision_v1/proto/image_annotator_pb2.py | 4929 -------------- .../proto/image_annotator_pb2_grpc.py | 126 - .../vision_v1/proto/product_search.proto | 126 - .../vision_v1/proto/product_search_pb2.py | 644 -- .../proto/product_search_pb2_grpc.py | 2 - .../proto/product_search_service.proto | 1026 --- .../proto/product_search_service_pb2.py | 3340 ---------- .../proto/product_search_service_pb2_grpc.py | 522 -- .../vision_v1/proto/text_annotation.proto | 260 - .../vision_v1/proto/text_annotation_pb2.py | 1139 ---- .../proto/text_annotation_pb2_grpc.py | 2 - .../cloud/vision_v1/proto/web_detection.proto | 107 - .../vision_v1/proto/web_detection_pb2.py | 617 -- .../vision_v1/proto/web_detection_pb2_grpc.py | 2 - vision/google/cloud/vision_v1/types.py | 74 - .../google/cloud/vision_v1p1beta1/__init__.py | 45 - .../cloud/vision_v1p1beta1/gapic/__init__.py | 0 .../cloud/vision_v1p1beta1/gapic/enums.py | 204 - .../gapic/image_annotator_client.py | 247 - .../gapic/image_annotator_client_config.py | 28 - .../gapic/transports/__init__.py | 0 .../image_annotator_grpc_transport.py | 124 - .../cloud/vision_v1p1beta1/proto/__init__.py | 0 .../vision_v1p1beta1/proto/geometry.proto | 53 - .../vision_v1p1beta1/proto/geometry_pb2.py | 270 - .../proto/geometry_pb2_grpc.py | 2 - .../proto/image_annotator.proto | 592 -- .../proto/image_annotator_pb2.py | 2981 --------- .../proto/image_annotator_pb2_grpc.py | 53 - .../proto/product_search.proto | 161 - .../proto/product_search_service.proto | 825 --- .../proto/text_annotation.proto | 252 - .../proto/text_annotation_pb2.py | 1135 ---- .../proto/text_annotation_pb2_grpc.py | 2 - .../proto/web_detection.proto | 104 - .../proto/web_detection_pb2.py | 616 -- .../proto/web_detection_pb2_grpc.py | 2 - vision/google/cloud/vision_v1p1beta1/types.py | 56 - .../google/cloud/vision_v1p2beta1/__init__.py | 45 - .../cloud/vision_v1p2beta1/gapic/__init__.py | 0 .../cloud/vision_v1p2beta1/gapic/enums.py | 228 - .../gapic/image_annotator_client.py | 330 - .../gapic/image_annotator_client_config.py | 33 - .../gapic/transports/__init__.py | 0 .../image_annotator_grpc_transport.py | 150 - .../cloud/vision_v1p2beta1/proto/__init__.py | 0 .../vision_v1p2beta1/proto/geometry.proto | 67 - .../vision_v1p2beta1/proto/geometry_pb2.py | 367 -- .../proto/geometry_pb2_grpc.py | 2 - .../proto/image_annotator.proto | 765 --- .../proto/image_annotator_pb2.py | 3935 ----------- .../proto/image_annotator_pb2_grpc.py | 78 - .../proto/product_search.proto | 161 - .../proto/product_search_service.proto | 825 --- .../proto/text_annotation.proto | 259 - .../proto/text_annotation_pb2.py | 1139 ---- .../proto/text_annotation_pb2_grpc.py | 2 - .../proto/web_detection.proto | 104 - .../proto/web_detection_pb2.py | 616 -- .../proto/web_detection_pb2_grpc.py | 2 - vision/google/cloud/vision_v1p2beta1/types.py | 66 - .../google/cloud/vision_v1p3beta1/__init__.py | 51 - .../cloud/vision_v1p3beta1/gapic/__init__.py | 0 .../cloud/vision_v1p3beta1/gapic/enums.py | 285 - .../gapic/image_annotator_client.py | 334 - .../gapic/image_annotator_client_config.py | 33 - .../gapic/product_search_client.py | 1921 ------ .../gapic/product_search_client_config.py | 113 - .../gapic/transports/__init__.py | 0 .../image_annotator_grpc_transport.py | 150 - .../product_search_grpc_transport.py | 490 -- .../cloud/vision_v1p3beta1/proto/__init__.py | 0 .../vision_v1p3beta1/proto/geometry.proto | 75 - .../vision_v1p3beta1/proto/geometry_pb2.py | 431 -- .../proto/geometry_pb2_grpc.py | 2 - .../proto/image_annotator.proto | 803 --- .../proto/image_annotator_pb2.py | 4177 ------------ .../proto/image_annotator_pb2_grpc.py | 78 - .../proto/product_search.proto | 162 - .../proto/product_search_pb2.py | 713 -- .../proto/product_search_pb2_grpc.py | 2 - .../proto/product_search_service.proto | 842 --- .../proto/product_search_service_pb2.py | 3031 --------- .../proto/product_search_service_pb2_grpc.py | 505 -- .../proto/text_annotation.proto | 259 - .../proto/text_annotation_pb2.py | 1139 ---- .../proto/text_annotation_pb2_grpc.py | 2 - .../proto/web_detection.proto | 104 - .../proto/web_detection_pb2.py | 616 -- .../proto/web_detection_pb2_grpc.py | 2 - vision/google/cloud/vision_v1p3beta1/types.py | 74 - .../google/cloud/vision_v1p4beta1/__init__.py | 51 - .../cloud/vision_v1p4beta1/gapic/__init__.py | 0 .../cloud/vision_v1p4beta1/gapic/enums.py | 255 - .../gapic/image_annotator_client.py | 497 -- .../gapic/image_annotator_client_config.py | 43 - .../gapic/product_search_client.py | 2026 ------ .../gapic/product_search_client_config.py | 118 - .../gapic/transports/__init__.py | 0 .../image_annotator_grpc_transport.py | 191 - .../product_search_grpc_transport.py | 510 -- .../cloud/vision_v1p4beta1/proto/__init__.py | 0 .../cloud/vision_v1p4beta1/proto/face.proto | 61 - .../cloud/vision_v1p4beta1/proto/face_pb2.py | 286 - .../vision_v1p4beta1/proto/face_pb2_grpc.py | 2 - .../vision_v1p4beta1/proto/geometry.proto | 71 - .../vision_v1p4beta1/proto/geometry_pb2.py | 371 -- .../proto/geometry_pb2_grpc.py | 2 - .../proto/image_annotator.proto | 951 --- .../proto/image_annotator_pb2.py | 4764 -------------- .../proto/image_annotator_pb2_grpc.py | 126 - .../proto/product_search.proto | 128 - .../proto/product_search_pb2.py | 643 -- .../proto/product_search_pb2_grpc.py | 2 - .../proto/product_search_service.proto | 1039 --- .../proto/product_search_service_pb2.py | 3339 ---------- .../proto/product_search_service_pb2_grpc.py | 530 -- .../proto/text_annotation.proto | 261 - .../proto/text_annotation_pb2.py | 1139 ---- .../proto/text_annotation_pb2_grpc.py | 2 - .../proto/web_detection.proto | 107 - .../proto/web_detection_pb2.py | 617 -- .../proto/web_detection_pb2_grpc.py | 2 - vision/google/cloud/vision_v1p4beta1/types.py | 76 - vision/noxfile.py | 161 - vision/pylint.config.py | 25 - vision/setup.cfg | 3 - vision/setup.py | 73 - vision/synth.metadata | 643 -- vision/synth.py | 87 - vision/tests/__init__.py | 0 vision/tests/data/faces.jpg | Bin 283497 -> 0 bytes vision/tests/data/logo.png | Bin 21568 -> 0 bytes vision/tests/data/pdf_test.pdf | Bin 15615 -> 0 bytes vision/tests/system.py | 926 --- vision/tests/unit/__init__.py | 0 .../v1/test_image_annotator_client_v1.py | 256 - .../gapic/v1/test_product_search_client_v1.py | 895 --- .../test_image_annotator_client_v1p1beta1.py | 102 - .../test_image_annotator_client_v1p2beta1.py | 159 - .../test_image_annotator_client_v1p3beta1.py | 159 - .../test_product_search_client_v1p3beta1.py | 858 --- .../test_image_annotator_client_v1p4beta1.py | 256 - .../test_product_search_client_v1p4beta1.py | 891 --- vision/tests/unit/test_decorators.py | 112 - vision/tests/unit/test_helpers.py | 129 - 790 files changed, 17 insertions(+), 207905 deletions(-) delete mode 100644 billingbudgets/.coveragerc delete mode 100644 billingbudgets/.flake8 delete mode 100644 billingbudgets/.repo-metadata.json delete mode 100644 billingbudgets/CHANGELOG.md delete mode 100644 billingbudgets/LICENSE delete mode 100644 billingbudgets/MANIFEST.in delete mode 100644 billingbudgets/README.rst delete mode 120000 billingbudgets/docs/README.rst delete mode 100644 billingbudgets/docs/_static/custom.css delete mode 100644 billingbudgets/docs/_templates/layout.html delete mode 120000 billingbudgets/docs/changelog.md delete mode 100644 billingbudgets/docs/conf.py delete mode 100644 billingbudgets/docs/gapic/v1beta1/api.rst delete mode 100644 billingbudgets/docs/gapic/v1beta1/types.rst delete mode 100644 billingbudgets/docs/index.rst delete mode 100644 billingbudgets/google/__init__.py delete mode 100644 billingbudgets/google/cloud/__init__.py delete mode 100644 billingbudgets/google/cloud/billing_budgets.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/__init__.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/__init__.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/enums.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/transports/__init__.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/proto/__init__.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model.proto delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service.proto delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py delete mode 100644 billingbudgets/google/cloud/billing_budgets_v1beta1/types.py delete mode 100644 billingbudgets/noxfile.py delete mode 100644 billingbudgets/setup.cfg delete mode 100644 billingbudgets/setup.py delete mode 100644 billingbudgets/synth.metadata delete mode 100644 billingbudgets/synth.py delete mode 100644 billingbudgets/tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py delete mode 100644 iam/.coveragerc delete mode 100644 iam/.flake8 delete mode 100644 iam/.repo-metadata.json delete mode 100644 iam/CHANGELOG.md delete mode 100644 iam/LICENSE delete mode 100644 iam/MANIFEST.in delete mode 100644 iam/README.rst delete mode 120000 iam/docs/README.rst delete mode 100644 iam/docs/_static/custom.css delete mode 100644 iam/docs/_templates/layout.html delete mode 120000 iam/docs/changelog.md delete mode 100644 iam/docs/conf.py delete mode 100644 iam/docs/gapic/v1/api.rst delete mode 100644 iam/docs/gapic/v1/types.rst delete mode 100644 iam/docs/index.rst delete mode 100644 iam/google/__init__.py delete mode 100644 iam/google/cloud/__init__.py delete mode 100644 iam/google/cloud/iam_credentials.py delete mode 100644 iam/google/cloud/iam_credentials_v1/__init__.py delete mode 100644 iam/google/cloud/iam_credentials_v1/gapic/__init__.py delete mode 100644 iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py delete mode 100644 iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py delete mode 100644 iam/google/cloud/iam_credentials_v1/gapic/transports/__init__.py delete mode 100644 iam/google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py delete mode 100644 iam/google/cloud/iam_credentials_v1/proto/__init__.py delete mode 100644 iam/google/cloud/iam_credentials_v1/proto/common.proto delete mode 100644 iam/google/cloud/iam_credentials_v1/proto/common_pb2.py delete mode 100644 iam/google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py delete mode 100644 iam/google/cloud/iam_credentials_v1/proto/iamcredentials.proto delete mode 100644 iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py delete mode 100644 iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py delete mode 100644 iam/google/cloud/iam_credentials_v1/types.py delete mode 100644 iam/noxfile.py delete mode 100644 iam/setup.cfg delete mode 100644 iam/setup.py delete mode 100644 iam/synth.metadata delete mode 100644 iam/synth.py delete mode 100644 iam/tests/unit/gapic/v1/test_iam_credentials_client_v1.py delete mode 100644 pubsub/.coveragerc delete mode 100644 pubsub/.flake8 delete mode 100644 pubsub/.repo-metadata.json delete mode 100644 pubsub/CHANGELOG.md delete mode 100644 pubsub/LICENSE delete mode 100644 pubsub/MANIFEST.in delete mode 100644 pubsub/README.rst delete mode 120000 pubsub/docs/README.rst delete mode 100644 pubsub/docs/_static/custom.css delete mode 100644 pubsub/docs/_templates/layout.html delete mode 120000 pubsub/docs/changelog.md delete mode 100644 pubsub/docs/conf.py delete mode 100644 pubsub/docs/index.rst delete mode 100644 pubsub/docs/publisher/api/client.rst delete mode 100644 pubsub/docs/publisher/api/futures.rst delete mode 100644 pubsub/docs/publisher/index.rst delete mode 100644 pubsub/docs/subscriber/api/client.rst delete mode 100644 pubsub/docs/subscriber/api/futures.rst delete mode 100644 pubsub/docs/subscriber/api/message.rst delete mode 100644 pubsub/docs/subscriber/api/scheduler.rst delete mode 100644 pubsub/docs/subscriber/index.rst delete mode 100644 pubsub/docs/types.rst delete mode 100644 pubsub/google/__init__.py delete mode 100644 pubsub/google/cloud/__init__.py delete mode 100644 pubsub/google/cloud/pubsub.py delete mode 100644 pubsub/google/cloud/pubsub_v1/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/_gapic.py delete mode 100644 pubsub/google/cloud/pubsub_v1/exceptions.py delete mode 100644 pubsub/google/cloud/pubsub_v1/futures.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/publisher_client.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/publisher_client_config.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/subscriber_client.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/subscriber_client_config.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/transports/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/transports/publisher_grpc_transport.py delete mode 100644 pubsub/google/cloud/pubsub_v1/gapic/transports/subscriber_grpc_transport.py delete mode 100644 pubsub/google/cloud/pubsub_v1/proto/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/proto/pubsub.proto delete mode 100644 pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2.py delete mode 100644 pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2_grpc.py delete mode 100644 pubsub/google/cloud/pubsub_v1/publisher/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/publisher/_batch/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/publisher/_batch/base.py delete mode 100644 pubsub/google/cloud/pubsub_v1/publisher/_batch/thread.py delete mode 100644 pubsub/google/cloud/pubsub_v1/publisher/client.py delete mode 100644 pubsub/google/cloud/pubsub_v1/publisher/exceptions.py delete mode 100644 pubsub/google/cloud/pubsub_v1/publisher/futures.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/__init__.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/dispatcher.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/heartbeater.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/helper_threads.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/histogram.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/leaser.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/requests.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/client.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/futures.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/message.py delete mode 100644 pubsub/google/cloud/pubsub_v1/subscriber/scheduler.py delete mode 100644 pubsub/google/cloud/pubsub_v1/types.py delete mode 100644 pubsub/noxfile.py delete mode 100644 pubsub/pylint.config.py delete mode 100644 pubsub/setup.cfg delete mode 100644 pubsub/setup.py delete mode 100644 pubsub/synth.metadata delete mode 100644 pubsub/synth.py delete mode 100644 pubsub/tests/system.py delete mode 100644 pubsub/tests/system/gapic/v1/test_system_publisher_v1.py delete mode 100644 pubsub/tests/unit/__init__.py delete mode 100644 pubsub/tests/unit/gapic/v1/test_publisher_client_v1.py delete mode 100644 pubsub/tests/unit/gapic/v1/test_subscriber_client_v1.py delete mode 100644 pubsub/tests/unit/pubsub_v1/publisher/batch/test_base.py delete mode 100644 pubsub/tests/unit/pubsub_v1/publisher/batch/test_thread.py delete mode 100644 pubsub/tests/unit/pubsub_v1/publisher/test_futures_publisher.py delete mode 100644 pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_dispatcher.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_futures_subscriber.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_heartbeater.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_helper_threads.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_histogram.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_leaser.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_message.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_scheduler.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_streaming_pull_manager.py delete mode 100644 pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py delete mode 100644 pubsub/tests/unit/pubsub_v1/test__gapic.py delete mode 100644 pubsub/tests/unit/pubsub_v1/test_futures.py delete mode 100644 pubsub/tests/unit/test_pubsub.py delete mode 100644 redis/.coveragerc delete mode 100644 redis/.flake8 delete mode 100644 redis/.repo-metadata.json delete mode 100644 redis/CHANGELOG.md delete mode 100644 redis/LICENSE delete mode 100644 redis/MANIFEST.in delete mode 100644 redis/README.rst delete mode 120000 redis/docs/README.rst delete mode 100644 redis/docs/_static/custom.css delete mode 100644 redis/docs/_templates/layout.html delete mode 100644 redis/docs/conf.py delete mode 100644 redis/docs/gapic/v1/api.rst delete mode 100644 redis/docs/gapic/v1/types.rst delete mode 100644 redis/docs/gapic/v1beta1/api.rst delete mode 100644 redis/docs/gapic/v1beta1/types.rst delete mode 100644 redis/docs/index.rst delete mode 100644 redis/google/__init__.py delete mode 100644 redis/google/cloud/__init__.py delete mode 100644 redis/google/cloud/redis.py delete mode 100644 redis/google/cloud/redis_v1/__init__.py delete mode 100644 redis/google/cloud/redis_v1/gapic/__init__.py delete mode 100644 redis/google/cloud/redis_v1/gapic/cloud_redis_client.py delete mode 100644 redis/google/cloud/redis_v1/gapic/cloud_redis_client_config.py delete mode 100644 redis/google/cloud/redis_v1/gapic/enums.py delete mode 100644 redis/google/cloud/redis_v1/gapic/transports/__init__.py delete mode 100644 redis/google/cloud/redis_v1/gapic/transports/cloud_redis_grpc_transport.py delete mode 100644 redis/google/cloud/redis_v1/proto/__init__.py delete mode 100644 redis/google/cloud/redis_v1/proto/cloud_redis.proto delete mode 100644 redis/google/cloud/redis_v1/proto/cloud_redis_pb2.py delete mode 100644 redis/google/cloud/redis_v1/proto/cloud_redis_pb2_grpc.py delete mode 100644 redis/google/cloud/redis_v1/types.py delete mode 100644 redis/google/cloud/redis_v1beta1/__init__.py delete mode 100644 redis/google/cloud/redis_v1beta1/gapic/__init__.py delete mode 100644 redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client.py delete mode 100644 redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client_config.py delete mode 100644 redis/google/cloud/redis_v1beta1/gapic/enums.py delete mode 100644 redis/google/cloud/redis_v1beta1/gapic/transports/__init__.py delete mode 100644 redis/google/cloud/redis_v1beta1/gapic/transports/cloud_redis_grpc_transport.py delete mode 100644 redis/google/cloud/redis_v1beta1/proto/__init__.py delete mode 100644 redis/google/cloud/redis_v1beta1/proto/cloud_redis.proto delete mode 100644 redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2.py delete mode 100644 redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2_grpc.py delete mode 100644 redis/google/cloud/redis_v1beta1/types.py delete mode 100644 redis/noxfile.py delete mode 100644 redis/setup.cfg delete mode 100644 redis/setup.py delete mode 100644 redis/synth.metadata delete mode 100644 redis/synth.py delete mode 100644 redis/tests/unit/gapic/v1/test_cloud_redis_client_v1.py delete mode 100644 redis/tests/unit/gapic/v1beta1/test_cloud_redis_client_v1beta1.py delete mode 100644 speech/.coveragerc delete mode 100644 speech/.flake8 delete mode 100644 speech/.repo-metadata.json delete mode 100644 speech/CHANGELOG.md delete mode 100644 speech/LICENSE delete mode 100644 speech/MANIFEST.in delete mode 100644 speech/README.rst delete mode 120000 speech/docs/README.rst delete mode 100644 speech/docs/_static/custom.css delete mode 100644 speech/docs/_templates/layout.html delete mode 120000 speech/docs/changelog.md delete mode 100644 speech/docs/conf.py delete mode 100644 speech/docs/gapic/v1/api.rst delete mode 100644 speech/docs/gapic/v1/types.rst delete mode 100644 speech/docs/gapic/v1p1beta1/api.rst delete mode 100644 speech/docs/gapic/v1p1beta1/types.rst delete mode 100644 speech/docs/index.rst delete mode 100644 speech/google/__init__.py delete mode 100644 speech/google/cloud/__init__.py delete mode 100644 speech/google/cloud/speech.py delete mode 100644 speech/google/cloud/speech_v1/__init__.py delete mode 100644 speech/google/cloud/speech_v1/gapic/__init__.py delete mode 100644 speech/google/cloud/speech_v1/gapic/enums.py delete mode 100644 speech/google/cloud/speech_v1/gapic/speech_client.py delete mode 100644 speech/google/cloud/speech_v1/gapic/speech_client_config.py delete mode 100644 speech/google/cloud/speech_v1/gapic/transports/__init__.py delete mode 100644 speech/google/cloud/speech_v1/gapic/transports/speech_grpc_transport.py delete mode 100644 speech/google/cloud/speech_v1/helpers.py delete mode 100644 speech/google/cloud/speech_v1/proto/__init__.py delete mode 100644 speech/google/cloud/speech_v1/proto/cloud_speech.proto delete mode 100644 speech/google/cloud/speech_v1/proto/cloud_speech_pb2.py delete mode 100644 speech/google/cloud/speech_v1/proto/cloud_speech_pb2_grpc.py delete mode 100644 speech/google/cloud/speech_v1/types.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/__init__.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/gapic/__init__.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/gapic/enums.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/gapic/speech_client.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/gapic/speech_client_config.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/gapic/transports/__init__.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/gapic/transports/speech_grpc_transport.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/proto/__init__.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/proto/cloud_speech.proto delete mode 100644 speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2_grpc.py delete mode 100644 speech/google/cloud/speech_v1p1beta1/types.py delete mode 100644 speech/noxfile.py delete mode 100644 speech/pylint.config.py delete mode 100644 speech/samples/resources/brooklyn_bridge.flac delete mode 100644 speech/samples/resources/brooklyn_bridge.mp3 delete mode 100644 speech/samples/resources/brooklyn_bridge.raw delete mode 100644 speech/samples/resources/brooklyn_bridge.wav delete mode 100644 speech/samples/resources/commercial_mono.wav delete mode 100644 speech/samples/resources/hello.raw delete mode 100644 speech/samples/resources/hello.wav delete mode 100644 speech/samples/resources/multi.flac delete mode 100644 speech/samples/resources/multi.wav delete mode 100644 speech/samples/v1/speech_transcribe_async.py delete mode 100644 speech/samples/v1/speech_transcribe_async_gcs.py delete mode 100644 speech/samples/v1/speech_transcribe_async_word_time_offsets_gcs.py delete mode 100644 speech/samples/v1/speech_transcribe_enhanced_model.py delete mode 100644 speech/samples/v1/speech_transcribe_model_selection.py delete mode 100644 speech/samples/v1/speech_transcribe_model_selection_gcs.py delete mode 100644 speech/samples/v1/speech_transcribe_multichannel.py delete mode 100644 speech/samples/v1/speech_transcribe_multichannel_gcs.py delete mode 100644 speech/samples/v1/speech_transcribe_sync.py delete mode 100644 speech/samples/v1/speech_transcribe_sync_gcs.py delete mode 100644 speech/samples/v1/test/samples.manifest.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_async.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_async_gcs.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_async_word_time_offsets_gcs.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_enhanced_model.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_model_selection.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_model_selection_gcs.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_multichannel.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_multichannel_gcs.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_sync.test.yaml delete mode 100644 speech/samples/v1/test/speech_transcribe_sync_gcs.test.yaml delete mode 100644 speech/samples/v1p1beta1/speech_adaptation_beta.py delete mode 100644 speech/samples/v1p1beta1/speech_contexts_classes_beta.py delete mode 100644 speech/samples/v1p1beta1/speech_quickstart_beta.py delete mode 100644 speech/samples/v1p1beta1/speech_transcribe_auto_punctuation_beta.py delete mode 100644 speech/samples/v1p1beta1/speech_transcribe_diarization_beta.py delete mode 100644 speech/samples/v1p1beta1/speech_transcribe_multilanguage_beta.py delete mode 100644 speech/samples/v1p1beta1/speech_transcribe_recognition_metadata_beta.py delete mode 100644 speech/samples/v1p1beta1/speech_transcribe_word_level_confidence_beta.py delete mode 100644 speech/samples/v1p1beta1/test/samples.manifest.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_adaptation_beta.test.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_contexts_classes_beta.test.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_quickstart_beta.test.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_transcribe_auto_punctuation_beta.test.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_transcribe_diarization_beta.test.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_transcribe_multilanguage_beta.test.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_transcribe_recognition_metadata_beta.test.yaml delete mode 100644 speech/samples/v1p1beta1/test/speech_transcribe_word_level_confidence_beta.test.yaml delete mode 100644 speech/setup.cfg delete mode 100644 speech/setup.py delete mode 100644 speech/synth.metadata delete mode 100644 speech/synth.py delete mode 100644 speech/tests/system/gapic/v1/test_system_speech_v1.py delete mode 100644 speech/tests/system/gapic/v1p1beta1/test_system_speech_v1p1beta1.py delete mode 100644 speech/tests/unit/gapic/v1/test_speech_client_v1.py delete mode 100644 speech/tests/unit/gapic/v1p1beta1/test_speech_client_v1p1beta1.py delete mode 100644 speech/tests/unit/test_helpers.py delete mode 100644 talent/.coveragerc delete mode 100644 talent/.flake8 delete mode 100644 talent/.repo-metadata.json delete mode 100644 talent/CHANGELOG.md delete mode 100644 talent/LICENSE delete mode 100644 talent/MANIFEST.in delete mode 100644 talent/README.rst delete mode 120000 talent/docs/README.rst delete mode 100644 talent/docs/_static/custom.css delete mode 100644 talent/docs/_templates/layout.html delete mode 120000 talent/docs/changelog.md delete mode 100644 talent/docs/conf.py delete mode 100644 talent/docs/gapic/v4beta1/api.rst delete mode 100644 talent/docs/gapic/v4beta1/types.rst delete mode 100644 talent/docs/index.rst delete mode 100644 talent/google/__init__.py delete mode 100644 talent/google/cloud/__init__.py delete mode 100644 talent/google/cloud/talent.py delete mode 100644 talent/google/cloud/talent_v4beta1/__init__.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/__init__.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/application_service_client.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/application_service_client_config.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/company_service_client.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/company_service_client_config.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/completion_client.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/completion_client_config.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/enums.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/event_service_client.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/event_service_client_config.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/job_service_client.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/job_service_client_config.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/profile_service_client.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/profile_service_client_config.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/tenant_service_client.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/tenant_service_client_config.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/__init__.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/application_service_grpc_transport.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/company_service_grpc_transport.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/completion_grpc_transport.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/event_service_grpc_transport.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/job_service_grpc_transport.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/profile_service_grpc_transport.py delete mode 100644 talent/google/cloud/talent_v4beta1/gapic/transports/tenant_service_grpc_transport.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/__init__.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/application.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/application_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/application_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/application_service.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/application_service_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/application_service_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/batch.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/batch_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/batch_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/common.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/common_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/common_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/company.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/company_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/company_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/company_service.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/company_service_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/company_service_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/completion_service.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/completion_service_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/completion_service_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/event.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/event_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/event_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/event_service.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/event_service_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/event_service_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/filters.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/filters_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/filters_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/histogram.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/histogram_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/histogram_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/job.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/job_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/job_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/job_service.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/job_service_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/job_service_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/profile.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/profile_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/profile_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/profile_service.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/profile_service_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/profile_service_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/tenant.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/tenant_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/tenant_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/tenant_service.proto delete mode 100644 talent/google/cloud/talent_v4beta1/proto/tenant_service_pb2.py delete mode 100644 talent/google/cloud/talent_v4beta1/proto/tenant_service_pb2_grpc.py delete mode 100644 talent/google/cloud/talent_v4beta1/types.py delete mode 100644 talent/noxfile.py delete mode 100644 talent/setup.cfg delete mode 100644 talent/setup.py delete mode 100644 talent/synth.metadata delete mode 100644 talent/synth.py delete mode 100644 talent/tests/unit/gapic/v4beta1/test_application_service_client_v4beta1.py delete mode 100644 talent/tests/unit/gapic/v4beta1/test_company_service_client_v4beta1.py delete mode 100644 talent/tests/unit/gapic/v4beta1/test_completion_client_v4beta1.py delete mode 100644 talent/tests/unit/gapic/v4beta1/test_event_service_client_v4beta1.py delete mode 100644 talent/tests/unit/gapic/v4beta1/test_job_service_client_v4beta1.py delete mode 100644 talent/tests/unit/gapic/v4beta1/test_profile_service_client_v4beta1.py delete mode 100644 talent/tests/unit/gapic/v4beta1/test_tenant_service_client_v4beta1.py delete mode 100644 trace/.coveragerc delete mode 100644 trace/.flake8 delete mode 100644 trace/.repo-metadata.json delete mode 100644 trace/CHANGELOG.md delete mode 100644 trace/LICENSE delete mode 100644 trace/MANIFEST.in delete mode 100644 trace/PUBLISHING.rst delete mode 100644 trace/README.rst delete mode 120000 trace/docs/README.rst delete mode 100644 trace/docs/_static/custom.css delete mode 100644 trace/docs/_templates/layout.html delete mode 120000 trace/docs/changelog.md delete mode 100644 trace/docs/conf.py delete mode 100644 trace/docs/gapic/v1/api.rst delete mode 100644 trace/docs/gapic/v1/types.rst delete mode 100644 trace/docs/gapic/v2/api.rst delete mode 100644 trace/docs/gapic/v2/types.rst delete mode 100644 trace/docs/index.rst delete mode 100644 trace/docs/starting.html delete mode 100644 trace/google/__init__.py delete mode 100644 trace/google/cloud/__init__.py delete mode 100644 trace/google/cloud/trace.py delete mode 100644 trace/google/cloud/trace/__init__.py delete mode 100644 trace/google/cloud/trace/_gapic.py delete mode 100644 trace/google/cloud/trace/client.py delete mode 100644 trace/google/cloud/trace/v1/__init__.py delete mode 100644 trace/google/cloud/trace/v1/_gapic.py delete mode 100644 trace/google/cloud/trace/v1/client.py delete mode 100644 trace/google/cloud/trace_v1/__init__.py delete mode 100644 trace/google/cloud/trace_v1/gapic/__init__.py delete mode 100644 trace/google/cloud/trace_v1/gapic/enums.py delete mode 100644 trace/google/cloud/trace_v1/gapic/trace_service_client.py delete mode 100644 trace/google/cloud/trace_v1/gapic/trace_service_client_config.py delete mode 100644 trace/google/cloud/trace_v1/gapic/transports/__init__.py delete mode 100644 trace/google/cloud/trace_v1/gapic/transports/trace_service_grpc_transport.py delete mode 100644 trace/google/cloud/trace_v1/proto/__init__.py delete mode 100644 trace/google/cloud/trace_v1/proto/trace.proto delete mode 100644 trace/google/cloud/trace_v1/proto/trace_pb2.py delete mode 100644 trace/google/cloud/trace_v1/proto/trace_pb2_grpc.py delete mode 100644 trace/google/cloud/trace_v1/proto/tracing.proto delete mode 100644 trace/google/cloud/trace_v1/types.py delete mode 100644 trace/google/cloud/trace_v2/__init__.py delete mode 100644 trace/google/cloud/trace_v2/gapic/__init__.py delete mode 100644 trace/google/cloud/trace_v2/gapic/enums.py delete mode 100644 trace/google/cloud/trace_v2/gapic/trace_service_client.py delete mode 100644 trace/google/cloud/trace_v2/gapic/trace_service_client_config.py delete mode 100644 trace/google/cloud/trace_v2/gapic/transports/__init__.py delete mode 100644 trace/google/cloud/trace_v2/gapic/transports/trace_service_grpc_transport.py delete mode 100644 trace/google/cloud/trace_v2/proto/__init__.py delete mode 100644 trace/google/cloud/trace_v2/proto/trace.proto delete mode 100644 trace/google/cloud/trace_v2/proto/trace_pb2.py delete mode 100644 trace/google/cloud/trace_v2/proto/trace_pb2_grpc.py delete mode 100644 trace/google/cloud/trace_v2/proto/tracing.proto delete mode 100644 trace/google/cloud/trace_v2/proto/tracing_pb2.py delete mode 100644 trace/google/cloud/trace_v2/proto/tracing_pb2_grpc.py delete mode 100644 trace/google/cloud/trace_v2/types.py delete mode 100644 trace/noxfile.py delete mode 100644 trace/setup.cfg delete mode 100644 trace/setup.py delete mode 100644 trace/synth.metadata delete mode 100644 trace/synth.py delete mode 100644 trace/tests/__init__.py delete mode 100644 trace/tests/system/gapic/v1/test_system_trace_service_v1.py delete mode 100644 trace/tests/system/gapic/v1/test_system_trace_service_v1_vpcsc.py delete mode 100644 trace/tests/system/gapic/v2/test_system_trace_service_v2.py delete mode 100644 trace/tests/system/gapic/v2/test_system_trace_service_v2_vpcsc.py delete mode 100644 trace/tests/unit/gapic/v1/test_trace_service_client_v1.py delete mode 100644 trace/tests/unit/gapic/v2/test_trace_service_client_v2.py delete mode 100644 trace/tests/unit/v1/test__gapic_v1.py delete mode 100644 trace/tests/unit/v1/test_client_v1.py delete mode 100644 trace/tests/unit/v2/test__gapic_v2.py delete mode 100644 trace/tests/unit/v2/test_client_v2.py delete mode 100644 videointelligence/.coveragerc delete mode 100644 videointelligence/.flake8 delete mode 100644 videointelligence/.repo-metadata.json delete mode 100644 videointelligence/CHANGELOG.md delete mode 100644 videointelligence/LICENSE delete mode 100644 videointelligence/MANIFEST.in delete mode 100644 videointelligence/README.rst delete mode 120000 videointelligence/docs/README.rst delete mode 100644 videointelligence/docs/_static/custom.css delete mode 100644 videointelligence/docs/_templates/layout.html delete mode 120000 videointelligence/docs/changelog.md delete mode 100644 videointelligence/docs/conf.py delete mode 100644 videointelligence/docs/gapic/v1/api.rst delete mode 100644 videointelligence/docs/gapic/v1/types.rst delete mode 100644 videointelligence/docs/gapic/v1beta2/api.rst delete mode 100644 videointelligence/docs/gapic/v1beta2/types.rst delete mode 100644 videointelligence/docs/gapic/v1p1beta1/api.rst delete mode 100644 videointelligence/docs/gapic/v1p1beta1/types.rst delete mode 100644 videointelligence/docs/gapic/v1p2beta1/api.rst delete mode 100644 videointelligence/docs/gapic/v1p2beta1/types.rst delete mode 100644 videointelligence/docs/gapic/v1p3beta1/api.rst delete mode 100644 videointelligence/docs/gapic/v1p3beta1/types.rst delete mode 100644 videointelligence/docs/index.rst delete mode 100644 videointelligence/google/__init__.py delete mode 100644 videointelligence/google/cloud/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/gapic/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/gapic/enums.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/gapic/transports/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/gapic/transports/video_intelligence_service_grpc_transport.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/gapic/video_intelligence_service_client.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/gapic/video_intelligence_service_client_config.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/proto/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/proto/video_intelligence.proto delete mode 100644 videointelligence/google/cloud/videointelligence_v1/proto/video_intelligence_pb2.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/proto/video_intelligence_pb2_grpc.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1/types.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/gapic/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/gapic/enums.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/gapic/transports/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/gapic/transports/video_intelligence_service_grpc_transport.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/gapic/video_intelligence_service_client.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/gapic/video_intelligence_service_client_config.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/proto/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/proto/video_intelligence.proto delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/proto/video_intelligence_pb2.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/proto/video_intelligence_pb2_grpc.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1beta2/types.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/gapic/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/gapic/enums.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/gapic/transports/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/gapic/transports/video_intelligence_service_grpc_transport.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/gapic/video_intelligence_service_client.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/gapic/video_intelligence_service_client_config.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/proto/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/proto/video_intelligence.proto delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/proto/video_intelligence_pb2.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/proto/video_intelligence_pb2_grpc.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p1beta1/types.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/gapic/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/gapic/enums.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/gapic/transports/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/gapic/transports/video_intelligence_service_grpc_transport.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/gapic/video_intelligence_service_client.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/gapic/video_intelligence_service_client_config.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/proto/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/proto/video_intelligence.proto delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/proto/video_intelligence_pb2.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/proto/video_intelligence_pb2_grpc.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p2beta1/types.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/enums.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/streaming_video_intelligence_service_client.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/streaming_video_intelligence_service_client_config.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/transports/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/transports/streaming_video_intelligence_service_grpc_transport.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/transports/video_intelligence_service_grpc_transport.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/video_intelligence_service_client.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/gapic/video_intelligence_service_client_config.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/proto/__init__.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/proto/video_intelligence.proto delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/proto/video_intelligence_pb2.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/proto/video_intelligence_pb2_grpc.py delete mode 100644 videointelligence/google/cloud/videointelligence_v1p3beta1/types.py delete mode 100644 videointelligence/noxfile.py delete mode 100644 videointelligence/pylint.config.py delete mode 100644 videointelligence/setup.cfg delete mode 100644 videointelligence/setup.py delete mode 100644 videointelligence/synth.metadata delete mode 100644 videointelligence/synth.py delete mode 100644 videointelligence/tests/system.py delete mode 100644 videointelligence/tests/unit/gapic/v1/test_video_intelligence_service_client_v1.py delete mode 100644 videointelligence/tests/unit/gapic/v1beta2/test_video_intelligence_service_client_v1beta2.py delete mode 100644 videointelligence/tests/unit/gapic/v1p1beta1/test_video_intelligence_service_client_v1p1beta1.py delete mode 100644 videointelligence/tests/unit/gapic/v1p2beta1/test_video_intelligence_service_client_v1p2beta1.py delete mode 100644 videointelligence/tests/unit/gapic/v1p3beta1/test_streaming_video_intelligence_service_client_v1p3beta1.py delete mode 100644 videointelligence/tests/unit/gapic/v1p3beta1/test_video_intelligence_service_client_v1p3beta1.py delete mode 100644 vision/.coveragerc delete mode 100644 vision/.flake8 delete mode 100644 vision/.repo-metadata.json delete mode 100644 vision/CHANGELOG.md delete mode 100644 vision/LICENSE delete mode 100644 vision/MANIFEST.in delete mode 100644 vision/README.rst delete mode 120000 vision/docs/README.rst delete mode 100644 vision/docs/_static/custom.css delete mode 100644 vision/docs/_templates/layout.html delete mode 120000 vision/docs/changelog.md delete mode 100644 vision/docs/conf.py delete mode 100644 vision/docs/gapic/v1/api.rst delete mode 100644 vision/docs/gapic/v1/types.rst delete mode 100644 vision/docs/gapic/v1p2beta1/api.rst delete mode 100644 vision/docs/gapic/v1p2beta1/types.rst delete mode 100644 vision/docs/gapic/v1p3beta1/api.rst delete mode 100644 vision/docs/gapic/v1p3beta1/types.rst delete mode 100644 vision/docs/gapic/v1p4beta1/api.rst delete mode 100644 vision/docs/gapic/v1p4beta1/types.rst delete mode 100644 vision/docs/index.rst delete mode 100644 vision/google/__init__.py delete mode 100644 vision/google/cloud/__init__.py delete mode 100644 vision/google/cloud/vision.py delete mode 100644 vision/google/cloud/vision_helpers/__init__.py delete mode 100644 vision/google/cloud/vision_helpers/decorators.py delete mode 100644 vision/google/cloud/vision_v1/__init__.py delete mode 100644 vision/google/cloud/vision_v1/gapic/__init__.py delete mode 100644 vision/google/cloud/vision_v1/gapic/enums.py delete mode 100644 vision/google/cloud/vision_v1/gapic/image_annotator_client.py delete mode 100644 vision/google/cloud/vision_v1/gapic/image_annotator_client_config.py delete mode 100644 vision/google/cloud/vision_v1/gapic/product_search_client.py delete mode 100644 vision/google/cloud/vision_v1/gapic/product_search_client_config.py delete mode 100644 vision/google/cloud/vision_v1/gapic/transports/__init__.py delete mode 100644 vision/google/cloud/vision_v1/gapic/transports/image_annotator_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1/gapic/transports/product_search_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1/proto/__init__.py delete mode 100644 vision/google/cloud/vision_v1/proto/geometry.proto delete mode 100644 vision/google/cloud/vision_v1/proto/geometry_pb2.py delete mode 100644 vision/google/cloud/vision_v1/proto/geometry_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1/proto/image_annotator.proto delete mode 100644 vision/google/cloud/vision_v1/proto/image_annotator_pb2.py delete mode 100644 vision/google/cloud/vision_v1/proto/image_annotator_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1/proto/product_search.proto delete mode 100644 vision/google/cloud/vision_v1/proto/product_search_pb2.py delete mode 100644 vision/google/cloud/vision_v1/proto/product_search_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1/proto/product_search_service.proto delete mode 100644 vision/google/cloud/vision_v1/proto/product_search_service_pb2.py delete mode 100644 vision/google/cloud/vision_v1/proto/product_search_service_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1/proto/text_annotation.proto delete mode 100644 vision/google/cloud/vision_v1/proto/text_annotation_pb2.py delete mode 100644 vision/google/cloud/vision_v1/proto/text_annotation_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1/proto/web_detection.proto delete mode 100644 vision/google/cloud/vision_v1/proto/web_detection_pb2.py delete mode 100644 vision/google/cloud/vision_v1/proto/web_detection_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1/types.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/__init__.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/gapic/__init__.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/gapic/enums.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/gapic/image_annotator_client.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/gapic/image_annotator_client_config.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/gapic/transports/__init__.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/gapic/transports/image_annotator_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/__init__.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/geometry.proto delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/geometry_pb2.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/geometry_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/image_annotator.proto delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/image_annotator_pb2.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/image_annotator_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/product_search.proto delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/product_search_service.proto delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/text_annotation.proto delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/text_annotation_pb2.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/text_annotation_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/web_detection.proto delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/web_detection_pb2.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/proto/web_detection_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p1beta1/types.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/__init__.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/gapic/__init__.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/gapic/enums.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/gapic/image_annotator_client.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/gapic/image_annotator_client_config.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/gapic/transports/__init__.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/gapic/transports/image_annotator_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/__init__.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/geometry.proto delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/geometry_pb2.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/geometry_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/image_annotator.proto delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/image_annotator_pb2.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/image_annotator_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/product_search.proto delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/product_search_service.proto delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/text_annotation.proto delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/text_annotation_pb2.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/text_annotation_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/web_detection.proto delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/web_detection_pb2.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/proto/web_detection_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p2beta1/types.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/__init__.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/__init__.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/enums.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/image_annotator_client.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/image_annotator_client_config.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/product_search_client.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/product_search_client_config.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/transports/__init__.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/transports/image_annotator_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/gapic/transports/product_search_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/__init__.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/geometry.proto delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/geometry_pb2.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/geometry_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/image_annotator.proto delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/image_annotator_pb2.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/image_annotator_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/product_search.proto delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/product_search_pb2.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/product_search_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/product_search_service.proto delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/product_search_service_pb2.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/product_search_service_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/text_annotation.proto delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/text_annotation_pb2.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/text_annotation_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/web_detection.proto delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/web_detection_pb2.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/proto/web_detection_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p3beta1/types.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/__init__.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/__init__.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/enums.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/image_annotator_client.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/image_annotator_client_config.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/product_search_client.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/product_search_client_config.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/transports/__init__.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/transports/image_annotator_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/gapic/transports/product_search_grpc_transport.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/__init__.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/face.proto delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/face_pb2.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/face_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/geometry.proto delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/geometry_pb2.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/geometry_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/image_annotator.proto delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/image_annotator_pb2.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/image_annotator_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/product_search.proto delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/product_search_pb2.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/product_search_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/product_search_service.proto delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/product_search_service_pb2.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/product_search_service_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/text_annotation.proto delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/text_annotation_pb2.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/text_annotation_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/web_detection.proto delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/web_detection_pb2.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/proto/web_detection_pb2_grpc.py delete mode 100644 vision/google/cloud/vision_v1p4beta1/types.py delete mode 100644 vision/noxfile.py delete mode 100644 vision/pylint.config.py delete mode 100644 vision/setup.cfg delete mode 100644 vision/setup.py delete mode 100644 vision/synth.metadata delete mode 100644 vision/synth.py delete mode 100644 vision/tests/__init__.py delete mode 100644 vision/tests/data/faces.jpg delete mode 100644 vision/tests/data/logo.png delete mode 100644 vision/tests/data/pdf_test.pdf delete mode 100644 vision/tests/system.py delete mode 100644 vision/tests/unit/__init__.py delete mode 100644 vision/tests/unit/gapic/v1/test_image_annotator_client_v1.py delete mode 100644 vision/tests/unit/gapic/v1/test_product_search_client_v1.py delete mode 100644 vision/tests/unit/gapic/v1p1beta1/test_image_annotator_client_v1p1beta1.py delete mode 100644 vision/tests/unit/gapic/v1p2beta1/test_image_annotator_client_v1p2beta1.py delete mode 100644 vision/tests/unit/gapic/v1p3beta1/test_image_annotator_client_v1p3beta1.py delete mode 100644 vision/tests/unit/gapic/v1p3beta1/test_product_search_client_v1p3beta1.py delete mode 100644 vision/tests/unit/gapic/v1p4beta1/test_image_annotator_client_v1p4beta1.py delete mode 100644 vision/tests/unit/gapic/v1p4beta1/test_product_search_client_v1p4beta1.py delete mode 100644 vision/tests/unit/test_decorators.py delete mode 100644 vision/tests/unit/test_helpers.py diff --git a/README.rst b/README.rst index 063b8fc4ffa9..34b1cfaafe1f 100644 --- a/README.rst +++ b/README.rst @@ -63,7 +63,7 @@ The following client libraries have **GA** support: .. _Natural Language Documentation: https://googleapis.dev/python/language/latest .. _Google Cloud Pub/Sub: https://pypi.org/project/google-cloud-pubsub/ -.. _Pub/Sub README: https://github.com/googleapis/google-cloud-python/tree/master/pubsub +.. _Pub/Sub README: https://github.com/googleapis/python-pubsub .. _Pub/Sub Documentation: https://googleapis.dev/python/pubsub/latest .. _Google Cloud Spanner: https://pypi.org/project/google-cloud-spanner @@ -71,7 +71,7 @@ The following client libraries have **GA** support: .. _Spanner Documentation: https://googleapis.dev/python/spanner/latest .. _Google Cloud Speech to Text: https://pypi.org/project/google-cloud-speech/ -.. _Speech to Text README: https://github.com/googleapis/google-cloud-python/tree/master/speech +.. _Speech to Text README: https://github.com/googleapis/python-speech .. _Speech to Text Documentation: https://googleapis.dev/python/speech/latest .. _Google Cloud Storage: https://pypi.org/project/google-cloud-storage/ @@ -116,7 +116,7 @@ The following client libraries have **beta** support: .. _Asset Documentation: https://googleapis.dev/python/cloudasset/latest .. _Google Cloud Billing Budgets: https://pypi.org/project/google-cloud-billing-budgets/ -.. _Billing Budgets README: https://github.com/googleapis/google-cloud-python/tree/master/billingbudgets +.. _Billing Budgets README: https://github.com/googleapis/python-billingbudgets .. _Billing Budgets Documentation: https://googleapis.dev/python/billingbudgets/latest .. _Google Cloud Data Catalog: https://pypi.org/project/google-cloud-datacatalog/ @@ -132,11 +132,11 @@ The following client libraries have **beta** support: .. _Firestore Documentation: https://googleapis.dev/python/firestore/latest .. _Google Cloud Video Intelligence: https://pypi.org/project/google-cloud-videointelligence -.. _Video Intelligence README: https://github.com/googleapis/google-cloud-python/tree/master/videointelligence +.. _Video Intelligence README: https://github.com/googleapis/python-videointelligence .. _Video Intelligence Documentation: https://googleapis.dev/python/videointelligence/latest .. _Google Cloud Vision: https://pypi.org/project/google-cloud-vision/ -.. _Vision README: https://github.com/googleapis/google-cloud-python/tree/master/vision +.. _Vision README: https://github.com/googleapis/python-vision .. _Vision Documentation: https://googleapis.dev/python/vision/latest @@ -158,12 +158,14 @@ The following client libraries have **alpha** support: - `Google Cloud Dataproc`_ (`Dataproc README`_, `Dataproc Documentation`_) - `Google Cloud DLP`_ (`DLP README`_, `DLP Documentation`_) - `Google Cloud DNS`_ (`DNS README`_, `DNS Documentation`_) +- `Google Cloud IAM`_ (`IAM README`_, `IAM Documentation`_) - `Google Cloud IoT`_ (`IoT README`_, `IoT Documentation`_) - `Google Cloud Memorystore for Redis`_ (`Redis README`_, `Redis Documentation`_) - `Google Cloud Recommender`_ (`Recommender README`_, `Recommender Documentation`_) - `Google Cloud Resource Manager`_ (`Resource Manager README`_, `Resource Manager Documentation`_) - `Google Cloud Runtime Configuration`_ (`Runtime Config README`_, `Runtime Config Documentation`_) - `Google Cloud Security Scanner`_ (`Security Scanner README`_ , `Security Scanner Documentation`_) +- `Google Cloud Talent`_ (`Talent README`_, `Talent Documentation`_) - `Google Cloud Trace`_ (`Trace README`_, `Trace Documentation`_) - `Google Cloud Text-to-Speech`_ (`Text-to-Speech README`_, `Text-to-Speech Documentation`_) - `Grafeas`_ (`Grafeas README`_, `Grafeas Documentation`_) @@ -207,12 +209,16 @@ The following client libraries have **alpha** support: .. _DNS README: https://github.com/googleapis/python-dns#python-client-for-google-cloud-dns .. _DNS Documentation: https://googleapis.dev/python/dns/latest +.. _Google Cloud IAM: https://pypi.org/project/google-cloud-IAM/ +.. _IAM README: https://github.com/googleapis/python-iam +.. _IAM Documentation: https://googleapis.dev/python/iamcredentials/latest + .. _Google Cloud IoT: https://pypi.org/project/google-cloud-iot/ .. _IoT README: https://github.com/googleapis/google-cloud-python/tree/master/iot .. _IoT Documentation: https://googleapis.dev/python/cloudiot/latest .. _Google Cloud Memorystore for Redis: https://pypi.org/project/google-cloud-redis/ -.. _Redis README: https://github.com/googleapis/google-cloud-python/tree/master/redis +.. _Redis README: https://github.com/googleapis/python-redis .. _Redis Documentation: https://googleapis.dev/python/redis/latest .. _Google Cloud Recommender: https://pypi.org/project/google-cloud-recommender/ @@ -231,12 +237,16 @@ The following client libraries have **alpha** support: .. _Security Scanner README: https://github.com/googleapis/google-cloud-python/blob/master/websecurityscanner .. _Security Scanner Documentation: https://googleapis.dev/python/websecurityscanner/latest +.. _Google Cloud Talent: https://pypi.org/project/google-cloud-talent/ +.. _Talent README: https://github.com/googleapis/python-talent +.. _Talent Documentation: https://googleapis.dev/python/talent/latest + .. _Google Cloud Text-to-Speech: https://pypi.org/project/google-cloud-texttospeech/ .. _Text-to-Speech README: https://github.com/googleapis/python-texttospeech#python-client-for-cloud-text-to-speech-api .. _Text-to-Speech Documentation: https://googleapis.dev/python/texttospeech/latest .. _Google Cloud Trace: https://pypi.org/project/google-cloud-trace/ -.. _Trace README: https://github.com/googleapis/google-cloud-python/tree/master/trace +.. _Trace README: https://github.com/googleapis/python-trace .. _Trace Documentation: https://googleapis.dev/python/cloudtrace/latest .. _Grafeas: https://pypi.org/project/grafeas/ diff --git a/billingbudgets/.coveragerc b/billingbudgets/.coveragerc deleted file mode 100644 index b178b094aa1d..000000000000 --- a/billingbudgets/.coveragerc +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[run] -branch = True - -[report] -fail_under = 100 -show_missing = True -exclude_lines = - # Re-enable the standard pragma - pragma: NO COVER - # Ignore debug-only repr - def __repr__ - # Ignore abstract methods - raise NotImplementedError -omit = - */gapic/*.py - */proto/*.py - */core/*.py - */site-packages/*.py \ No newline at end of file diff --git a/billingbudgets/.flake8 b/billingbudgets/.flake8 deleted file mode 100644 index 0268ecc9c55c..000000000000 --- a/billingbudgets/.flake8 +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[flake8] -ignore = E203, E266, E501, W503 -exclude = - # Exclude generated code. - **/proto/** - **/gapic/** - *_pb2.py - - # Standard linting exemptions. - __pycache__, - .git, - *.pyc, - conf.py diff --git a/billingbudgets/.repo-metadata.json b/billingbudgets/.repo-metadata.json deleted file mode 100644 index 40fd90f82168..000000000000 --- a/billingbudgets/.repo-metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "billingbudgets", - "name_pretty": "Cloud Billing Budget", - "product_documentation": "https://cloud.google.com/billing/docs/how-to/budget-api-overview", - "client_documentation": "https://googleapis.dev/python/billingbudgets/latest", - "issue_tracker": "https://issuetracker.google.com/savedsearches/559770", - "release_level": "beta", - "language": "python", - "repo": "googleapis/google-cloud-python", - "distribution_name": "google-cloud-billing-budgets", - "api_id": "billingbudgets.googleapis.com", - "requires_billing": true -} \ No newline at end of file diff --git a/billingbudgets/CHANGELOG.md b/billingbudgets/CHANGELOG.md deleted file mode 100644 index 12330bc55ae9..000000000000 --- a/billingbudgets/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -# Changelog -## 0.2.0 - -12-12-2019 12:36 PST - - -### New Features -- Deprecate resource name helper methods (via synth). ([#9830](https://github.com/googleapis/google-cloud-python/pull/9830)) - -### Internal / Testing Changes -- Add 3.8 unit tests (via synth). ([#9933](https://github.com/googleapis/google-cloud-python/pull/9933)) -- Remove TODOs in proto comments (via synth). ([#9912](https://github.com/googleapis/google-cloud-python/pull/9912)) -- Add comments to proto files (via synth). ([#9854](https://github.com/googleapis/google-cloud-python/pull/9854)) - -## 0.1.0 - -11-15-2019 10:34 PST - -### New Features -- Initial generation of billing budget. ([#9622](https://github.com/googleapis/google-cloud-python/pull/9622)) - -### Documentation -- Add Python 2 sunset banner (via synth). ([#9813](https://github.com/googleapis/google-cloud-python/pull/9813)) - diff --git a/billingbudgets/LICENSE b/billingbudgets/LICENSE deleted file mode 100644 index a8ee855de2aa..000000000000 --- a/billingbudgets/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/billingbudgets/MANIFEST.in b/billingbudgets/MANIFEST.in deleted file mode 100644 index 9cbf175afe6b..000000000000 --- a/billingbudgets/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include README.rst LICENSE -recursive-include google *.json *.proto -recursive-include tests * -global-exclude *.py[co] -global-exclude __pycache__ diff --git a/billingbudgets/README.rst b/billingbudgets/README.rst deleted file mode 100644 index 344135705e20..000000000000 --- a/billingbudgets/README.rst +++ /dev/null @@ -1,77 +0,0 @@ -Python Client for Cloud Billing Budget API (`Alpha`_) -===================================================== - -`Cloud Billing Budget API`_: The Cloud Billing Budget API stores Cloud Billing budgets, which define a -budget plan and the rules to execute as spend is tracked against that -plan. - -- `Client Library Documentation`_ -- `Product Documentation`_ - -.. _Alpha: https://github.com/googleapis/google-cloud-python/blob/master/README.rst -.. _Cloud Billing Budget API: https://cloud.google.com/billing/docs/how-to/budget-api-overview -.. _Client Library Documentation: https://googleapis.dev/python/billingbudgets/latest -.. _Product Documentation: https://cloud.google.com/billing/docs/how-to/budget-api-overview - -Quick Start ------------ - -In order to use this library, you first need to go through the following steps: - -1. `Select or create a Cloud Platform project.`_ -2. `Enable billing for your project.`_ -3. `Enable the Cloud Billing Budget API.`_ -4. `Setup Authentication.`_ - -.. _Select or create a Cloud Platform project.: https://console.cloud.google.com/project -.. _Enable billing for your project.: https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project -.. _Enable the Cloud Billing Budget API.: https://cloud.google.com/billing/docs/how-to/budget-api-overview -.. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html - -Installation -~~~~~~~~~~~~ - -Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to -create isolated Python environments. The basic problem it addresses is one of -dependencies and versions, and indirectly permissions. - -With `virtualenv`_, it's possible to install this library without needing system -install permissions, and without clashing with the installed system -dependencies. - -.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ - - -Mac/Linux -^^^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - source /bin/activate - /bin/pip install google-cloud-billing-budgets - - -Windows -^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - \Scripts\activate - \Scripts\pip.exe install google-cloud-billing-budgets - -Next Steps -~~~~~~~~~~ - -- Read the `Client Library Documentation`_ for Cloud Billing Budget API - API to see other available methods on the client. -- Read the `Cloud Billing Budget API Product documentation`_ to learn - more about the product and see How-to Guides. -- View this `repository’s main README`_ to see the full list of Cloud - APIs that we cover. - -.. _Cloud Billing Budget API Product documentation: https://cloud.google.com/billing/docs/how-to/budget-api-overview -.. _repository’s main README: https://github.com/googleapis/google-cloud-python/blob/master/README.rst \ No newline at end of file diff --git a/billingbudgets/docs/README.rst b/billingbudgets/docs/README.rst deleted file mode 120000 index 89a0106941ff..000000000000 --- a/billingbudgets/docs/README.rst +++ /dev/null @@ -1 +0,0 @@ -../README.rst \ No newline at end of file diff --git a/billingbudgets/docs/_static/custom.css b/billingbudgets/docs/_static/custom.css deleted file mode 100644 index 0abaf229fce3..000000000000 --- a/billingbudgets/docs/_static/custom.css +++ /dev/null @@ -1,4 +0,0 @@ -div#python2-eol { - border-color: red; - border-width: medium; -} \ No newline at end of file diff --git a/billingbudgets/docs/_templates/layout.html b/billingbudgets/docs/_templates/layout.html deleted file mode 100644 index 228529efe2d2..000000000000 --- a/billingbudgets/docs/_templates/layout.html +++ /dev/null @@ -1,50 +0,0 @@ - -{% extends "!layout.html" %} -{%- block content %} -{%- if theme_fixed_sidebar|lower == 'true' %} -
- {{ sidebar() }} - {%- block document %} -
- {%- if render_sidebar %} -
- {%- endif %} - - {%- block relbar_top %} - {%- if theme_show_relbar_top|tobool %} - - {%- endif %} - {% endblock %} - -
-
- On January 1, 2020 this library will no longer support Python 2 on the latest released version. - Previously released library versions will continue to be available. For more information please - visit Python 2 support on Google Cloud. -
- {% block body %} {% endblock %} -
- - {%- block relbar_bottom %} - {%- if theme_show_relbar_bottom|tobool %} - - {%- endif %} - {% endblock %} - - {%- if render_sidebar %} -
- {%- endif %} -
- {%- endblock %} -
-
-{%- else %} -{{ super() }} -{%- endif %} -{%- endblock %} diff --git a/billingbudgets/docs/changelog.md b/billingbudgets/docs/changelog.md deleted file mode 120000 index 04c99a55caae..000000000000 --- a/billingbudgets/docs/changelog.md +++ /dev/null @@ -1 +0,0 @@ -../CHANGELOG.md \ No newline at end of file diff --git a/billingbudgets/docs/conf.py b/billingbudgets/docs/conf.py deleted file mode 100644 index a3933c50cbc5..000000000000 --- a/billingbudgets/docs/conf.py +++ /dev/null @@ -1,363 +0,0 @@ -# -*- coding: utf-8 -*- -# -# google-cloud-billing-budgets documentation build configuration file -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -import shlex - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath("..")) - -__version__ = "0.1.0" - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "1.6.3" - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.intersphinx", - "sphinx.ext.coverage", - "sphinx.ext.napoleon", - "sphinx.ext.todo", - "sphinx.ext.viewcode", -] - -# autodoc/autosummary flags -autoclass_content = "both" -autodoc_default_flags = ["members"] -autosummary_generate = True - - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# Allow markdown includes (so releases.md can include CHANGLEOG.md) -# http://www.sphinx-doc.org/en/master/markdown.html -source_parsers = {".md": "recommonmark.parser.CommonMarkParser"} - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = [".rst", ".md"] - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = u"google-cloud-billing-budgets" -copyright = u"2017, Google" -author = u"Google APIs" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The full version, including alpha/beta/rc tags. -release = __version__ -# The short X.Y version. -version = ".".join(release.split(".")[0:2]) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["_build"] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "alabaster" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = { - "description": "Google Cloud Client Libraries for Python", - "github_user": "googleapis", - "github_repo": "google-cloud-python", - "github_banner": True, - "font_family": "'Roboto', Georgia, sans", - "head_font_family": "'Roboto', Georgia, serif", - "code_font_family": "'Roboto Mono', 'Consolas', monospace", -} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -# html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -# html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = "google-cloud-billing-budgets-doc" - -# -- Options for warnings ------------------------------------------------------ - - -suppress_warnings = [ - # Temporarily suppress this to avoid "more than one target found for - # cross-reference" warning, which are intractable for us to avoid while in - # a mono-repo. - # See https://github.com/sphinx-doc/sphinx/blob - # /2a65ffeef5c107c19084fabdd706cdff3f52d93c/sphinx/domains/python.py#L843 - "ref.python" -] - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - #'preamble': '', - # Latex figure (float) alignment - #'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "google-cloud-billing-budgets.tex", - u"google-cloud-billing-budgets Documentation", - author, - "manual", - ) -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ( - master_doc, - "google-cloud-billing-budgets", - u"google-cloud-billing-budgets Documentation", - [author], - 1, - ) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "google-cloud-billing-budgets", - u"google-cloud-billing-budgets Documentation", - author, - "google-cloud-billing-budgets", - "GAPIC library for the {metadata.shortName} v1beta1 service", - "APIs", - ) -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - "python": ("http://python.readthedocs.org/en/latest/", None), - "gax": ("https://gax-python.readthedocs.org/en/latest/", None), - "google-auth": ("https://google-auth.readthedocs.io/en/stable", None), - "google-gax": ("https://gax-python.readthedocs.io/en/latest/", None), - "google.api_core": ("https://googleapis.dev/python/google-api-core/latest", None), - "grpc": ("https://grpc.io/grpc/python/", None), - "requests": ("https://requests.kennethreitz.org/en/master/", None), - "fastavro": ("https://fastavro.readthedocs.io/en/stable/", None), - "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), -} - - -# Napoleon settings -napoleon_google_docstring = True -napoleon_numpy_docstring = True -napoleon_include_private_with_doc = False -napoleon_include_special_with_doc = True -napoleon_use_admonition_for_examples = False -napoleon_use_admonition_for_notes = False -napoleon_use_admonition_for_references = False -napoleon_use_ivar = False -napoleon_use_param = True -napoleon_use_rtype = True diff --git a/billingbudgets/docs/gapic/v1beta1/api.rst b/billingbudgets/docs/gapic/v1beta1/api.rst deleted file mode 100644 index b1f9f07ec077..000000000000 --- a/billingbudgets/docs/gapic/v1beta1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Cloud Billing Budget API -=================================== - -.. automodule:: google.cloud.billing_budgets_v1beta1 - :members: - :inherited-members: \ No newline at end of file diff --git a/billingbudgets/docs/gapic/v1beta1/types.rst b/billingbudgets/docs/gapic/v1beta1/types.rst deleted file mode 100644 index d25d7a205bc1..000000000000 --- a/billingbudgets/docs/gapic/v1beta1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Cloud Billing Budget API Client -========================================= - -.. automodule:: google.cloud.billing_budgets_v1beta1.types - :members: \ No newline at end of file diff --git a/billingbudgets/docs/index.rst b/billingbudgets/docs/index.rst deleted file mode 100644 index 813764f98353..000000000000 --- a/billingbudgets/docs/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. include:: README.rst - -Api Reference -------------- -.. toctree:: - :maxdepth: 2 - - gapic/v1beta1/api - gapic/v1beta1/types - -Changelog ---------- - -For a list of all ``google-cloud-billing-budgets`` releases: - -.. toctree:: - :maxdepth: 2 - - changelog diff --git a/billingbudgets/google/__init__.py b/billingbudgets/google/__init__.py deleted file mode 100644 index 9a1b64a6d586..000000000000 --- a/billingbudgets/google/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/billingbudgets/google/cloud/__init__.py b/billingbudgets/google/cloud/__init__.py deleted file mode 100644 index 9a1b64a6d586..000000000000 --- a/billingbudgets/google/cloud/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/billingbudgets/google/cloud/billing_budgets.py b/billingbudgets/google/cloud/billing_budgets.py deleted file mode 100644 index 602f2e80266f..000000000000 --- a/billingbudgets/google/cloud/billing_budgets.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import - -from google.cloud.billing_budgets_v1beta1 import BudgetServiceClient -from google.cloud.billing_budgets_v1beta1 import enums -from google.cloud.billing_budgets_v1beta1 import types - - -__all__ = ("enums", "types", "BudgetServiceClient") diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/__init__.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/__init__.py deleted file mode 100644 index 79ad050672d1..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys -import warnings - -from google.cloud.billing_budgets_v1beta1 import types -from google.cloud.billing_budgets_v1beta1.gapic import budget_service_client -from google.cloud.billing_budgets_v1beta1.gapic import enums - - -if sys.version_info[:2] == (2, 7): - message = ( - "A future version of this library will drop support for Python 2.7." - "More details about Python 2 support for Google Cloud Client Libraries" - "can be found at https://cloud.google.com/python/docs/python2-sunset/" - ) - warnings.warn(message, DeprecationWarning) - - -class BudgetServiceClient(budget_service_client.BudgetServiceClient): - __doc__ = budget_service_client.BudgetServiceClient.__doc__ - enums = enums - - -__all__ = ("enums", "types", "BudgetServiceClient") diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/__init__.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py deleted file mode 100644 index 10c13615c805..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py +++ /dev/null @@ -1,618 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.cloud.billing.budgets.v1beta1 BudgetService API.""" - -import functools -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.gapic_v1.routing_header -import google.api_core.grpc_helpers -import google.api_core.page_iterator -import google.api_core.path_template -import grpc - -from google.cloud.billing_budgets_v1beta1.gapic import budget_service_client_config -from google.cloud.billing_budgets_v1beta1.gapic import enums -from google.cloud.billing_budgets_v1beta1.gapic.transports import ( - budget_service_grpc_transport, -) -from google.cloud.billing_budgets_v1beta1.proto import budget_model_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2_grpc -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution( - "google-cloud-billing-budgets" -).version - - -class BudgetServiceClient(object): - """ - BudgetService stores Cloud Billing budgets, which define a - budget plan and rules to execute as we track spend against that plan. - """ - - SERVICE_ADDRESS = "billingbudgets.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.billing.budgets.v1beta1.BudgetService" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - BudgetServiceClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - @classmethod - def billing_account_path(cls, billing_account): - """Return a fully-qualified billing_account string.""" - return google.api_core.path_template.expand( - "billingAccounts/{billing_account}", billing_account=billing_account - ) - - @classmethod - def budget_path(cls, billing_account, budget): - """Return a fully-qualified budget string.""" - return google.api_core.path_template.expand( - "billingAccounts/{billing_account}/budgets/{budget}", - billing_account=billing_account, - budget=budget, - ) - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.BudgetServiceGrpcTransport, - Callable[[~.Credentials, type], ~.BudgetServiceGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = budget_service_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=budget_service_grpc_transport.BudgetServiceGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = budget_service_grpc_transport.BudgetServiceGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def create_budget( - self, - parent, - budget, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Creates a new budget. See - Quotas and limits - for more information on the limits of the number of budgets you can create. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> parent = client.billing_account_path('[BILLING_ACCOUNT]') - >>> - >>> # TODO: Initialize `budget`: - >>> budget = {} - >>> - >>> response = client.create_budget(parent, budget) - - Args: - parent (str): Required. The name of the billing account to create the budget in. - Values are of the form ``billingAccounts/{billingAccountId}``. - budget (Union[dict, ~google.cloud.billing_budgets_v1beta1.types.Budget]): Required. Budget to create. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "create_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "create_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_budget, - default_retry=self._method_configs["CreateBudget"].retry, - default_timeout=self._method_configs["CreateBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.CreateBudgetRequest(parent=parent, budget=budget) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["create_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def update_budget( - self, - budget, - update_mask=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Updates a budget and returns the updated budget. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> # TODO: Initialize `budget`: - >>> budget = {} - >>> - >>> response = client.update_budget(budget) - - Args: - budget (Union[dict, ~google.cloud.billing_budgets_v1beta1.types.Budget]): Required. The updated budget object. - The budget to update is specified by the budget name in the budget. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` - update_mask (Union[dict, ~google.cloud.billing_budgets_v1beta1.types.FieldMask]): Optional. Indicates which fields in the provided budget to update. - Read-only fields (such as ``name``) cannot be changed. If this is not - provided, then only fields with non-default values from the request are - updated. See - https://developers.google.com/protocol-buffers/docs/proto3#default for - more details about default values. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.billing_budgets_v1beta1.types.FieldMask` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "update_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "update_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.update_budget, - default_retry=self._method_configs["UpdateBudget"].retry, - default_timeout=self._method_configs["UpdateBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.UpdateBudgetRequest( - budget=budget, update_mask=update_mask - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("budget.name", budget.name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["update_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def get_budget( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns a budget. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> name = client.budget_path('[BILLING_ACCOUNT]', '[BUDGET]') - >>> - >>> response = client.get_budget(name) - - Args: - name (str): Required. Name of budget to get. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "get_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_budget, - default_retry=self._method_configs["GetBudget"].retry, - default_timeout=self._method_configs["GetBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.GetBudgetRequest(name=name) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def list_budgets( - self, - parent, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns a list of budgets for a billing account. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> parent = client.billing_account_path('[BILLING_ACCOUNT]') - >>> - >>> # Iterate over all results - >>> for element in client.list_budgets(parent): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_budgets(parent).pages: - ... for element in page: - ... # process element - ... pass - - Args: - parent (str): Required. Name of billing account to list budgets under. Values are of - the form ``billingAccounts/{billingAccountId}``. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.PageIterator` instance. - An iterable of :class:`~google.cloud.billing_budgets_v1beta1.types.Budget` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_budgets" not in self._inner_api_calls: - self._inner_api_calls[ - "list_budgets" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_budgets, - default_retry=self._method_configs["ListBudgets"].retry, - default_timeout=self._method_configs["ListBudgets"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.ListBudgetsRequest( - parent=parent, page_size=page_size - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_budgets"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="budgets", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def delete_budget( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Deletes a budget. Returns successfully if already deleted. - - Example: - >>> from google.cloud import billing_budgets_v1beta1 - >>> - >>> client = billing_budgets_v1beta1.BudgetServiceClient() - >>> - >>> name = client.budget_path('[BILLING_ACCOUNT]', '[BUDGET]') - >>> - >>> client.delete_budget(name) - - Args: - name (str): Required. Name of the budget to delete. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "delete_budget" not in self._inner_api_calls: - self._inner_api_calls[ - "delete_budget" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_budget, - default_retry=self._method_configs["DeleteBudget"].retry, - default_timeout=self._method_configs["DeleteBudget"].timeout, - client_info=self._client_info, - ) - - request = budget_service_pb2.DeleteBudgetRequest(name=name) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["delete_budget"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py deleted file mode 100644 index 1987acdea387..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py +++ /dev/null @@ -1,48 +0,0 @@ -config = { - "interfaces": { - "google.cloud.billing.budgets.v1beta1.BudgetService": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "CreateBudget": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "UpdateBudget": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "GetBudget": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "ListBudgets": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "DeleteBudget": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/enums.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/enums.py deleted file mode 100644 index 39ead59afc74..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/enums.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class Filter(object): - class CreditTypesTreatment(enum.IntEnum): - """ - Specifies how credits should be treated when determining spend for - threshold calculations. - - Attributes: - CREDIT_TYPES_TREATMENT_UNSPECIFIED (int) - INCLUDE_ALL_CREDITS (int): All types of credit are subtracted from the gross cost to determine the - spend for threshold calculations. - EXCLUDE_ALL_CREDITS (int): All types of credit are added to the net cost to determine the spend for - threshold calculations. - """ - - CREDIT_TYPES_TREATMENT_UNSPECIFIED = 0 - INCLUDE_ALL_CREDITS = 1 - EXCLUDE_ALL_CREDITS = 2 - - -class ThresholdRule(object): - class Basis(enum.IntEnum): - """ - The type of basis used to determine if spend has passed the threshold. - - Attributes: - BASIS_UNSPECIFIED (int): Unspecified threshold basis. - CURRENT_SPEND (int): Use current spend as the basis for comparison against the threshold. - FORECASTED_SPEND (int): Use forecasted spend for the period as the basis for comparison against - the threshold. - """ - - BASIS_UNSPECIFIED = 0 - CURRENT_SPEND = 1 - FORECASTED_SPEND = 2 diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/transports/__init__.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/transports/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py deleted file mode 100644 index bf49a4d2339f..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py +++ /dev/null @@ -1,178 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers - -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2_grpc - - -class BudgetServiceGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.billing.budgets.v1beta1 BudgetService API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, - channel=None, - credentials=None, - address="billingbudgets.googleapis.com:443", - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = { - "budget_service_stub": budget_service_pb2_grpc.BudgetServiceStub(channel) - } - - @classmethod - def create_channel( - cls, address="billingbudgets.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def create_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.create_budget`. - - Creates a new budget. See - Quotas and limits - for more information on the limits of the number of budgets you can create. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].CreateBudget - - @property - def update_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.update_budget`. - - Updates a budget and returns the updated budget. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].UpdateBudget - - @property - def get_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.get_budget`. - - Returns a budget. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].GetBudget - - @property - def list_budgets(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.list_budgets`. - - Returns a list of budgets for a billing account. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].ListBudgets - - @property - def delete_budget(self): - """Return the gRPC stub for :meth:`BudgetServiceClient.delete_budget`. - - Deletes a budget. Returns successfully if already deleted. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["budget_service_stub"].DeleteBudget diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/__init__.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model.proto b/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model.proto deleted file mode 100644 index 89e96bea21c4..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model.proto +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.cloud.billing.budgets.v1beta1; - -import "google/api/field_behavior.proto"; -import "google/api/resource.proto"; -import "google/type/money.proto"; - -option go_package = "google.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgets"; -option java_multiple_files = true; -option java_package = "com.google.cloud.billing.budgets.v1beta1"; - -// A budget is a plan that describes what you expect to spend on Cloud -// projects, plus the rules to execute as spend is tracked against that plan, -// (for example, send an alert when 90% of the target spend is met). -// Currently all plans are monthly budgets so the usage period(s) tracked are -// implied (calendar months of usage back-to-back). -message Budget { - option (google.api.resource) = { - type: "billingbudgets.googleapis.com/Budget" - pattern: "billingAccounts/{billing_account}/budgets/{budget}" - }; - - // Output only. Resource name of the budget. - // The resource name implies the scope of a budget. Values are of the form - // `billingAccounts/{billingAccountId}/budgets/{budgetId}`. - string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // User data for display name in UI. - // Validation: <= 60 chars. - string display_name = 2; - - // Optional. Filters that define which resources are used to compute - // the actual spend against the budget. - Filter budget_filter = 3 [(google.api.field_behavior) = OPTIONAL]; - - // Required. Budgeted amount. - BudgetAmount amount = 4 [(google.api.field_behavior) = REQUIRED]; - - // Required. Rules that trigger alerts (notifications of thresholds - // being crossed) when spend exceeds the specified percentages of the budget. - repeated ThresholdRule threshold_rules = 5 [(google.api.field_behavior) = REQUIRED]; - - // Optional. Rules to apply to all updates to the actual spend, regardless - // of the thresholds set in `threshold_rules`. - AllUpdatesRule all_updates_rule = 6 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. Etag to validate that the object is unchanged for a - // read-modify-write operation. - // An empty etag will cause an update to overwrite other changes. - string etag = 7 [(google.api.field_behavior) = OPTIONAL]; -} - -// The budgeted amount for each usage period. -message BudgetAmount { - // Specification for what amount to use as the budget. - oneof budget_amount { - // A specified amount to use as the budget. - // `currency_code` is optional. If specified, it must match the - // currency of the billing account. The `currency_code` is provided on - // output. - google.type.Money specified_amount = 1; - - // Use the last period's actual spend as the budget for the present period. - LastPeriodAmount last_period_amount = 2; - } -} - -// Describes a budget amount targeted to last period's spend. -// At this time, the amount is automatically 100% of last period's spend; -// that is, there are no other options yet. -// Future configuration will be described here (for example, configuring a -// percentage of last period's spend). -message LastPeriodAmount { - -} - -// ThresholdRule contains a definition of a threshold which triggers -// an alert (a notification of a threshold being crossed) to be sent when -// spend goes above the specified amount. -// Alerts are automatically e-mailed to users with the Billing Account -// Administrator role or the Billing Account User role. -// The thresholds here have no effect on notifications sent to anything -// configured under `Budget.all_updates_rule`. -message ThresholdRule { - // The type of basis used to determine if spend has passed the threshold. - enum Basis { - // Unspecified threshold basis. - BASIS_UNSPECIFIED = 0; - - // Use current spend as the basis for comparison against the threshold. - CURRENT_SPEND = 1; - - // Use forecasted spend for the period as the basis for comparison against - // the threshold. - FORECASTED_SPEND = 2; - } - - // Required. Send an alert when this threshold is exceeded. - // This is a 1.0-based percentage, so 0.5 = 50%. - // Validation: non-negative number. - double threshold_percent = 1 [(google.api.field_behavior) = REQUIRED]; - - // Optional. The type of basis used to determine if spend has passed the - // threshold. Behavior defaults to CURRENT_SPEND if not set. - Basis spend_basis = 2 [(google.api.field_behavior) = OPTIONAL]; -} - -// AllUpdatesRule defines notifications that are sent on every update to the -// billing account's spend, regardless of the thresholds defined using -// threshold rules. -message AllUpdatesRule { - // Required. The name of the Cloud Pub/Sub topic where budget related messages will be - // published, in the form `projects/{project_id}/topics/{topic_id}`. Updates - // are sent at regular intervals to the topic. - // The topic needs to be created before the budget is created; see - // https://cloud.google.com/billing/docs/how-to/budgets#manage-notifications - // for more details. - // Caller is expected to have - // `pubsub.topics.setIamPolicy` permission on the topic when it's set for a - // budget, otherwise, the API call will fail with PERMISSION_DENIED. See - // https://cloud.google.com/pubsub/docs/access-control for more details on - // Pub/Sub roles and permissions. - string pubsub_topic = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The schema version of the notification. - // Only "1.0" is accepted. It represents the JSON schema as defined in - // https://cloud.google.com/billing/docs/how-to/budgets#notification_format - string schema_version = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// A filter for a budget, limiting the scope of the cost to calculate. -message Filter { - // Specifies how credits should be treated when determining spend for - // threshold calculations. - enum CreditTypesTreatment { - CREDIT_TYPES_TREATMENT_UNSPECIFIED = 0; - - // All types of credit are subtracted from the gross cost to determine the - // spend for threshold calculations. - INCLUDE_ALL_CREDITS = 1; - - // All types of credit are added to the net cost to determine the spend for - // threshold calculations. - EXCLUDE_ALL_CREDITS = 2; - } - - // Optional. A set of projects of the form `projects/{project_id}`, - // specifying that usage from only this set of projects should be - // included in the budget. If omitted, the report will include all usage for - // the billing account, regardless of which project the usage occurred on. - // Only zero or one project can be specified currently. - repeated string projects = 1 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. If not set, default behavior is `INCLUDE_ALL_CREDITS`. - CreditTypesTreatment credit_types_treatment = 4 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. A set of services of the form `services/{service_id}`, - // specifying that usage from only this set of services should be - // included in the budget. If omitted, the report will include usage for - // all the services. - // The service names are available through the Catalog API: - // https://cloud.google.com/billing/v1/how-tos/catalog-api. - repeated string services = 3 [(google.api.field_behavior) = OPTIONAL]; -} diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py deleted file mode 100644 index cac9ce2b0342..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py +++ /dev/null @@ -1,765 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/billing/budgets_v1beta1/proto/budget_model.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 -from google.type import money_pb2 as google_dot_type_dot_money__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/billing/budgets_v1beta1/proto/budget_model.proto", - package="google.cloud.billing.budgets.v1beta1", - syntax="proto3", - serialized_options=_b( - "\n(com.google.cloud.billing.budgets.v1beta1P\001ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgets" - ), - serialized_pb=_b( - '\n=google/cloud/billing/budgets_v1beta1/proto/budget_model.proto\x12$google.cloud.billing.budgets.v1beta1\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x17google/type/money.proto"\xde\x03\n\x06\x42udget\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x03\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12H\n\rbudget_filter\x18\x03 \x01(\x0b\x32,.google.cloud.billing.budgets.v1beta1.FilterB\x03\xe0\x41\x01\x12G\n\x06\x61mount\x18\x04 \x01(\x0b\x32\x32.google.cloud.billing.budgets.v1beta1.BudgetAmountB\x03\xe0\x41\x02\x12Q\n\x0fthreshold_rules\x18\x05 \x03(\x0b\x32\x33.google.cloud.billing.budgets.v1beta1.ThresholdRuleB\x03\xe0\x41\x02\x12S\n\x10\x61ll_updates_rule\x18\x06 \x01(\x0b\x32\x34.google.cloud.billing.budgets.v1beta1.AllUpdatesRuleB\x03\xe0\x41\x01\x12\x11\n\x04\x65tag\x18\x07 \x01(\tB\x03\xe0\x41\x01:]\xea\x41Z\n$billingbudgets.googleapis.com/Budget\x12\x32\x62illingAccounts/{billing_account}/budgets/{budget}"\xa5\x01\n\x0c\x42udgetAmount\x12.\n\x10specified_amount\x18\x01 \x01(\x0b\x32\x12.google.type.MoneyH\x00\x12T\n\x12last_period_amount\x18\x02 \x01(\x0b\x32\x36.google.cloud.billing.budgets.v1beta1.LastPeriodAmountH\x00\x42\x0f\n\rbudget_amount"\x12\n\x10LastPeriodAmount"\xcd\x01\n\rThresholdRule\x12\x1e\n\x11threshold_percent\x18\x01 \x01(\x01\x42\x03\xe0\x41\x02\x12S\n\x0bspend_basis\x18\x02 \x01(\x0e\x32\x39.google.cloud.billing.budgets.v1beta1.ThresholdRule.BasisB\x03\xe0\x41\x01"G\n\x05\x42\x61sis\x12\x15\n\x11\x42\x41SIS_UNSPECIFIED\x10\x00\x12\x11\n\rCURRENT_SPEND\x10\x01\x12\x14\n\x10\x46ORECASTED_SPEND\x10\x02"H\n\x0e\x41llUpdatesRule\x12\x19\n\x0cpubsub_topic\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x1b\n\x0eschema_version\x18\x02 \x01(\tB\x03\xe0\x41\x02"\x90\x02\n\x06\x46ilter\x12\x15\n\x08projects\x18\x01 \x03(\tB\x03\xe0\x41\x01\x12\x66\n\x16\x63redit_types_treatment\x18\x04 \x01(\x0e\x32\x41.google.cloud.billing.budgets.v1beta1.Filter.CreditTypesTreatmentB\x03\xe0\x41\x01\x12\x15\n\x08services\x18\x03 \x03(\tB\x03\xe0\x41\x01"p\n\x14\x43reditTypesTreatment\x12&\n"CREDIT_TYPES_TREATMENT_UNSPECIFIED\x10\x00\x12\x17\n\x13INCLUDE_ALL_CREDITS\x10\x01\x12\x17\n\x13\x45XCLUDE_ALL_CREDITS\x10\x02\x42y\n(com.google.cloud.billing.budgets.v1beta1P\x01ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgetsb\x06proto3' - ), - dependencies=[ - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_api_dot_resource__pb2.DESCRIPTOR, - google_dot_type_dot_money__pb2.DESCRIPTOR, - ], -) - - -_THRESHOLDRULE_BASIS = _descriptor.EnumDescriptor( - name="Basis", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule.Basis", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="BASIS_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="CURRENT_SPEND", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="FORECASTED_SPEND", - index=2, - number=2, - serialized_options=None, - type=None, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=992, - serialized_end=1063, -) -_sym_db.RegisterEnumDescriptor(_THRESHOLDRULE_BASIS) - -_FILTER_CREDITTYPESTREATMENT = _descriptor.EnumDescriptor( - name="CreditTypesTreatment", - full_name="google.cloud.billing.budgets.v1beta1.Filter.CreditTypesTreatment", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="CREDIT_TYPES_TREATMENT_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="INCLUDE_ALL_CREDITS", - index=1, - number=1, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="EXCLUDE_ALL_CREDITS", - index=2, - number=2, - serialized_options=None, - type=None, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1300, - serialized_end=1412, -) -_sym_db.RegisterEnumDescriptor(_FILTER_CREDITTYPESTREATMENT) - - -_BUDGET = _descriptor.Descriptor( - name="Budget", - full_name="google.cloud.billing.budgets.v1beta1.Budget", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.billing.budgets.v1beta1.Budget.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="display_name", - full_name="google.cloud.billing.budgets.v1beta1.Budget.display_name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="budget_filter", - full_name="google.cloud.billing.budgets.v1beta1.Budget.budget_filter", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="amount", - full_name="google.cloud.billing.budgets.v1beta1.Budget.amount", - index=3, - number=4, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="threshold_rules", - full_name="google.cloud.billing.budgets.v1beta1.Budget.threshold_rules", - index=4, - number=5, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="all_updates_rule", - full_name="google.cloud.billing.budgets.v1beta1.Budget.all_updates_rule", - index=5, - number=6, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="etag", - full_name="google.cloud.billing.budgets.v1beta1.Budget.etag", - index=6, - number=7, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b( - "\352AZ\n$billingbudgets.googleapis.com/Budget\0222billingAccounts/{billing_account}/budgets/{budget}" - ), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=189, - serialized_end=667, -) - - -_BUDGETAMOUNT = _descriptor.Descriptor( - name="BudgetAmount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="specified_amount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount.specified_amount", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="last_period_amount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount.last_period_amount", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="budget_amount", - full_name="google.cloud.billing.budgets.v1beta1.BudgetAmount.budget_amount", - index=0, - containing_type=None, - fields=[], - ) - ], - serialized_start=670, - serialized_end=835, -) - - -_LASTPERIODAMOUNT = _descriptor.Descriptor( - name="LastPeriodAmount", - full_name="google.cloud.billing.budgets.v1beta1.LastPeriodAmount", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=837, - serialized_end=855, -) - - -_THRESHOLDRULE = _descriptor.Descriptor( - name="ThresholdRule", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="threshold_percent", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule.threshold_percent", - index=0, - number=1, - type=1, - cpp_type=5, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="spend_basis", - full_name="google.cloud.billing.budgets.v1beta1.ThresholdRule.spend_basis", - index=1, - number=2, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[_THRESHOLDRULE_BASIS], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=858, - serialized_end=1063, -) - - -_ALLUPDATESRULE = _descriptor.Descriptor( - name="AllUpdatesRule", - full_name="google.cloud.billing.budgets.v1beta1.AllUpdatesRule", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="pubsub_topic", - full_name="google.cloud.billing.budgets.v1beta1.AllUpdatesRule.pubsub_topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="schema_version", - full_name="google.cloud.billing.budgets.v1beta1.AllUpdatesRule.schema_version", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1065, - serialized_end=1137, -) - - -_FILTER = _descriptor.Descriptor( - name="Filter", - full_name="google.cloud.billing.budgets.v1beta1.Filter", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="projects", - full_name="google.cloud.billing.budgets.v1beta1.Filter.projects", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="credit_types_treatment", - full_name="google.cloud.billing.budgets.v1beta1.Filter.credit_types_treatment", - index=1, - number=4, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="services", - full_name="google.cloud.billing.budgets.v1beta1.Filter.services", - index=2, - number=3, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[_FILTER_CREDITTYPESTREATMENT], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1140, - serialized_end=1412, -) - -_BUDGET.fields_by_name["budget_filter"].message_type = _FILTER -_BUDGET.fields_by_name["amount"].message_type = _BUDGETAMOUNT -_BUDGET.fields_by_name["threshold_rules"].message_type = _THRESHOLDRULE -_BUDGET.fields_by_name["all_updates_rule"].message_type = _ALLUPDATESRULE -_BUDGETAMOUNT.fields_by_name[ - "specified_amount" -].message_type = google_dot_type_dot_money__pb2._MONEY -_BUDGETAMOUNT.fields_by_name["last_period_amount"].message_type = _LASTPERIODAMOUNT -_BUDGETAMOUNT.oneofs_by_name["budget_amount"].fields.append( - _BUDGETAMOUNT.fields_by_name["specified_amount"] -) -_BUDGETAMOUNT.fields_by_name[ - "specified_amount" -].containing_oneof = _BUDGETAMOUNT.oneofs_by_name["budget_amount"] -_BUDGETAMOUNT.oneofs_by_name["budget_amount"].fields.append( - _BUDGETAMOUNT.fields_by_name["last_period_amount"] -) -_BUDGETAMOUNT.fields_by_name[ - "last_period_amount" -].containing_oneof = _BUDGETAMOUNT.oneofs_by_name["budget_amount"] -_THRESHOLDRULE.fields_by_name["spend_basis"].enum_type = _THRESHOLDRULE_BASIS -_THRESHOLDRULE_BASIS.containing_type = _THRESHOLDRULE -_FILTER.fields_by_name[ - "credit_types_treatment" -].enum_type = _FILTER_CREDITTYPESTREATMENT -_FILTER_CREDITTYPESTREATMENT.containing_type = _FILTER -DESCRIPTOR.message_types_by_name["Budget"] = _BUDGET -DESCRIPTOR.message_types_by_name["BudgetAmount"] = _BUDGETAMOUNT -DESCRIPTOR.message_types_by_name["LastPeriodAmount"] = _LASTPERIODAMOUNT -DESCRIPTOR.message_types_by_name["ThresholdRule"] = _THRESHOLDRULE -DESCRIPTOR.message_types_by_name["AllUpdatesRule"] = _ALLUPDATESRULE -DESCRIPTOR.message_types_by_name["Filter"] = _FILTER -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -Budget = _reflection.GeneratedProtocolMessageType( - "Budget", - (_message.Message,), - dict( - DESCRIPTOR=_BUDGET, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_model_pb2", - __doc__="""A budget is a plan that describes what you expect to spend - on Cloud projects, plus the rules to execute as spend is tracked against - that plan, (for example, send an alert when 90% of the target spend is - met). Currently all plans are monthly budgets so the usage period(s) - tracked are implied (calendar months of usage back-to-back). - - - Attributes: - name: - Output only. Resource name of the budget. The resource name - implies the scope of a budget. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - display_name: - User data for display name in UI. Validation: <= 60 chars. - budget_filter: - Optional. Filters that define which resources are used to - compute the actual spend against the budget. - amount: - Required. Budgeted amount. - threshold_rules: - Required. Rules that trigger alerts (notifications of - thresholds being crossed) when spend exceeds the specified - percentages of the budget. - all_updates_rule: - Optional. Rules to apply to all updates to the actual spend, - regardless of the thresholds set in ``threshold_rules``. - etag: - Optional. Etag to validate that the object is unchanged for a - read-modify-write operation. An empty etag will cause an - update to overwrite other changes. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.Budget) - ), -) -_sym_db.RegisterMessage(Budget) - -BudgetAmount = _reflection.GeneratedProtocolMessageType( - "BudgetAmount", - (_message.Message,), - dict( - DESCRIPTOR=_BUDGETAMOUNT, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_model_pb2", - __doc__="""The budgeted amount for each usage period. - - - Attributes: - budget_amount: - Specification for what amount to use as the budget. - specified_amount: - A specified amount to use as the budget. ``currency_code`` is - optional. If specified, it must match the currency of the - billing account. The ``currency_code`` is provided on output. - last_period_amount: - Use the last period's actual spend as the budget for the - present period. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.BudgetAmount) - ), -) -_sym_db.RegisterMessage(BudgetAmount) - -LastPeriodAmount = _reflection.GeneratedProtocolMessageType( - "LastPeriodAmount", - (_message.Message,), - dict( - DESCRIPTOR=_LASTPERIODAMOUNT, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_model_pb2", - __doc__="""Describes a budget amount targeted to last period's spend. - At this time, the amount is automatically 100% of last period's spend; - that is, there are no other options yet. Future configuration will be - described here (for example, configuring a percentage of last period's - spend). - - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.LastPeriodAmount) - ), -) -_sym_db.RegisterMessage(LastPeriodAmount) - -ThresholdRule = _reflection.GeneratedProtocolMessageType( - "ThresholdRule", - (_message.Message,), - dict( - DESCRIPTOR=_THRESHOLDRULE, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_model_pb2", - __doc__="""ThresholdRule contains a definition of a threshold which - triggers an alert (a notification of a threshold being crossed) to be - sent when spend goes above the specified amount. Alerts are - automatically e-mailed to users with the Billing Account Administrator - role or the Billing Account User role. The thresholds here have no - effect on notifications sent to anything configured under - ``Budget.all_updates_rule``. - - - Attributes: - threshold_percent: - Required. Send an alert when this threshold is exceeded. This - is a 1.0-based percentage, so 0.5 = 50%. Validation: non- - negative number. - spend_basis: - Optional. The type of basis used to determine if spend has - passed the threshold. Behavior defaults to CURRENT\_SPEND if - not set. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.ThresholdRule) - ), -) -_sym_db.RegisterMessage(ThresholdRule) - -AllUpdatesRule = _reflection.GeneratedProtocolMessageType( - "AllUpdatesRule", - (_message.Message,), - dict( - DESCRIPTOR=_ALLUPDATESRULE, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_model_pb2", - __doc__="""AllUpdatesRule defines notifications that are sent on every update to - the billing account's spend, regardless of the thresholds defined using - threshold rules. - - - Attributes: - pubsub_topic: - Required. The name of the Cloud Pub/Sub topic where budget - related messages will be published, in the form - ``projects/{project_id}/topics/{topic_id}``. Updates are sent - at regular intervals to the topic. The topic needs to be - created before the budget is created; see - https://cloud.google.com/billing/docs/how-to/budgets#manage- - notifications for more details. Caller is expected to have - ``pubsub.topics.setIamPolicy`` permission on the topic when - it's set for a budget, otherwise, the API call will fail with - PERMISSION\_DENIED. See - https://cloud.google.com/pubsub/docs/access-control for more - details on Pub/Sub roles and permissions. - schema_version: - Required. The schema version of the notification. Only "1.0" - is accepted. It represents the JSON schema as defined in - https://cloud.google.com/billing/docs/how- - to/budgets#notification\_format - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.AllUpdatesRule) - ), -) -_sym_db.RegisterMessage(AllUpdatesRule) - -Filter = _reflection.GeneratedProtocolMessageType( - "Filter", - (_message.Message,), - dict( - DESCRIPTOR=_FILTER, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_model_pb2", - __doc__="""A filter for a budget, limiting the scope of the cost to - calculate. - - - Attributes: - projects: - Optional. A set of projects of the form - ``projects/{project_id}``, specifying that usage from only - this set of projects should be included in the budget. If - omitted, the report will include all usage for the billing - account, regardless of which project the usage occurred on. - Only zero or one project can be specified currently. - credit_types_treatment: - Optional. If not set, default behavior is - ``INCLUDE_ALL_CREDITS``. - services: - Optional. A set of services of the form - ``services/{service_id}``, specifying that usage from only - this set of services should be included in the budget. If - omitted, the report will include usage for all the services. - The service names are available through the Catalog API: - https://cloud.google.com/billing/v1/how-tos/catalog-api. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.Filter) - ), -) -_sym_db.RegisterMessage(Filter) - - -DESCRIPTOR._options = None -_BUDGET.fields_by_name["name"]._options = None -_BUDGET.fields_by_name["budget_filter"]._options = None -_BUDGET.fields_by_name["amount"]._options = None -_BUDGET.fields_by_name["threshold_rules"]._options = None -_BUDGET.fields_by_name["all_updates_rule"]._options = None -_BUDGET.fields_by_name["etag"]._options = None -_BUDGET._options = None -_THRESHOLDRULE.fields_by_name["threshold_percent"]._options = None -_THRESHOLDRULE.fields_by_name["spend_basis"]._options = None -_ALLUPDATESRULE.fields_by_name["pubsub_topic"]._options = None -_ALLUPDATESRULE.fields_by_name["schema_version"]._options = None -_FILTER.fields_by_name["projects"]._options = None -_FILTER.fields_by_name["credit_types_treatment"]._options = None -_FILTER.fields_by_name["services"]._options = None -# @@protoc_insertion_point(module_scope) diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py deleted file mode 100644 index 07cb78fe03a9..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py +++ /dev/null @@ -1,2 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service.proto b/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service.proto deleted file mode 100644 index d5e0f4bc9a5a..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service.proto +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.cloud.billing.budgets.v1beta1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/api/resource.proto"; -import "google/cloud/billing/budgets/v1beta1/budget_model.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/field_mask.proto"; - -option go_package = "google.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgets"; -option java_multiple_files = true; -option java_package = "com.google.cloud.billing.budgets.v1beta1"; - -// BudgetService stores Cloud Billing budgets, which define a -// budget plan and rules to execute as we track spend against that plan. -service BudgetService { - option (google.api.default_host) = "billingbudgets.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Creates a new budget. See - // Quotas and limits - // for more information on the limits of the number of budgets you can create. - rpc CreateBudget(CreateBudgetRequest) returns (Budget) { - option (google.api.http) = { - post: "/v1beta1/{parent=billingAccounts/*}/budgets" - body: "*" - }; - } - - // Updates a budget and returns the updated budget. - rpc UpdateBudget(UpdateBudgetRequest) returns (Budget) { - option (google.api.http) = { - patch: "/v1beta1/{budget.name=billingAccounts/*/budgets/*}" - body: "*" - }; - } - - // Returns a budget. - rpc GetBudget(GetBudgetRequest) returns (Budget) { - option (google.api.http) = { - get: "/v1beta1/{name=billingAccounts/*/budgets/*}" - }; - } - - // Returns a list of budgets for a billing account. - rpc ListBudgets(ListBudgetsRequest) returns (ListBudgetsResponse) { - option (google.api.http) = { - get: "/v1beta1/{parent=billingAccounts/*}/budgets" - }; - } - - // Deletes a budget. Returns successfully if already deleted. - rpc DeleteBudget(DeleteBudgetRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - delete: "/v1beta1/{name=billingAccounts/*/budgets/*}" - }; - } -} - -// Request for CreateBudget -message CreateBudgetRequest { - // Required. The name of the billing account to create the budget in. Values - // are of the form `billingAccounts/{billingAccountId}`. - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "billingbudgets.googleapis.com/Budget" - } - ]; - - // Required. Budget to create. - Budget budget = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// Request for UpdateBudget -message UpdateBudgetRequest { - // Required. The updated budget object. - // The budget to update is specified by the budget name in the budget. - Budget budget = 1 [(google.api.field_behavior) = REQUIRED]; - - // Optional. Indicates which fields in the provided budget to update. - // Read-only fields (such as `name`) cannot be changed. If this is not - // provided, then only fields with non-default values from the request are - // updated. See - // https://developers.google.com/protocol-buffers/docs/proto3#default for more - // details about default values. - google.protobuf.FieldMask update_mask = 2 [(google.api.field_behavior) = OPTIONAL]; -} - -// Request for GetBudget -message GetBudgetRequest { - // Required. Name of budget to get. Values are of the form - // `billingAccounts/{billingAccountId}/budgets/{budgetId}`. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "billingbudgets.googleapis.com/Budget" - } - ]; -} - -// Request for ListBudgets -message ListBudgetsRequest { - // Required. Name of billing account to list budgets under. Values - // are of the form `billingAccounts/{billingAccountId}`. - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - child_type: "billingbudgets.googleapis.com/Budget" - } - ]; - - // Optional. The maximum number of budgets to return per page. - // The default and maximum value are 100. - int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. The value returned by the last `ListBudgetsResponse` which - // indicates that this is a continuation of a prior `ListBudgets` call, - // and that the system should return the next page of data. - string page_token = 3 [(google.api.field_behavior) = OPTIONAL]; -} - -// Response for ListBudgets -message ListBudgetsResponse { - // List of the budgets owned by the requested billing account. - repeated Budget budgets = 1; - - // If not empty, indicates that there may be more budgets that match the - // request; this value should be passed in a new `ListBudgetsRequest`. - string next_page_token = 2; -} - -// Request for DeleteBudget -message DeleteBudgetRequest { - // Required. Name of the budget to delete. Values are of the form - // `billingAccounts/{billingAccountId}/budgets/{budgetId}`. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "billingbudgets.googleapis.com/Budget" - } - ]; -} diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py deleted file mode 100644 index 37b30941031a..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py +++ /dev/null @@ -1,628 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/billing/budgets_v1beta1/proto/budget_service.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 -from google.cloud.billing_budgets_v1beta1.proto import ( - budget_model_pb2 as google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2, -) -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 -from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/billing/budgets_v1beta1/proto/budget_service.proto", - package="google.cloud.billing.budgets.v1beta1", - syntax="proto3", - serialized_options=_b( - "\n(com.google.cloud.billing.budgets.v1beta1P\001ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgets" - ), - serialized_pb=_b( - '\n?google/cloud/billing/budgets_v1beta1/proto/budget_service.proto\x12$google.cloud.billing.budgets.v1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a=google/cloud/billing/budgets_v1beta1/proto/budget_model.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto"\x96\x01\n\x13\x43reateBudgetRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$billingbudgets.googleapis.com/Budget\x12\x41\n\x06\x62udget\x18\x02 \x01(\x0b\x32,.google.cloud.billing.budgets.v1beta1.BudgetB\x03\xe0\x41\x02"\x8e\x01\n\x13UpdateBudgetRequest\x12\x41\n\x06\x62udget\x18\x01 \x01(\x0b\x32,.google.cloud.billing.budgets.v1beta1.BudgetB\x03\xe0\x41\x02\x12\x34\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMaskB\x03\xe0\x41\x01"N\n\x10GetBudgetRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$billingbudgets.googleapis.com/Budget"\x83\x01\n\x12ListBudgetsRequest\x12<\n\x06parent\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\x12$billingbudgets.googleapis.com/Budget\x12\x16\n\tpage_size\x18\x02 \x01(\x05\x42\x03\xe0\x41\x01\x12\x17\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01"m\n\x13ListBudgetsResponse\x12=\n\x07\x62udgets\x18\x01 \x03(\x0b\x32,.google.cloud.billing.budgets.v1beta1.Budget\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"Q\n\x13\x44\x65leteBudgetRequest\x12:\n\x04name\x18\x01 \x01(\tB,\xe0\x41\x02\xfa\x41&\n$billingbudgets.googleapis.com/Budget2\xc9\x07\n\rBudgetService\x12\xaf\x01\n\x0c\x43reateBudget\x12\x39.google.cloud.billing.budgets.v1beta1.CreateBudgetRequest\x1a,.google.cloud.billing.budgets.v1beta1.Budget"6\x82\xd3\xe4\x93\x02\x30"+/v1beta1/{parent=billingAccounts/*}/budgets:\x01*\x12\xb6\x01\n\x0cUpdateBudget\x12\x39.google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest\x1a,.google.cloud.billing.budgets.v1beta1.Budget"=\x82\xd3\xe4\x93\x02\x37\x32\x32/v1beta1/{budget.name=billingAccounts/*/budgets/*}:\x01*\x12\xa6\x01\n\tGetBudget\x12\x36.google.cloud.billing.budgets.v1beta1.GetBudgetRequest\x1a,.google.cloud.billing.budgets.v1beta1.Budget"3\x82\xd3\xe4\x93\x02-\x12+/v1beta1/{name=billingAccounts/*/budgets/*}\x12\xb7\x01\n\x0bListBudgets\x12\x38.google.cloud.billing.budgets.v1beta1.ListBudgetsRequest\x1a\x39.google.cloud.billing.budgets.v1beta1.ListBudgetsResponse"3\x82\xd3\xe4\x93\x02-\x12+/v1beta1/{parent=billingAccounts/*}/budgets\x12\x96\x01\n\x0c\x44\x65leteBudget\x12\x39.google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest\x1a\x16.google.protobuf.Empty"3\x82\xd3\xe4\x93\x02-*+/v1beta1/{name=billingAccounts/*/budgets/*}\x1aQ\xca\x41\x1d\x62illingbudgets.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformBy\n(com.google.cloud.billing.budgets.v1beta1P\x01ZKgoogle.golang.org/genproto/googleapis/cloud/billing/budgets/v1beta1;budgetsb\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_api_dot_resource__pb2.DESCRIPTOR, - google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2.DESCRIPTOR, - google_dot_protobuf_dot_empty__pb2.DESCRIPTOR, - google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR, - ], -) - - -_CREATEBUDGETREQUEST = _descriptor.Descriptor( - name="CreateBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.CreateBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="parent", - full_name="google.cloud.billing.budgets.v1beta1.CreateBudgetRequest.parent", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A&\022$billingbudgets.googleapis.com/Budget" - ), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="budget", - full_name="google.cloud.billing.budgets.v1beta1.CreateBudgetRequest.budget", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=347, - serialized_end=497, -) - - -_UPDATEBUDGETREQUEST = _descriptor.Descriptor( - name="UpdateBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="budget", - full_name="google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest.budget", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="update_mask", - full_name="google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest.update_mask", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=500, - serialized_end=642, -) - - -_GETBUDGETREQUEST = _descriptor.Descriptor( - name="GetBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.GetBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.billing.budgets.v1beta1.GetBudgetRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A&\n$billingbudgets.googleapis.com/Budget" - ), - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=644, - serialized_end=722, -) - - -_LISTBUDGETSREQUEST = _descriptor.Descriptor( - name="ListBudgetsRequest", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="parent", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest.parent", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A&\022$billingbudgets.googleapis.com/Budget" - ), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_size", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest.page_size", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_token", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsRequest.page_token", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=725, - serialized_end=856, -) - - -_LISTBUDGETSRESPONSE = _descriptor.Descriptor( - name="ListBudgetsResponse", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="budgets", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsResponse.budgets", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="next_page_token", - full_name="google.cloud.billing.budgets.v1beta1.ListBudgetsResponse.next_page_token", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=858, - serialized_end=967, -) - - -_DELETEBUDGETREQUEST = _descriptor.Descriptor( - name="DeleteBudgetRequest", - full_name="google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A&\n$billingbudgets.googleapis.com/Budget" - ), - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=969, - serialized_end=1050, -) - -_CREATEBUDGETREQUEST.fields_by_name[ - "budget" -].message_type = ( - google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET -) -_UPDATEBUDGETREQUEST.fields_by_name[ - "budget" -].message_type = ( - google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET -) -_UPDATEBUDGETREQUEST.fields_by_name[ - "update_mask" -].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK -_LISTBUDGETSRESPONSE.fields_by_name[ - "budgets" -].message_type = ( - google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET -) -DESCRIPTOR.message_types_by_name["CreateBudgetRequest"] = _CREATEBUDGETREQUEST -DESCRIPTOR.message_types_by_name["UpdateBudgetRequest"] = _UPDATEBUDGETREQUEST -DESCRIPTOR.message_types_by_name["GetBudgetRequest"] = _GETBUDGETREQUEST -DESCRIPTOR.message_types_by_name["ListBudgetsRequest"] = _LISTBUDGETSREQUEST -DESCRIPTOR.message_types_by_name["ListBudgetsResponse"] = _LISTBUDGETSRESPONSE -DESCRIPTOR.message_types_by_name["DeleteBudgetRequest"] = _DELETEBUDGETREQUEST -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -CreateBudgetRequest = _reflection.GeneratedProtocolMessageType( - "CreateBudgetRequest", - (_message.Message,), - dict( - DESCRIPTOR=_CREATEBUDGETREQUEST, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_service_pb2", - __doc__="""Request for CreateBudget - - - Attributes: - parent: - Required. The name of the billing account to create the budget - in. Values are of the form - ``billingAccounts/{billingAccountId}``. - budget: - Required. Budget to create. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.CreateBudgetRequest) - ), -) -_sym_db.RegisterMessage(CreateBudgetRequest) - -UpdateBudgetRequest = _reflection.GeneratedProtocolMessageType( - "UpdateBudgetRequest", - (_message.Message,), - dict( - DESCRIPTOR=_UPDATEBUDGETREQUEST, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_service_pb2", - __doc__="""Request for UpdateBudget - - - Attributes: - budget: - Required. The updated budget object. The budget to update is - specified by the budget name in the budget. - update_mask: - Optional. Indicates which fields in the provided budget to - update. Read-only fields (such as ``name``) cannot be changed. - If this is not provided, then only fields with non-default - values from the request are updated. See - https://developers.google.com/protocol- - buffers/docs/proto3#default for more details about default - values. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.UpdateBudgetRequest) - ), -) -_sym_db.RegisterMessage(UpdateBudgetRequest) - -GetBudgetRequest = _reflection.GeneratedProtocolMessageType( - "GetBudgetRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GETBUDGETREQUEST, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_service_pb2", - __doc__="""Request for GetBudget - - - Attributes: - name: - Required. Name of budget to get. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.GetBudgetRequest) - ), -) -_sym_db.RegisterMessage(GetBudgetRequest) - -ListBudgetsRequest = _reflection.GeneratedProtocolMessageType( - "ListBudgetsRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTBUDGETSREQUEST, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_service_pb2", - __doc__="""Request for ListBudgets - - - Attributes: - parent: - Required. Name of billing account to list budgets under. - Values are of the form ``billingAccounts/{billingAccountId}``. - page_size: - Optional. The maximum number of budgets to return per page. - The default and maximum value are 100. - page_token: - Optional. The value returned by the last - ``ListBudgetsResponse`` which indicates that this is a - continuation of a prior ``ListBudgets`` call, and that the - system should return the next page of data. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.ListBudgetsRequest) - ), -) -_sym_db.RegisterMessage(ListBudgetsRequest) - -ListBudgetsResponse = _reflection.GeneratedProtocolMessageType( - "ListBudgetsResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTBUDGETSRESPONSE, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_service_pb2", - __doc__="""Response for ListBudgets - - - Attributes: - budgets: - List of the budgets owned by the requested billing account. - next_page_token: - If not empty, indicates that there may be more budgets that - match the request; this value should be passed in a new - ``ListBudgetsRequest``. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.ListBudgetsResponse) - ), -) -_sym_db.RegisterMessage(ListBudgetsResponse) - -DeleteBudgetRequest = _reflection.GeneratedProtocolMessageType( - "DeleteBudgetRequest", - (_message.Message,), - dict( - DESCRIPTOR=_DELETEBUDGETREQUEST, - __module__="google.cloud.billing.budgets_v1beta1.proto.budget_service_pb2", - __doc__="""Request for DeleteBudget - - - Attributes: - name: - Required. Name of the budget to delete. Values are of the form - ``billingAccounts/{billingAccountId}/budgets/{budgetId}``. - """, - # @@protoc_insertion_point(class_scope:google.cloud.billing.budgets.v1beta1.DeleteBudgetRequest) - ), -) -_sym_db.RegisterMessage(DeleteBudgetRequest) - - -DESCRIPTOR._options = None -_CREATEBUDGETREQUEST.fields_by_name["parent"]._options = None -_CREATEBUDGETREQUEST.fields_by_name["budget"]._options = None -_UPDATEBUDGETREQUEST.fields_by_name["budget"]._options = None -_UPDATEBUDGETREQUEST.fields_by_name["update_mask"]._options = None -_GETBUDGETREQUEST.fields_by_name["name"]._options = None -_LISTBUDGETSREQUEST.fields_by_name["parent"]._options = None -_LISTBUDGETSREQUEST.fields_by_name["page_size"]._options = None -_LISTBUDGETSREQUEST.fields_by_name["page_token"]._options = None -_DELETEBUDGETREQUEST.fields_by_name["name"]._options = None - -_BUDGETSERVICE = _descriptor.ServiceDescriptor( - name="BudgetService", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\035billingbudgets.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=1053, - serialized_end=2022, - methods=[ - _descriptor.MethodDescriptor( - name="CreateBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.CreateBudget", - index=0, - containing_service=None, - input_type=_CREATEBUDGETREQUEST, - output_type=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET, - serialized_options=_b( - '\202\323\344\223\0020"+/v1beta1/{parent=billingAccounts/*}/budgets:\001*' - ), - ), - _descriptor.MethodDescriptor( - name="UpdateBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.UpdateBudget", - index=1, - containing_service=None, - input_type=_UPDATEBUDGETREQUEST, - output_type=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET, - serialized_options=_b( - "\202\323\344\223\002722/v1beta1/{budget.name=billingAccounts/*/budgets/*}:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="GetBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.GetBudget", - index=2, - containing_service=None, - input_type=_GETBUDGETREQUEST, - output_type=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2._BUDGET, - serialized_options=_b( - "\202\323\344\223\002-\022+/v1beta1/{name=billingAccounts/*/budgets/*}" - ), - ), - _descriptor.MethodDescriptor( - name="ListBudgets", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.ListBudgets", - index=3, - containing_service=None, - input_type=_LISTBUDGETSREQUEST, - output_type=_LISTBUDGETSRESPONSE, - serialized_options=_b( - "\202\323\344\223\002-\022+/v1beta1/{parent=billingAccounts/*}/budgets" - ), - ), - _descriptor.MethodDescriptor( - name="DeleteBudget", - full_name="google.cloud.billing.budgets.v1beta1.BudgetService.DeleteBudget", - index=4, - containing_service=None, - input_type=_DELETEBUDGETREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=_b( - "\202\323\344\223\002-*+/v1beta1/{name=billingAccounts/*/budgets/*}" - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_BUDGETSERVICE) - -DESCRIPTOR.services_by_name["BudgetService"] = _BUDGETSERVICE - -# @@protoc_insertion_point(module_scope) diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py deleted file mode 100644 index 3cddb5843873..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py +++ /dev/null @@ -1,125 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.billing_budgets_v1beta1.proto import ( - budget_model_pb2 as google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2, -) -from google.cloud.billing_budgets_v1beta1.proto import ( - budget_service_pb2 as google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2, -) -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 - - -class BudgetServiceStub(object): - """BudgetService stores Cloud Billing budgets, which define a - budget plan and rules to execute as we track spend against that plan. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.CreateBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/CreateBudget", - request_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.CreateBudgetRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.FromString, - ) - self.UpdateBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/UpdateBudget", - request_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.UpdateBudgetRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.FromString, - ) - self.GetBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/GetBudget", - request_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.GetBudgetRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.FromString, - ) - self.ListBudgets = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/ListBudgets", - request_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsResponse.FromString, - ) - self.DeleteBudget = channel.unary_unary( - "/google.cloud.billing.budgets.v1beta1.BudgetService/DeleteBudget", - request_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.DeleteBudgetRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - - -class BudgetServiceServicer(object): - """BudgetService stores Cloud Billing budgets, which define a - budget plan and rules to execute as we track spend against that plan. - """ - - def CreateBudget(self, request, context): - """Creates a new budget. See - Quotas and limits - for more information on the limits of the number of budgets you can create. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def UpdateBudget(self, request, context): - """Updates a budget and returns the updated budget. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetBudget(self, request, context): - """Returns a budget. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ListBudgets(self, request, context): - """Returns a list of budgets for a billing account. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def DeleteBudget(self, request, context): - """Deletes a budget. Returns successfully if already deleted. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_BudgetServiceServicer_to_server(servicer, server): - rpc_method_handlers = { - "CreateBudget": grpc.unary_unary_rpc_method_handler( - servicer.CreateBudget, - request_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.CreateBudgetRequest.FromString, - response_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.SerializeToString, - ), - "UpdateBudget": grpc.unary_unary_rpc_method_handler( - servicer.UpdateBudget, - request_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.UpdateBudgetRequest.FromString, - response_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.SerializeToString, - ), - "GetBudget": grpc.unary_unary_rpc_method_handler( - servicer.GetBudget, - request_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.GetBudgetRequest.FromString, - response_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__model__pb2.Budget.SerializeToString, - ), - "ListBudgets": grpc.unary_unary_rpc_method_handler( - servicer.ListBudgets, - request_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsRequest.FromString, - response_serializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.ListBudgetsResponse.SerializeToString, - ), - "DeleteBudget": grpc.unary_unary_rpc_method_handler( - servicer.DeleteBudget, - request_deserializer=google_dot_cloud_dot_billing_dot_budgets__v1beta1_dot_proto_dot_budget__service__pb2.DeleteBudgetRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.billing.budgets.v1beta1.BudgetService", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/billingbudgets/google/cloud/billing_budgets_v1beta1/types.py b/billingbudgets/google/cloud/billing_budgets_v1beta1/types.py deleted file mode 100644 index 6496b805c829..000000000000 --- a/billingbudgets/google/cloud/billing_budgets_v1beta1/types.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.billing_budgets_v1beta1.proto import budget_model_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 -from google.type import money_pb2 - - -_shared_modules = [empty_pb2, field_mask_pb2, money_pb2] - -_local_modules = [budget_model_pb2, budget_service_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.billing_budgets_v1beta1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/billingbudgets/noxfile.py b/billingbudgets/noxfile.py deleted file mode 100644 index 74dba69dbeeb..000000000000 --- a/billingbudgets/noxfile.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by synthtool. DO NOT EDIT! - -from __future__ import absolute_import -import os -import shutil - -import nox - - -LOCAL_DEPS = (os.path.join("..", "api_core"), os.path.join("..", "core")) -BLACK_VERSION = "black==19.3b0" -BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] - -if os.path.exists("samples"): - BLACK_PATHS.append("samples") - - -@nox.session(python="3.7") -def lint(session): - """Run linters. - - Returns a failure if the linters find linting errors or sufficiently - serious code quality issues. - """ - session.install("flake8", BLACK_VERSION, *LOCAL_DEPS) - session.run("black", "--check", *BLACK_PATHS) - session.run("flake8", "google", "tests") - - -@nox.session(python="3.6") -def blacken(session): - """Run black. - - Format code to uniform standard. - - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. - That run uses an image that doesn't have 3.6 installed. Before updating this - check the state of the `gcp_ubuntu_config` we use for that Kokoro run. - """ - session.install(BLACK_VERSION) - session.run("black", *BLACK_PATHS) - - -@nox.session(python="3.7") -def lint_setup_py(session): - """Verify that setup.py is valid (including RST check).""" - session.install("docutils", "pygments") - session.run("python", "setup.py", "check", "--restructuredtext", "--strict") - - -def default(session): - # Install all test dependencies, then install this package in-place. - session.install("mock", "pytest", "pytest-cov") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", ".") - - # Run py.test against the unit tests. - session.run( - "py.test", - "--quiet", - "--cov=google.cloud", - "--cov=tests.unit", - "--cov-append", - "--cov-config=.coveragerc", - "--cov-report=", - "--cov-fail-under=0", - os.path.join("tests", "unit"), - *session.posargs, - ) - - -@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"]) -def unit(session): - """Run the unit test suite.""" - default(session) - - -@nox.session(python=["2.7", "3.7"]) -def system(session): - """Run the system test suite.""" - system_test_path = os.path.join("tests", "system.py") - system_test_folder_path = os.path.join("tests", "system") - # Sanity check: Only run tests if the environment variable is set. - if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): - session.skip("Credentials must be set via environment variable") - - system_test_exists = os.path.exists(system_test_path) - system_test_folder_exists = os.path.exists(system_test_folder_path) - # Sanity check: only run tests if found. - if not system_test_exists and not system_test_folder_exists: - session.skip("System tests were not found") - - # Use pre-release gRPC for system tests. - session.install("--pre", "grpcio") - - # Install all test dependencies, then install this package into the - # virtualenv's dist-packages. - session.install("mock", "pytest") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", "../test_utils/") - session.install("-e", ".") - - # Run py.test against the system tests. - if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) - if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) - - -@nox.session(python="3.7") -def cover(session): - """Run the final coverage report. - - This outputs the coverage report aggregating coverage from the unit - test runs (not system test runs), and then erases coverage data. - """ - session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=72") - - session.run("coverage", "erase") - - -@nox.session(python="3.7") -def docs(session): - """Build the docs for this library.""" - - session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark") - - shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) - session.run( - "sphinx-build", - "-W", # warnings as errors - "-T", # show full traceback on exception - "-N", # no colors - "-b", - "html", - "-d", - os.path.join("docs", "_build", "doctrees", ""), - os.path.join("docs", ""), - os.path.join("docs", "_build", "html", ""), - ) diff --git a/billingbudgets/setup.cfg b/billingbudgets/setup.cfg deleted file mode 100644 index 3bd555500e37..000000000000 --- a/billingbudgets/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[bdist_wheel] -universal = 1 diff --git a/billingbudgets/setup.py b/billingbudgets/setup.py deleted file mode 100644 index ec56b4976016..000000000000 --- a/billingbudgets/setup.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import io -import os - -import setuptools - - -name = "google-cloud-billing-budgets" -description = "Cloud Billing Budget API API client library" -version = "0.2.0" -release_status = "Development Status :: 3 - Beta" -dependencies = [ - "google-api-core[grpc] >= 1.14.0, < 2.0.0dev", - 'enum34; python_version < "3.4"', -] - - -package_root = os.path.abspath(os.path.dirname(__file__)) - -readme_filename = os.path.join(package_root, "README.rst") -with io.open(readme_filename, encoding="utf-8") as readme_file: - readme = readme_file.read() - -packages = [ - package for package in setuptools.find_packages() if package.startswith("google") -] - -namespaces = ["google"] -if "google.cloud" in packages: - namespaces.append("google.cloud") - - -setuptools.setup( - name=name, - version=version, - description=description, - long_description=readme, - author="Google LLC", - author_email="googleapis-packages@google.com", - license="Apache 2.0", - url="https://github.com/googleapis/google-cloud-python", - classifiers=[ - release_status, - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Operating System :: OS Independent", - "Topic :: Internet", - ], - platforms="Posix; MacOS X; Windows", - packages=packages, - namespace_packages=namespaces, - install_requires=dependencies, - include_package_data=True, - zip_safe=False, -) diff --git a/billingbudgets/synth.metadata b/billingbudgets/synth.metadata deleted file mode 100644 index 98bbfd8447b1..000000000000 --- a/billingbudgets/synth.metadata +++ /dev/null @@ -1,159 +0,0 @@ -{ - "updateTime": "2020-01-29T13:18:37.536635Z", - "sources": [ - { - "generator": { - "name": "artman", - "version": "0.44.4", - "dockerImage": "googleapis/artman@sha256:19e945954fc960a4bdfee6cb34695898ab21a8cf0bac063ee39b91f00a1faec8" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "cf3b61102ed5f36b827bc82ec39be09525f018c8", - "internalRef": "292034635", - "log": "cf3b61102ed5f36b827bc82ec39be09525f018c8\n Fix to protos for v1p1beta1 release of Cloud Security Command Center\n\nPiperOrigin-RevId: 292034635\n\n4e1cfaa7c0fede9e65d64213ca3da1b1255816c0\nUpdate the public proto to support UTF-8 encoded id for CatalogService API, increase the ListCatalogItems deadline to 300s and some minor documentation change\n\nPiperOrigin-RevId: 292030970\n\n9c483584f8fd5a1b862ae07973f4cc7bb3e46648\nasset: add annotations to v1p1beta1\n\nPiperOrigin-RevId: 292009868\n\ne19209fac29731d0baf6d9ac23da1164f7bdca24\nAdd the google.rpc.context.AttributeContext message to the open source\ndirectories.\n\nPiperOrigin-RevId: 291999930\n\nae5662960573f279502bf98a108a35ba1175e782\noslogin API: move file level option on top of the file to avoid protobuf.js bug.\n\nPiperOrigin-RevId: 291990506\n\neba3897fff7c49ed85d3c47fc96fe96e47f6f684\nAdd cc_proto_library and cc_grpc_library targets for Spanner and IAM protos.\n\nPiperOrigin-RevId: 291988651\n\n8e981acfd9b97ea2f312f11bbaa7b6c16e412dea\nBeta launch for PersonDetection and FaceDetection features.\n\nPiperOrigin-RevId: 291821782\n\n994e067fae3b21e195f7da932b08fff806d70b5d\nasset: add annotations to v1p2beta1\n\nPiperOrigin-RevId: 291815259\n\n244e1d2c89346ca2e0701b39e65552330d68545a\nAdd Playable Locations service\n\nPiperOrigin-RevId: 291806349\n\n909f8f67963daf45dd88d020877fb9029b76788d\nasset: add annotations to v1beta2\n\nPiperOrigin-RevId: 291805301\n\n3c39a1d6e23c1ef63c7fba4019c25e76c40dfe19\nKMS: add file-level message for CryptoKeyPath, it is defined in gapic yaml but not\nin proto files.\n\nPiperOrigin-RevId: 291420695\n\nc6f3f350b8387f8d1b85ed4506f30187ebaaddc3\ncontaineranalysis: update v1beta1 and bazel build with annotations\n\nPiperOrigin-RevId: 291401900\n\n92887d74b44e4e636252b7b8477d0d2570cd82db\nfix: fix the location of grpc config file.\n\nPiperOrigin-RevId: 291396015\n\ne26cab8afd19d396b929039dac5d874cf0b5336c\nexpr: add default_host and method_signature annotations to CelService\n\nPiperOrigin-RevId: 291240093\n\n06093ae3952441c34ec176d1f7431b8765cec0be\nirm: fix v1alpha2 bazel build by adding missing proto imports\n\nPiperOrigin-RevId: 291227940\n\na8a2514af326e4673063f9a3c9d0ef1091c87e6c\nAdd proto annotation for cloud/irm API\n\nPiperOrigin-RevId: 291217859\n\n8d16f76de065f530d395a4c7eabbf766d6a120fd\nGenerate Memcache v1beta2 API protos and gRPC ServiceConfig files\n\nPiperOrigin-RevId: 291008516\n\n3af1dabd93df9a9f17bf3624d3b875c11235360b\ngrafeas: Add containeranalysis default_host to Grafeas service\n\nPiperOrigin-RevId: 290965849\n\nbe2663fa95e31cba67d0cd62611a6674db9f74b7\nfix(google/maps/roads): add missing opening bracket\n\nPiperOrigin-RevId: 290964086\n\nfacc26550a0af0696e0534bc9cae9df14275aa7c\nUpdating v2 protos with the latest inline documentation (in comments) and adding a per-service .yaml file.\n\nPiperOrigin-RevId: 290952261\n\ncda99c1f7dc5e4ca9b1caeae1dc330838cbc1461\nChange api_name to 'asset' for v1p1beta1\n\nPiperOrigin-RevId: 290800639\n\n94e9e90c303a820ce40643d9129e7f0d2054e8a1\nAdds Google Maps Road service\n\nPiperOrigin-RevId: 290795667\n\na3b23dcb2eaecce98c600c7d009451bdec52dbda\nrpc: new message ErrorInfo, other comment updates\n\nPiperOrigin-RevId: 290781668\n\n26420ef4e46c37f193c0fbe53d6ebac481de460e\nAdd proto definition for Org Policy v1.\n\nPiperOrigin-RevId: 290771923\n\n7f0dab8177cf371ae019a082e2512de7ac102888\nPublish Routes Preferred API v1 service definitions.\n\nPiperOrigin-RevId: 290326986\n\nad6e508d0728e1d1bca6e3f328cd562718cb772d\nFix: Qualify resource type references with \"jobs.googleapis.com/\"\n\nPiperOrigin-RevId: 290285762\n\n58e770d568a2b78168ddc19a874178fee8265a9d\ncts client library\n\nPiperOrigin-RevId: 290146169\n\naf9daa4c3b4c4a8b7133b81588dd9ffd37270af2\nAdd more programming language options to public proto\n\nPiperOrigin-RevId: 290144091\n\nd9f2bbf2df301ef84641d4cec7c828736a0bd907\ntalent: add missing resource.proto dep to Bazel build target\n\nPiperOrigin-RevId: 290143164\n\n3b3968237451d027b42471cd28884a5a1faed6c7\nAnnotate Talent API.\nAdd gRPC service config for retry.\nUpdate bazel file with google.api.resource dependency.\n\nPiperOrigin-RevId: 290125172\n\n0735b4b096872960568d1f366bfa75b7b0e1f1a3\nWeekly library update.\n\nPiperOrigin-RevId: 289939042\n\n8760d3d9a4543d7f9c0d1c7870aca08b116e4095\nWeekly library update.\n\nPiperOrigin-RevId: 289939020\n\n8607df842f782a901805187e02fff598145b0b0e\nChange Talent API timeout to 30s.\n\nPiperOrigin-RevId: 289912621\n\n908155991fe32570653bcb72ecfdcfc896642f41\nAdd Recommendations AI V1Beta1\n\nPiperOrigin-RevId: 289901914\n\n5c9a8c2bebd8b71aa66d1cc473edfaac837a2c78\nAdding no-arg method signatures for ListBillingAccounts and ListServices\n\nPiperOrigin-RevId: 289891136\n\n50b0e8286ac988b0593bd890eb31fef6ea2f5767\nlongrunning: add grpc service config and default_host annotation to operations.proto\n\nPiperOrigin-RevId: 289876944\n\n6cac27dabe51c54807b0401698c32d34998948a9\n Updating default deadline for Cloud Security Command Center's v1 APIs.\n\nPiperOrigin-RevId: 289875412\n\nd99df0d67057a233c711187e0689baa4f8e6333d\nFix: Correct spelling in C# namespace option\n\nPiperOrigin-RevId: 289709813\n\n2fa8d48165cc48e35b0c62e6f7bdade12229326c\nfeat: Publish Recommender v1 to GitHub.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289619243\n\n9118db63d1ab493a2e44a3b4973fde810a835c49\nfirestore: don't retry reads that fail with Aborted\n\nFor transaction reads that fail with ABORTED, we need to rollback and start a new transaction. Our current configuration makes it so that GAPIC retries ABORTED reads multiple times without making any progress. Instead, we should retry at the transaction level.\n\nPiperOrigin-RevId: 289532382\n\n1dbfd3fe4330790b1e99c0bb20beb692f1e20b8a\nFix bazel build\nAdd other langauges (Java was already there) for bigquery/storage/v1alpha2 api.\n\nPiperOrigin-RevId: 289519766\n\nc06599cdd7d11f8d3fd25f8d3249e5bb1a3d5d73\nInitial commit of google.cloud.policytroubleshooter API, The API helps in troubleshooting GCP policies. Refer https://cloud.google.com/iam/docs/troubleshooting-access for more information\n\nPiperOrigin-RevId: 289491444\n\nfce7d80fa16ea241e87f7bc33d68595422e94ecd\nDo not pass samples option for Artman config of recommender v1 API.\n\nPiperOrigin-RevId: 289477403\n\nef179e8c61436297e6bb124352e47e45c8c80cb1\nfix: Address missing Bazel dependency.\n\nBazel builds stopped working in 06ec6d5 because\nthe google/longrunning/operations.proto file took\nan import from google/api/client.proto, but that\nimport was not added to BUILD.bazel.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289446074\n\n8841655b242c84fd691d77d7bcf21b61044f01ff\nMigrate Data Labeling v1beta1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289446026\n\n06ec6d5d053fff299eaa6eaa38afdd36c5e2fc68\nAdd annotations to google.longrunning.v1\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289413169\n\n0480cf40be1d3cc231f4268a2fdb36a8dd60e641\nMigrate IAM Admin v1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289411084\n\n1017173e9adeb858587639af61889ad970c728b1\nSpecify a C# namespace for BigQuery Connection v1beta1\n\nPiperOrigin-RevId: 289396763\n\nb08714b378e8e5b0c4ecdde73f92c36d6303b4b6\nfix: Integrate latest proto-docs-plugin fix.\nFixes dialogflow v2\n\nPiperOrigin-RevId: 289189004\n\n51217a67e79255ee1f2e70a6a3919df082513327\nCreate BUILD file for recommender v1\n\nPiperOrigin-RevId: 289183234\n\nacacd87263c0a60e458561b8b8ce9f67c760552a\nGenerate recommender v1 API protos and gRPC ServiceConfig files\n\nPiperOrigin-RevId: 289177510\n\n9d2f7133b97720b1fa3601f6dcd30760ba6d8a1e\nFix kokoro build script\n\nPiperOrigin-RevId: 289166315\n\nc43a67530d2a47a0220cad20ca8de39b3fbaf2c5\ncloudtasks: replace missing RPC timeout config for v2beta2 and v2beta3\n\nPiperOrigin-RevId: 289162391\n\n4cefc229a9197236fc0adf02d69b71c0c5cf59de\nSynchronize new proto/yaml changes.\n\nPiperOrigin-RevId: 289158456\n\n56f263fe959c50786dab42e3c61402d32d1417bd\nCatalog API: Adding config necessary to build client libraries\n\nPiperOrigin-RevId: 289149879\n\n4543762b23a57fc3c53d409efc3a9affd47b6ab3\nFix Bazel build\nbilling/v1 and dialogflow/v2 remain broken (not bazel-related issues).\nBilling has wrong configuration, dialogflow failure is caused by a bug in documentation plugin.\n\nPiperOrigin-RevId: 289140194\n\nc9dce519127b97e866ca133a01157f4ce27dcceb\nUpdate Bigtable docs\n\nPiperOrigin-RevId: 289114419\n\n802c5c5f2bf94c3facb011267d04e71942e0d09f\nMigrate DLP to proto annotations (but not GAPIC v2).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289102579\n\n6357f30f2ec3cff1d8239d18b707ff9d438ea5da\nRemove gRPC configuration file that was in the wrong place.\n\nPiperOrigin-RevId: 289096111\n\n360a8792ed62f944109d7e22d613a04a010665b4\n Protos for v1p1beta1 release of Cloud Security Command Center\n\nPiperOrigin-RevId: 289011995\n\na79211c20c4f2807eec524d00123bf7c06ad3d6e\nRoll back containeranalysis v1 to GAPIC v1.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288999068\n\n9e60345ba603e03484a8aaa33ce5ffa19c1c652b\nPublish Routes Preferred API v1 proto definitions.\n\nPiperOrigin-RevId: 288941399\n\nd52885b642ad2aa1f42b132ee62dbf49a73e1e24\nMigrate the service management API to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288909426\n\n6ace586805c08896fef43e28a261337fcf3f022b\ncloudtasks: replace missing RPC timeout config\n\nPiperOrigin-RevId: 288783603\n\n51d906cabee4876b12497054b15b05d4a50ad027\nImport of Grafeas from Github.\n\nUpdate BUILD.bazel accordingly.\n\nPiperOrigin-RevId: 288783426\n\n5ef42bcd363ba0440f0ee65b3c80b499e9067ede\nMigrate Recommender v1beta1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288713066\n\n94f986afd365b7d7e132315ddcd43d7af0e652fb\nMigrate Container Analysis v1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288708382\n\n7a751a279184970d3b6ba90e4dd4d22a382a0747\nRemove Container Analysis v1alpha1 (nobody publishes it).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288707473\n\n3c0d9c71242e70474b2b640e15bb0a435fd06ff0\nRemove specious annotation from BigQuery Data Transfer before\nanyone accidentally does anything that uses it.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288701604\n\n1af307a4764bd415ef942ac5187fa1def043006f\nMigrate BigQuery Connection to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288698681\n\n08b488e0660c59842a7dee0e3e2b65d9e3a514a9\nExposing cloud_catalog.proto (This API is already available through REST)\n\nPiperOrigin-RevId: 288625007\n\na613482977e11ac09fa47687a5d1b5a01efcf794\nUpdate the OS Login v1beta API description to render better in the UI.\n\nPiperOrigin-RevId: 288547940\n\n5e182b8d9943f1b17008d69d4c7e865dc83641a7\nUpdate the OS Login API description to render better in the UI.\n\nPiperOrigin-RevId: 288546443\n\ncb79155f596e0396dd900da93872be7066f6340d\nFix: Add a resource annotation for Agent\nFix: Correct the service name in annotations for Intent and SessionEntityType\n\nPiperOrigin-RevId: 288441307\n\nf7f6e9daec3315fd47cb638789bd8415bf4a27cc\nAdded cloud asset api v1p1beta1\n\nPiperOrigin-RevId: 288427239\n\nf2880f5b342c6345f3dcaad24fcb3c6ca9483654\nBilling account API: Adding config necessary to build client libraries\n\nPiperOrigin-RevId: 288351810\n\ndc250ffe071729f8f8bef9d6fd0fbbeb0254c666\nFix: Remove incorrect resource annotations in requests\n\nPiperOrigin-RevId: 288321208\n\n91ef2d9dd69807b0b79555f22566fb2d81e49ff9\nAdd GAPIC annotations to Cloud KMS (but do not migrate the GAPIC config yet).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 287999179\n\n" - } - }, - { - "template": { - "name": "python_library", - "origin": "synthtool.gcp", - "version": "2019.10.17" - } - } - ], - "destinations": [ - { - "client": { - "source": "googleapis", - "apiName": "billingbudgets", - "apiVersion": "v1beta1", - "language": "python", - "generator": "gapic", - "config": "google/cloud/billing/budgets/artman_billingbudgets_v1beta1.yaml" - } - } - ], - "newFiles": [ - { - "path": ".coveragerc" - }, - { - "path": ".flake8" - }, - { - "path": ".repo-metadata.json" - }, - { - "path": "CHANGELOG.md" - }, - { - "path": "LICENSE" - }, - { - "path": "MANIFEST.in" - }, - { - "path": "README.rst" - }, - { - "path": "docs/README.rst" - }, - { - "path": "docs/_static/custom.css" - }, - { - "path": "docs/_templates/layout.html" - }, - { - "path": "docs/changelog.md" - }, - { - "path": "docs/conf.py" - }, - { - "path": "docs/gapic/v1beta1/api.rst" - }, - { - "path": "docs/gapic/v1beta1/types.rst" - }, - { - "path": "docs/index.rst" - }, - { - "path": "google/__init__.py" - }, - { - "path": "google/cloud/__init__.py" - }, - { - "path": "google/cloud/billing_budgets.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/__init__.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/gapic/__init__.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/gapic/budget_service_client.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/gapic/budget_service_client_config.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/gapic/enums.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/gapic/transports/__init__.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/gapic/transports/budget_service_grpc_transport.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/proto/__init__.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/proto/budget_model.proto" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/proto/budget_model_pb2_grpc.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/proto/budget_service.proto" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/proto/budget_service_pb2_grpc.py" - }, - { - "path": "google/cloud/billing_budgets_v1beta1/types.py" - }, - { - "path": "noxfile.py" - }, - { - "path": "setup.cfg" - }, - { - "path": "setup.py" - }, - { - "path": "synth.metadata" - }, - { - "path": "synth.py" - }, - { - "path": "tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py" - } - ] -} \ No newline at end of file diff --git a/billingbudgets/synth.py b/billingbudgets/synth.py deleted file mode 100644 index 751501cd8543..000000000000 --- a/billingbudgets/synth.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This script is used to synthesize generated parts of this library.""" - -import synthtool as s -import synthtool.gcp as gcp -import logging - -logging.basicConfig(level=logging.DEBUG) - -gapic = gcp.GAPICGenerator() -common = gcp.CommonTemplates() - -# ---------------------------------------------------------------------------- -# Generate billing budgets GAPIC layer -# ---------------------------------------------------------------------------- -library = gapic.py_library( - "billingbudgets", - "v1beta1", - config_path="/google/cloud/billing/budgets/artman_billingbudgets_v1beta1.yaml", - include_protos=True, -) - -excludes = [ - "nox.py", - "setup.py", - "README.rst", - library / "docs/index.rst", - library - / "google/cloud/billingbudgets_v1beta1/proto", # proto files are copied to the wrong place -] - -s.move(library, excludes=excludes) -s.move( - library / "google/cloud/billingbudgets_v1beta1/proto/*.proto", - "google/cloud/billing_budgets_v1beta1/proto", -) - -# Fix namespace -s.replace( - "**/*.py", - "from google\.cloud\.billing\.budgets_v1beta1", - "from google.cloud.billing_budgets_v1beta1", -) - -# Fix package name -s.replace( - ["**/*.rst", "setup.py", "*/**/*.py"], - "google-cloud-billingbudgets", - "google-cloud-billing-budgets", -) - -# ---------------------------------------------------------------------------- -# Add templated files -# ---------------------------------------------------------------------------- -templated_files = common.py_library(unit_cov_level=72, cov_level=72) -s.move(templated_files) - -s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/billingbudgets/tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py b/billingbudgets/tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py deleted file mode 100644 index 8fa8bc5fcd1d..000000000000 --- a/billingbudgets/tests/unit/gapic/v1beta1/test_budget_service_client_v1beta1.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit tests.""" - -import mock -import pytest - -from google.cloud import billing_budgets_v1beta1 -from google.cloud.billing_budgets_v1beta1.proto import budget_model_pb2 -from google.cloud.billing_budgets_v1beta1.proto import budget_service_pb2 -from google.protobuf import empty_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestBudgetServiceClient(object): - def test_create_budget(self): - # Setup Expected Response - name = "name3373707" - display_name = "displayName1615086568" - etag = "etag3123477" - expected_response = {"name": name, "display_name": display_name, "etag": etag} - expected_response = budget_model_pb2.Budget(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - budget = {} - - response = client.create_budget(parent, budget) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.CreateBudgetRequest( - parent=parent, budget=budget - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_create_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - budget = {} - - with pytest.raises(CustomException): - client.create_budget(parent, budget) - - def test_update_budget(self): - # Setup Expected Response - name = "name3373707" - display_name = "displayName1615086568" - etag = "etag3123477" - expected_response = {"name": name, "display_name": display_name, "etag": etag} - expected_response = budget_model_pb2.Budget(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - budget = {} - - response = client.update_budget(budget) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.UpdateBudgetRequest(budget=budget) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_update_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - budget = {} - - with pytest.raises(CustomException): - client.update_budget(budget) - - def test_get_budget(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - etag = "etag3123477" - expected_response = {"name": name_2, "display_name": display_name, "etag": etag} - expected_response = budget_model_pb2.Budget(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - response = client.get_budget(name) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.GetBudgetRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - with pytest.raises(CustomException): - client.get_budget(name) - - def test_list_budgets(self): - # Setup Expected Response - next_page_token = "" - budgets_element = {} - budgets = [budgets_element] - expected_response = {"next_page_token": next_page_token, "budgets": budgets} - expected_response = budget_service_pb2.ListBudgetsResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - - paged_list_response = client.list_budgets(parent) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.budgets[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.ListBudgetsRequest(parent=parent) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_budgets_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - parent = client.billing_account_path("[BILLING_ACCOUNT]") - - paged_list_response = client.list_budgets(parent) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_delete_budget(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup Request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - client.delete_budget(name) - - assert len(channel.requests) == 1 - expected_request = budget_service_pb2.DeleteBudgetRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_delete_budget_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = billing_budgets_v1beta1.BudgetServiceClient() - - # Setup request - name = client.budget_path("[BILLING_ACCOUNT]", "[BUDGET]") - - with pytest.raises(CustomException): - client.delete_budget(name) diff --git a/iam/.coveragerc b/iam/.coveragerc deleted file mode 100644 index b178b094aa1d..000000000000 --- a/iam/.coveragerc +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[run] -branch = True - -[report] -fail_under = 100 -show_missing = True -exclude_lines = - # Re-enable the standard pragma - pragma: NO COVER - # Ignore debug-only repr - def __repr__ - # Ignore abstract methods - raise NotImplementedError -omit = - */gapic/*.py - */proto/*.py - */core/*.py - */site-packages/*.py \ No newline at end of file diff --git a/iam/.flake8 b/iam/.flake8 deleted file mode 100644 index 0268ecc9c55c..000000000000 --- a/iam/.flake8 +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[flake8] -ignore = E203, E266, E501, W503 -exclude = - # Exclude generated code. - **/proto/** - **/gapic/** - *_pb2.py - - # Standard linting exemptions. - __pycache__, - .git, - *.pyc, - conf.py diff --git a/iam/.repo-metadata.json b/iam/.repo-metadata.json deleted file mode 100644 index 158d56068de5..000000000000 --- a/iam/.repo-metadata.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "iamcredentials", - "name_pretty": "Cloud Identity and Access Management", - "product_documentation": "https://cloud.google.com/iam/docs/", - "client_documentation": "https://googleapis.dev/python/iamcredentials/latest", - "issue_tracker": "https://issuetracker.google.com/savedsearches/559761", - "release_level": "alpha", - "language": "python", - "repo": "googleapis/google-cloud-python", - "distribution_name": "google-cloud-iam", - "api_id": "iamcredentials.googleapis.com" -} \ No newline at end of file diff --git a/iam/CHANGELOG.md b/iam/CHANGELOG.md deleted file mode 100644 index a8ec84203fcc..000000000000 --- a/iam/CHANGELOG.md +++ /dev/null @@ -1,73 +0,0 @@ -# Changelog - -[PyPI History][1] - -[1]: https://pypi.org/project/google-cloud-iam/#history - -## 0.2.1 - -08-23-2019 10:10 PDT - -### Implementation Changes -- Remove send/recv msg size limit (via synth). ([#8936](https://github.com/googleapis/google-cloud-python/pull/8936)) - -### Documentation -- Fix documentation links for iam and error-reporting. ([#9073](https://github.com/googleapis/google-cloud-python/pull/9073)) -- Remove compatability badges from READMEs. ([#9035](https://github.com/googleapis/google-cloud-python/pull/9035)) -- Update intersphinx mapping for requests. ([#8805](https://github.com/googleapis/google-cloud-python/pull/8805)) - -## 0.2.0 - -07-24-2019 16:22 PDT - - -### Implementation Changes -- Remove generate_identity_binding_access_token (via synth). ([#8486](https://github.com/googleapis/google-cloud-python/pull/8486)) -- Allow kwargs to be passed to create_channel (via synth). ([#8392](https://github.com/googleapis/google-cloud-python/pull/8392)) -- Add routing header to method metadata, format docstrings, update docs configuration (via synth). ([#7595](https://github.com/googleapis/google-cloud-python/pull/7595)) -- Remove classifier for Python 3.4 for end-of-life. ([#7535](https://github.com/googleapis/google-cloud-python/pull/7535)) -- Remove unused message exports. ([#7268](https://github.com/googleapis/google-cloud-python/pull/7268)) -- Protoc-generated serialization update. ([#7084](https://github.com/googleapis/google-cloud-python/pull/7084)) -- Protoc-generated serialization update. ([#7052](https://github.com/googleapis/google-cloud-python/pull/7052)) -- Pick up stub docstring fix in GAPIC generator. ([#6972](https://github.com/googleapis/google-cloud-python/pull/6972)) - -### New Features -- Add 'client_options' support (via synth). ([#8511](https://github.com/googleapis/google-cloud-python/pull/8511)) - -### Dependencies -- Bump minimum version for google-api-core to 1.14.0. ([#8709](https://github.com/googleapis/google-cloud-python/pull/8709)) - -### Documentation -- Link to googleapis.dev documentation in READMEs. ([#8705](https://github.com/googleapis/google-cloud-python/pull/8705)) -- Add compatibility check badges to READMEs. ([#8288](https://github.com/googleapis/google-cloud-python/pull/8288)) -- Fix client lib docs link in README. ([#7813](https://github.com/googleapis/google-cloud-python/pull/7813)) -- Update copyright: 2018 -> 2019. ([#7146](https://github.com/googleapis/google-cloud-python/pull/7146)) - -### Internal / Testing Changes -- Pin black version (via synth). ([#8584](https://github.com/googleapis/google-cloud-python/pull/8584)) -- Add nox session 'docs' to remaining manual clients. ([#8478](https://github.com/googleapis/google-cloud-python/pull/8478)) -- Add docs job to publish to googleapis.dev. ([#8464](https://github.com/googleapis/google-cloud-python/pull/8464)) -- Declare encoding as utf-8 in pb2 files (via synth). [#8353](https://github.com/googleapis/google-cloud-python/pull/8353)) -- Add disclaimer to auto-generated template files (via synth). ([#8315](https://github.com/googleapis/google-cloud-python/pull/8315)) -- Suppress checking 'cov-fail-under' in nox default session (via synth). ([#8242](https://github.com/googleapis/google-cloud-python/pull/8242)) -- Fix coverage in 'types.py' (via synth). ([#8154](https://github.com/googleapis/google-cloud-python/pull/8154)) -- Blacken noxfile.py, setup.py (via synth). ([#8124](https://github.com/googleapis/google-cloud-python/pull/8124)) -- Add empty lines (via synth). ([#8059](https://github.com/googleapis/google-cloud-python/pull/8059)) -- Add nox session `docs` (via synth). ([#7772](https://github.com/googleapis/google-cloud-python/pull/7772)) -- Copy lintified proto files (via synth). ([#7467](https://github.com/googleapis/google-cloud-python/pull/7467)) -- Add clarifying comment to blacken nox target. ([#7393](https://github.com/googleapis/google-cloud-python/pull/7393)) -- Add protos as an artifact to library ([#7205](https://github.com/googleapis/google-cloud-python/pull/7205)) - -## 0.1.0 - -12-13-2018 10:55 PST - - -### New Features -- Add Client Library for IAM ([#6905](https://github.com/googleapis/google-cloud-python/pull/6905)) - -### Documentation -- Fix docs build ([#6913](https://github.com/googleapis/google-cloud-python/pull/6913)) - -### Internal / Testing Changes -- trove classifier fix ([#6922](https://github.com/googleapis/google-cloud-python/pull/6922)) diff --git a/iam/LICENSE b/iam/LICENSE deleted file mode 100644 index a8ee855de2aa..000000000000 --- a/iam/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/iam/MANIFEST.in b/iam/MANIFEST.in deleted file mode 100644 index 9cbf175afe6b..000000000000 --- a/iam/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include README.rst LICENSE -recursive-include google *.json *.proto -recursive-include tests * -global-exclude *.py[co] -global-exclude __pycache__ diff --git a/iam/README.rst b/iam/README.rst deleted file mode 100644 index 6f439c39a1f2..000000000000 --- a/iam/README.rst +++ /dev/null @@ -1,85 +0,0 @@ -Python Client for IAM API (`Alpha`_) -================================================================ - - - -`IAM API`_: IAM API - -- `Client Library Documentation`_ -- `Product Documentation`_ - -.. _Alpha: https://github.com/googleapis/google-cloud-python/blob/master/README.rst -.. _IAM API: https://cloud.google.com/iam -.. _Client Library Documentation: https://googleapis.dev/python/iamcredentials/latest -.. _Product Documentation: https://cloud.google.com/iam - -Quick Start ------------ - -In order to use this library, you first need to go through the following steps: - -1. `Select or create a Cloud Platform project.`_ -2. `Enable billing for your project.`_ -3. `Enable the IAM API.`_ -4. `Setup Authentication.`_ - -.. _Select or create a Cloud Platform project.: https://console.cloud.google.com/project -.. _Enable billing for your project.: https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project -.. _Enable the IAM API.: https://console.cloud.google.com/flows/enableapi?apiid=iam -.. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html - -Installation -~~~~~~~~~~~~ - -Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to -create isolated Python environments. The basic problem it addresses is one of -dependencies and versions, and indirectly permissions. - -With `virtualenv`_, it's possible to install this library without needing system -install permissions, and without clashing with the installed system -dependencies. - -.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ - -Supported Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.5 - -Deprecated Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^^ -Python == 2.7. Python 2.7 support will be removed on January 1, 2020. - - -Mac/Linux -^^^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - source /bin/activate - /bin/pip install google-cloud-iam - - -Windows -^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - \Scripts\activate - \Scripts\pip.exe install google-cloud-iam - -Next Steps -~~~~~~~~~~ - -- Read the `Client Library Documentation`_ for IAM API - API to see other available methods on the client. -- Read the `IAM API Product documentation`_ to learn - more about the product and see How-to Guides. -- View this `repository’s main README`_ to see the full list of Cloud - APIs that we cover. - -.. _IAM API Product documentation: https://cloud.google.com/iam -.. _repository’s main README: https://github.com/googleapis/google-cloud-python/blob/master/README.rst diff --git a/iam/docs/README.rst b/iam/docs/README.rst deleted file mode 120000 index 89a0106941ff..000000000000 --- a/iam/docs/README.rst +++ /dev/null @@ -1 +0,0 @@ -../README.rst \ No newline at end of file diff --git a/iam/docs/_static/custom.css b/iam/docs/_static/custom.css deleted file mode 100644 index 0abaf229fce3..000000000000 --- a/iam/docs/_static/custom.css +++ /dev/null @@ -1,4 +0,0 @@ -div#python2-eol { - border-color: red; - border-width: medium; -} \ No newline at end of file diff --git a/iam/docs/_templates/layout.html b/iam/docs/_templates/layout.html deleted file mode 100644 index 228529efe2d2..000000000000 --- a/iam/docs/_templates/layout.html +++ /dev/null @@ -1,50 +0,0 @@ - -{% extends "!layout.html" %} -{%- block content %} -{%- if theme_fixed_sidebar|lower == 'true' %} -
- {{ sidebar() }} - {%- block document %} -
- {%- if render_sidebar %} -
- {%- endif %} - - {%- block relbar_top %} - {%- if theme_show_relbar_top|tobool %} - - {%- endif %} - {% endblock %} - -
-
- On January 1, 2020 this library will no longer support Python 2 on the latest released version. - Previously released library versions will continue to be available. For more information please - visit Python 2 support on Google Cloud. -
- {% block body %} {% endblock %} -
- - {%- block relbar_bottom %} - {%- if theme_show_relbar_bottom|tobool %} - - {%- endif %} - {% endblock %} - - {%- if render_sidebar %} -
- {%- endif %} -
- {%- endblock %} -
-
-{%- else %} -{{ super() }} -{%- endif %} -{%- endblock %} diff --git a/iam/docs/changelog.md b/iam/docs/changelog.md deleted file mode 120000 index 04c99a55caae..000000000000 --- a/iam/docs/changelog.md +++ /dev/null @@ -1 +0,0 @@ -../CHANGELOG.md \ No newline at end of file diff --git a/iam/docs/conf.py b/iam/docs/conf.py deleted file mode 100644 index 92b55f389033..000000000000 --- a/iam/docs/conf.py +++ /dev/null @@ -1,357 +0,0 @@ -# -*- coding: utf-8 -*- -# -# google-cloud-iam documentation build configuration file -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -import shlex - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath("..")) - -__version__ = "0.1.0" - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "1.6.3" - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.intersphinx", - "sphinx.ext.coverage", - "sphinx.ext.napoleon", - "sphinx.ext.todo", - "sphinx.ext.viewcode", -] - -# autodoc/autosummary flags -autoclass_content = "both" -autodoc_default_flags = ["members"] -autosummary_generate = True - - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# Allow markdown includes (so releases.md can include CHANGLEOG.md) -# http://www.sphinx-doc.org/en/master/markdown.html -source_parsers = {".md": "recommonmark.parser.CommonMarkParser"} - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = [".rst", ".md"] - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = u"google-cloud-iam" -copyright = u"2017, Google" -author = u"Google APIs" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The full version, including alpha/beta/rc tags. -release = __version__ -# The short X.Y version. -version = ".".join(release.split(".")[0:2]) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["_build"] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "alabaster" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = { - "description": "Google Cloud Client Libraries for Python", - "github_user": "googleapis", - "github_repo": "google-cloud-python", - "github_banner": True, - "font_family": "'Roboto', Georgia, sans", - "head_font_family": "'Roboto', Georgia, serif", - "code_font_family": "'Roboto Mono', 'Consolas', monospace", -} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -# html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -# html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = "google-cloud-iam-doc" - -# -- Options for warnings ------------------------------------------------------ - - -suppress_warnings = [ - # Temporarily suppress this to avoid "more than one target found for - # cross-reference" warning, which are intractable for us to avoid while in - # a mono-repo. - # See https://github.com/sphinx-doc/sphinx/blob - # /2a65ffeef5c107c19084fabdd706cdff3f52d93c/sphinx/domains/python.py#L843 - "ref.python" -] - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - #'preamble': '', - # Latex figure (float) alignment - #'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "google-cloud-iam.tex", - u"google-cloud-iam Documentation", - author, - "manual", - ) -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, "google-cloud-iam", u"google-cloud-iam Documentation", [author], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "google-cloud-iam", - u"google-cloud-iam Documentation", - author, - "google-cloud-iam", - "GAPIC library for the {metadata.shortName} v1 service", - "APIs", - ) -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - "python": ("http://python.readthedocs.org/en/latest/", None), - "gax": ("https://gax-python.readthedocs.org/en/latest/", None), - "google-auth": ("https://google-auth.readthedocs.io/en/stable", None), - "google-gax": ("https://gax-python.readthedocs.io/en/latest/", None), - "google.api_core": ("https://googleapis.dev/python/google-api-core/latest", None), - "grpc": ("https://grpc.io/grpc/python/", None), - "requests": ("https://requests.kennethreitz.org/en/master/", None), - "fastavro": ("https://fastavro.readthedocs.io/en/stable/", None), - "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), -} - - -# Napoleon settings -napoleon_google_docstring = True -napoleon_numpy_docstring = True -napoleon_include_private_with_doc = False -napoleon_include_special_with_doc = True -napoleon_use_admonition_for_examples = False -napoleon_use_admonition_for_notes = False -napoleon_use_admonition_for_references = False -napoleon_use_ivar = False -napoleon_use_param = True -napoleon_use_rtype = True diff --git a/iam/docs/gapic/v1/api.rst b/iam/docs/gapic/v1/api.rst deleted file mode 100644 index 898390081ea9..000000000000 --- a/iam/docs/gapic/v1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for IAM Service Account Credentials API -============================================== - -.. automodule:: google.cloud.iam_credentials_v1 - :members: - :inherited-members: \ No newline at end of file diff --git a/iam/docs/gapic/v1/types.rst b/iam/docs/gapic/v1/types.rst deleted file mode 100644 index a80cc353174d..000000000000 --- a/iam/docs/gapic/v1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for IAM Service Account Credentials API Client -==================================================== - -.. automodule:: google.cloud.iam_credentials_v1.types - :members: \ No newline at end of file diff --git a/iam/docs/index.rst b/iam/docs/index.rst deleted file mode 100644 index 882915fa7d73..000000000000 --- a/iam/docs/index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. include:: README.rst - -API Reference -------------- -.. toctree:: - :maxdepth: 2 - - gapic/v1/api - gapic/v1/types - - -Changelog ---------- - -For a list of all ``google-cloud-iam`` releases: - -.. toctree:: - :maxdepth: 2 - - changelog diff --git a/iam/google/__init__.py b/iam/google/__init__.py deleted file mode 100644 index 9a1b64a6d586..000000000000 --- a/iam/google/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/iam/google/cloud/__init__.py b/iam/google/cloud/__init__.py deleted file mode 100644 index 9a1b64a6d586..000000000000 --- a/iam/google/cloud/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/iam/google/cloud/iam_credentials.py b/iam/google/cloud/iam_credentials.py deleted file mode 100644 index ac6ae35a9642..000000000000 --- a/iam/google/cloud/iam_credentials.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import - -from google.cloud.iam_credentials_v1 import IAMCredentialsClient -from google.cloud.iam_credentials_v1 import types - - -__all__ = ("types", "IAMCredentialsClient") diff --git a/iam/google/cloud/iam_credentials_v1/__init__.py b/iam/google/cloud/iam_credentials_v1/__init__.py deleted file mode 100644 index ba52c484a5bc..000000000000 --- a/iam/google/cloud/iam_credentials_v1/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys -import warnings - -from google.cloud.iam_credentials_v1 import types -from google.cloud.iam_credentials_v1.gapic import iam_credentials_client - - -if sys.version_info[:2] == (2, 7): - message = ( - "A future version of this library will drop support for Python 2.7." - "More details about Python 2 support for Google Cloud Client Libraries" - "can be found at https://cloud.google.com/python/docs/python2-sunset/" - ) - warnings.warn(message, DeprecationWarning) - - -class IAMCredentialsClient(iam_credentials_client.IAMCredentialsClient): - __doc__ = iam_credentials_client.IAMCredentialsClient.__doc__ - - -__all__ = ("types", "IAMCredentialsClient") diff --git a/iam/google/cloud/iam_credentials_v1/gapic/__init__.py b/iam/google/cloud/iam_credentials_v1/gapic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py b/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py deleted file mode 100644 index 858118592970..000000000000 --- a/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py +++ /dev/null @@ -1,590 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.iam.credentials.v1 IAMCredentials API.""" - -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.gapic_v1.routing_header -import google.api_core.grpc_helpers -import google.api_core.path_template -import grpc - -from google.cloud.iam_credentials_v1.gapic import iam_credentials_client_config -from google.cloud.iam_credentials_v1.gapic.transports import ( - iam_credentials_grpc_transport, -) -from google.cloud.iam_credentials_v1.proto import common_pb2 -from google.cloud.iam_credentials_v1.proto import iamcredentials_pb2_grpc -from google.protobuf import duration_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-iam").version - - -class IAMCredentialsClient(object): - """ - A service account is a special type of Google account that belongs to your - application or a virtual machine (VM), instead of to an individual end user. - Your application assumes the identity of the service account to call Google - APIs, so that the users aren't directly involved. - - Service account credentials are used to temporarily assume the identity - of the service account. Supported credential types include OAuth 2.0 access - tokens, OpenID Connect ID tokens, self-signed JSON Web Tokens (JWTs), and - more. - """ - - SERVICE_ADDRESS = "iamcredentials.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.iam.credentials.v1.IAMCredentials" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - IAMCredentialsClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - @classmethod - def service_account_path(cls, project, service_account): - """Return a fully-qualified service_account string.""" - return google.api_core.path_template.expand( - "projects/{project}/serviceAccounts/{service_account}", - project=project, - service_account=service_account, - ) - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.IamCredentialsGrpcTransport, - Callable[[~.Credentials, type], ~.IamCredentialsGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = iam_credentials_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=iam_credentials_grpc_transport.IamCredentialsGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = iam_credentials_grpc_transport.IamCredentialsGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def generate_access_token( - self, - name, - scope, - delegates=None, - lifetime=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Generates an OAuth 2.0 access token for a service account. - - Example: - >>> from google.cloud import iam_credentials_v1 - >>> - >>> client = iam_credentials_v1.IAMCredentialsClient() - >>> - >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') - >>> - >>> # TODO: Initialize `scope`: - >>> scope = [] - >>> - >>> response = client.generate_access_token(name, scope) - - Args: - name (str): Required. The resource name of the service account for which the - credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - scope (list[str]): Required. Code to identify the scopes to be included in the OAuth 2.0 access token. - See https://developers.google.com/identity/protocols/googlescopes for more - information. - At least one value required. - delegates (list[str]): The sequence of service accounts in a delegation chain. Each service - account must be granted the ``roles/iam.serviceAccountTokenCreator`` - role on its next service account in the chain. The last service account - in the chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service account - that is specified in the ``name`` field of the request. - - The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - lifetime (Union[dict, ~google.cloud.iam_credentials_v1.types.Duration]): The desired lifetime duration of the access token in seconds. - Must be set to a value less than or equal to 3600 (1 hour). If a value is - not specified, the token's lifetime will be set to a default value of one - hour. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.iam_credentials_v1.types.Duration` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.iam_credentials_v1.types.GenerateAccessTokenResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "generate_access_token" not in self._inner_api_calls: - self._inner_api_calls[ - "generate_access_token" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.generate_access_token, - default_retry=self._method_configs["GenerateAccessToken"].retry, - default_timeout=self._method_configs["GenerateAccessToken"].timeout, - client_info=self._client_info, - ) - - request = common_pb2.GenerateAccessTokenRequest( - name=name, scope=scope, delegates=delegates, lifetime=lifetime - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["generate_access_token"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def generate_id_token( - self, - name, - audience, - delegates=None, - include_email=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Generates an OpenID Connect ID token for a service account. - - Example: - >>> from google.cloud import iam_credentials_v1 - >>> - >>> client = iam_credentials_v1.IAMCredentialsClient() - >>> - >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') - >>> - >>> # TODO: Initialize `audience`: - >>> audience = '' - >>> - >>> response = client.generate_id_token(name, audience) - - Args: - name (str): Required. The resource name of the service account for which the - credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - audience (str): Required. The audience for the token, such as the API or account that this token - grants access to. - delegates (list[str]): The sequence of service accounts in a delegation chain. Each service - account must be granted the ``roles/iam.serviceAccountTokenCreator`` - role on its next service account in the chain. The last service account - in the chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service account - that is specified in the ``name`` field of the request. - - The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - include_email (bool): Include the service account email in the token. If set to ``true``, the - token will contain ``email`` and ``email_verified`` claims. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.iam_credentials_v1.types.GenerateIdTokenResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "generate_id_token" not in self._inner_api_calls: - self._inner_api_calls[ - "generate_id_token" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.generate_id_token, - default_retry=self._method_configs["GenerateIdToken"].retry, - default_timeout=self._method_configs["GenerateIdToken"].timeout, - client_info=self._client_info, - ) - - request = common_pb2.GenerateIdTokenRequest( - name=name, - audience=audience, - delegates=delegates, - include_email=include_email, - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["generate_id_token"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def sign_blob( - self, - name, - payload, - delegates=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Signs a blob using a service account's system-managed private key. - - Example: - >>> from google.cloud import iam_credentials_v1 - >>> - >>> client = iam_credentials_v1.IAMCredentialsClient() - >>> - >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') - >>> - >>> # TODO: Initialize `payload`: - >>> payload = b'' - >>> - >>> response = client.sign_blob(name, payload) - - Args: - name (str): Required. The resource name of the service account for which the - credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - payload (bytes): Required. The bytes to sign. - delegates (list[str]): The sequence of service accounts in a delegation chain. Each service - account must be granted the ``roles/iam.serviceAccountTokenCreator`` - role on its next service account in the chain. The last service account - in the chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service account - that is specified in the ``name`` field of the request. - - The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.iam_credentials_v1.types.SignBlobResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "sign_blob" not in self._inner_api_calls: - self._inner_api_calls[ - "sign_blob" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.sign_blob, - default_retry=self._method_configs["SignBlob"].retry, - default_timeout=self._method_configs["SignBlob"].timeout, - client_info=self._client_info, - ) - - request = common_pb2.SignBlobRequest( - name=name, payload=payload, delegates=delegates - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["sign_blob"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def sign_jwt( - self, - name, - payload, - delegates=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Signs a JWT using a service account's system-managed private key. - - Example: - >>> from google.cloud import iam_credentials_v1 - >>> - >>> client = iam_credentials_v1.IAMCredentialsClient() - >>> - >>> name = client.service_account_path('[PROJECT]', '[SERVICE_ACCOUNT]') - >>> - >>> # TODO: Initialize `payload`: - >>> payload = '' - >>> - >>> response = client.sign_jwt(name, payload) - - Args: - name (str): Required. The resource name of the service account for which the - credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - payload (str): Required. The JWT payload to sign: a JSON object that contains a JWT Claims Set. - delegates (list[str]): The sequence of service accounts in a delegation chain. Each service - account must be granted the ``roles/iam.serviceAccountTokenCreator`` - role on its next service account in the chain. The last service account - in the chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service account - that is specified in the ``name`` field of the request. - - The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. The ``-`` - wildcard character is required; replacing it with a project ID is - invalid. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.iam_credentials_v1.types.SignJwtResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "sign_jwt" not in self._inner_api_calls: - self._inner_api_calls[ - "sign_jwt" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.sign_jwt, - default_retry=self._method_configs["SignJwt"].retry, - default_timeout=self._method_configs["SignJwt"].timeout, - client_info=self._client_info, - ) - - request = common_pb2.SignJwtRequest( - name=name, payload=payload, delegates=delegates - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["sign_jwt"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py b/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py deleted file mode 100644 index 35c007ca367f..000000000000 --- a/iam/google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py +++ /dev/null @@ -1,43 +0,0 @@ -config = { - "interfaces": { - "google.iam.credentials.v1.IAMCredentials": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "GenerateAccessToken": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "GenerateIdToken": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "SignBlob": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "SignJwt": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/iam/google/cloud/iam_credentials_v1/gapic/transports/__init__.py b/iam/google/cloud/iam_credentials_v1/gapic/transports/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/iam/google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py b/iam/google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py deleted file mode 100644 index 39be27f30619..000000000000 --- a/iam/google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers - -from google.cloud.iam_credentials_v1.proto import iamcredentials_pb2_grpc - - -class IamCredentialsGrpcTransport(object): - """gRPC transport class providing stubs for - google.iam.credentials.v1 IAMCredentials API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, - channel=None, - credentials=None, - address="iamcredentials.googleapis.com:443", - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = { - "iam_credentials_stub": iamcredentials_pb2_grpc.IAMCredentialsStub(channel) - } - - @classmethod - def create_channel( - cls, address="iamcredentials.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def generate_access_token(self): - """Return the gRPC stub for :meth:`IAMCredentialsClient.generate_access_token`. - - Generates an OAuth 2.0 access token for a service account. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_credentials_stub"].GenerateAccessToken - - @property - def generate_id_token(self): - """Return the gRPC stub for :meth:`IAMCredentialsClient.generate_id_token`. - - Generates an OpenID Connect ID token for a service account. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_credentials_stub"].GenerateIdToken - - @property - def sign_blob(self): - """Return the gRPC stub for :meth:`IAMCredentialsClient.sign_blob`. - - Signs a blob using a service account's system-managed private key. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_credentials_stub"].SignBlob - - @property - def sign_jwt(self): - """Return the gRPC stub for :meth:`IAMCredentialsClient.sign_jwt`. - - Signs a JWT using a service account's system-managed private key. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_credentials_stub"].SignJwt diff --git a/iam/google/cloud/iam_credentials_v1/proto/__init__.py b/iam/google/cloud/iam_credentials_v1/proto/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/iam/google/cloud/iam_credentials_v1/proto/common.proto b/iam/google/cloud/iam_credentials_v1/proto/common.proto deleted file mode 100644 index 361f2e90caf8..000000000000 --- a/iam/google/cloud/iam_credentials_v1/proto/common.proto +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.iam.credentials.v1; - -import "google/api/field_behavior.proto"; -import "google/api/resource.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/timestamp.proto"; - -option cc_enable_arenas = true; -option go_package = "google.golang.org/genproto/googleapis/iam/credentials/v1;credentials"; -option java_multiple_files = true; -option java_outer_classname = "IAMCredentialsCommonProto"; -option java_package = "com.google.cloud.iam.credentials.v1"; -option (google.api.resource_definition) = { - type: "iam.googleapis.com/ServiceAccount" - pattern: "projects/{project}/serviceAccounts/{service_account}" -}; - -message GenerateAccessTokenRequest { - // Required. The resource name of the service account for which the credentials - // are requested, in the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "iam.googleapis.com/ServiceAccount" - } - ]; - - // The sequence of service accounts in a delegation chain. Each service - // account must be granted the `roles/iam.serviceAccountTokenCreator` role - // on its next service account in the chain. The last service account in the - // chain must be granted the `roles/iam.serviceAccountTokenCreator` role - // on the service account that is specified in the `name` field of the - // request. - // - // The delegates must have the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - repeated string delegates = 2; - - // Required. Code to identify the scopes to be included in the OAuth 2.0 access token. - // See https://developers.google.com/identity/protocols/googlescopes for more - // information. - // At least one value required. - repeated string scope = 4 [(google.api.field_behavior) = REQUIRED]; - - // The desired lifetime duration of the access token in seconds. - // Must be set to a value less than or equal to 3600 (1 hour). If a value is - // not specified, the token's lifetime will be set to a default value of one - // hour. - google.protobuf.Duration lifetime = 7; -} - -message GenerateAccessTokenResponse { - // The OAuth 2.0 access token. - string access_token = 1; - - // Token expiration time. - // The expiration time is always set. - google.protobuf.Timestamp expire_time = 3; -} - -message SignBlobRequest { - // Required. The resource name of the service account for which the credentials - // are requested, in the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "iam.googleapis.com/ServiceAccount" - } - ]; - - // The sequence of service accounts in a delegation chain. Each service - // account must be granted the `roles/iam.serviceAccountTokenCreator` role - // on its next service account in the chain. The last service account in the - // chain must be granted the `roles/iam.serviceAccountTokenCreator` role - // on the service account that is specified in the `name` field of the - // request. - // - // The delegates must have the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - repeated string delegates = 3; - - // Required. The bytes to sign. - bytes payload = 5 [(google.api.field_behavior) = REQUIRED]; -} - -message SignBlobResponse { - // The ID of the key used to sign the blob. - string key_id = 1; - - // The signed blob. - bytes signed_blob = 4; -} - -message SignJwtRequest { - // Required. The resource name of the service account for which the credentials - // are requested, in the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "iam.googleapis.com/ServiceAccount" - } - ]; - - // The sequence of service accounts in a delegation chain. Each service - // account must be granted the `roles/iam.serviceAccountTokenCreator` role - // on its next service account in the chain. The last service account in the - // chain must be granted the `roles/iam.serviceAccountTokenCreator` role - // on the service account that is specified in the `name` field of the - // request. - // - // The delegates must have the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - repeated string delegates = 3; - - // Required. The JWT payload to sign: a JSON object that contains a JWT Claims Set. - string payload = 5 [(google.api.field_behavior) = REQUIRED]; -} - -message SignJwtResponse { - // The ID of the key used to sign the JWT. - string key_id = 1; - - // The signed JWT. - string signed_jwt = 2; -} - -message GenerateIdTokenRequest { - // Required. The resource name of the service account for which the credentials - // are requested, in the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "iam.googleapis.com/ServiceAccount" - } - ]; - - // The sequence of service accounts in a delegation chain. Each service - // account must be granted the `roles/iam.serviceAccountTokenCreator` role - // on its next service account in the chain. The last service account in the - // chain must be granted the `roles/iam.serviceAccountTokenCreator` role - // on the service account that is specified in the `name` field of the - // request. - // - // The delegates must have the following format: - // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard - // character is required; replacing it with a project ID is invalid. - repeated string delegates = 2; - - // Required. The audience for the token, such as the API or account that this token - // grants access to. - string audience = 3 [(google.api.field_behavior) = REQUIRED]; - - // Include the service account email in the token. If set to `true`, the - // token will contain `email` and `email_verified` claims. - bool include_email = 4; -} - -message GenerateIdTokenResponse { - // The OpenId Connect ID token. - string token = 1; -} diff --git a/iam/google/cloud/iam_credentials_v1/proto/common_pb2.py b/iam/google/cloud/iam_credentials_v1/proto/common_pb2.py deleted file mode 100644 index 08438614650e..000000000000 --- a/iam/google/cloud/iam_credentials_v1/proto/common_pb2.py +++ /dev/null @@ -1,846 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/iam/credentials/v1/common.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 -from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 -from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/iam/credentials/v1/common.proto", - package="google.iam.credentials.v1", - syntax="proto3", - serialized_options=_b( - "\n#com.google.cloud.iam.credentials.v1B\031IAMCredentialsCommonProtoP\001ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\370\001\001\352AY\n!iam.googleapis.com/ServiceAccount\0224projects/{project}/serviceAccounts/{service_account}" - ), - serialized_pb=_b( - '\n&google/iam/credentials/v1/common.proto\x12\x19google.iam.credentials.v1\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xa9\x01\n\x1aGenerateAccessTokenRequest\x12\x37\n\x04name\x18\x01 \x01(\tB)\xe0\x41\x02\xfa\x41#\n!iam.googleapis.com/ServiceAccount\x12\x11\n\tdelegates\x18\x02 \x03(\t\x12\x12\n\x05scope\x18\x04 \x03(\tB\x03\xe0\x41\x02\x12+\n\x08lifetime\x18\x07 \x01(\x0b\x32\x19.google.protobuf.Duration"d\n\x1bGenerateAccessTokenResponse\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x01 \x01(\t\x12/\n\x0b\x65xpire_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"s\n\x0fSignBlobRequest\x12\x37\n\x04name\x18\x01 \x01(\tB)\xe0\x41\x02\xfa\x41#\n!iam.googleapis.com/ServiceAccount\x12\x11\n\tdelegates\x18\x03 \x03(\t\x12\x14\n\x07payload\x18\x05 \x01(\x0c\x42\x03\xe0\x41\x02"7\n\x10SignBlobResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x13\n\x0bsigned_blob\x18\x04 \x01(\x0c"r\n\x0eSignJwtRequest\x12\x37\n\x04name\x18\x01 \x01(\tB)\xe0\x41\x02\xfa\x41#\n!iam.googleapis.com/ServiceAccount\x12\x11\n\tdelegates\x18\x03 \x03(\t\x12\x14\n\x07payload\x18\x05 \x01(\tB\x03\xe0\x41\x02"5\n\x0fSignJwtResponse\x12\x0e\n\x06key_id\x18\x01 \x01(\t\x12\x12\n\nsigned_jwt\x18\x02 \x01(\t"\x92\x01\n\x16GenerateIdTokenRequest\x12\x37\n\x04name\x18\x01 \x01(\tB)\xe0\x41\x02\xfa\x41#\n!iam.googleapis.com/ServiceAccount\x12\x11\n\tdelegates\x18\x02 \x03(\t\x12\x15\n\x08\x61udience\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x15\n\rinclude_email\x18\x04 \x01(\x08"(\n\x17GenerateIdTokenResponse\x12\r\n\x05token\x18\x01 \x01(\tB\xe7\x01\n#com.google.cloud.iam.credentials.v1B\x19IAMCredentialsCommonProtoP\x01ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\xf8\x01\x01\xea\x41Y\n!iam.googleapis.com/ServiceAccount\x12\x34projects/{project}/serviceAccounts/{service_account}b\x06proto3' - ), - dependencies=[ - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_api_dot_resource__pb2.DESCRIPTOR, - google_dot_protobuf_dot_duration__pb2.DESCRIPTOR, - google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, - ], -) - - -_GENERATEACCESSTOKENREQUEST = _descriptor.Descriptor( - name="GenerateAccessTokenRequest", - full_name="google.iam.credentials.v1.GenerateAccessTokenRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A#\n!iam.googleapis.com/ServiceAccount" - ), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="delegates", - full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.delegates", - index=1, - number=2, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="scope", - full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.scope", - index=2, - number=4, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="lifetime", - full_name="google.iam.credentials.v1.GenerateAccessTokenRequest.lifetime", - index=3, - number=7, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=195, - serialized_end=364, -) - - -_GENERATEACCESSTOKENRESPONSE = _descriptor.Descriptor( - name="GenerateAccessTokenResponse", - full_name="google.iam.credentials.v1.GenerateAccessTokenResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="access_token", - full_name="google.iam.credentials.v1.GenerateAccessTokenResponse.access_token", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="expire_time", - full_name="google.iam.credentials.v1.GenerateAccessTokenResponse.expire_time", - index=1, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=366, - serialized_end=466, -) - - -_SIGNBLOBREQUEST = _descriptor.Descriptor( - name="SignBlobRequest", - full_name="google.iam.credentials.v1.SignBlobRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.iam.credentials.v1.SignBlobRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A#\n!iam.googleapis.com/ServiceAccount" - ), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="delegates", - full_name="google.iam.credentials.v1.SignBlobRequest.delegates", - index=1, - number=3, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="payload", - full_name="google.iam.credentials.v1.SignBlobRequest.payload", - index=2, - number=5, - type=12, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b(""), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=468, - serialized_end=583, -) - - -_SIGNBLOBRESPONSE = _descriptor.Descriptor( - name="SignBlobResponse", - full_name="google.iam.credentials.v1.SignBlobResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key_id", - full_name="google.iam.credentials.v1.SignBlobResponse.key_id", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="signed_blob", - full_name="google.iam.credentials.v1.SignBlobResponse.signed_blob", - index=1, - number=4, - type=12, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b(""), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=585, - serialized_end=640, -) - - -_SIGNJWTREQUEST = _descriptor.Descriptor( - name="SignJwtRequest", - full_name="google.iam.credentials.v1.SignJwtRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.iam.credentials.v1.SignJwtRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A#\n!iam.googleapis.com/ServiceAccount" - ), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="delegates", - full_name="google.iam.credentials.v1.SignJwtRequest.delegates", - index=1, - number=3, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="payload", - full_name="google.iam.credentials.v1.SignJwtRequest.payload", - index=2, - number=5, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=642, - serialized_end=756, -) - - -_SIGNJWTRESPONSE = _descriptor.Descriptor( - name="SignJwtResponse", - full_name="google.iam.credentials.v1.SignJwtResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key_id", - full_name="google.iam.credentials.v1.SignJwtResponse.key_id", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="signed_jwt", - full_name="google.iam.credentials.v1.SignJwtResponse.signed_jwt", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=758, - serialized_end=811, -) - - -_GENERATEIDTOKENREQUEST = _descriptor.Descriptor( - name="GenerateIdTokenRequest", - full_name="google.iam.credentials.v1.GenerateIdTokenRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.iam.credentials.v1.GenerateIdTokenRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b( - "\340A\002\372A#\n!iam.googleapis.com/ServiceAccount" - ), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="delegates", - full_name="google.iam.credentials.v1.GenerateIdTokenRequest.delegates", - index=1, - number=2, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audience", - full_name="google.iam.credentials.v1.GenerateIdTokenRequest.audience", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="include_email", - full_name="google.iam.credentials.v1.GenerateIdTokenRequest.include_email", - index=3, - number=4, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=814, - serialized_end=960, -) - - -_GENERATEIDTOKENRESPONSE = _descriptor.Descriptor( - name="GenerateIdTokenResponse", - full_name="google.iam.credentials.v1.GenerateIdTokenResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="token", - full_name="google.iam.credentials.v1.GenerateIdTokenResponse.token", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=962, - serialized_end=1002, -) - -_GENERATEACCESSTOKENREQUEST.fields_by_name[ - "lifetime" -].message_type = google_dot_protobuf_dot_duration__pb2._DURATION -_GENERATEACCESSTOKENRESPONSE.fields_by_name[ - "expire_time" -].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP -DESCRIPTOR.message_types_by_name[ - "GenerateAccessTokenRequest" -] = _GENERATEACCESSTOKENREQUEST -DESCRIPTOR.message_types_by_name[ - "GenerateAccessTokenResponse" -] = _GENERATEACCESSTOKENRESPONSE -DESCRIPTOR.message_types_by_name["SignBlobRequest"] = _SIGNBLOBREQUEST -DESCRIPTOR.message_types_by_name["SignBlobResponse"] = _SIGNBLOBRESPONSE -DESCRIPTOR.message_types_by_name["SignJwtRequest"] = _SIGNJWTREQUEST -DESCRIPTOR.message_types_by_name["SignJwtResponse"] = _SIGNJWTRESPONSE -DESCRIPTOR.message_types_by_name["GenerateIdTokenRequest"] = _GENERATEIDTOKENREQUEST -DESCRIPTOR.message_types_by_name["GenerateIdTokenResponse"] = _GENERATEIDTOKENRESPONSE -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -GenerateAccessTokenRequest = _reflection.GeneratedProtocolMessageType( - "GenerateAccessTokenRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GENERATEACCESSTOKENREQUEST, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - name: - Required. The resource name of the service account for which - the credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - delegates: - The sequence of service accounts in a delegation chain. Each - service account must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on its next - service account in the chain. The last service account in the - chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service - account that is specified in the ``name`` field of the - request. The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - scope: - Required. Code to identify the scopes to be included in the - OAuth 2.0 access token. See - https://developers.google.com/identity/protocols/googlescopes - for more information. At least one value required. - lifetime: - The desired lifetime duration of the access token in seconds. - Must be set to a value less than or equal to 3600 (1 hour). If - a value is not specified, the token's lifetime will be set to - a default value of one hour. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateAccessTokenRequest) - ), -) -_sym_db.RegisterMessage(GenerateAccessTokenRequest) - -GenerateAccessTokenResponse = _reflection.GeneratedProtocolMessageType( - "GenerateAccessTokenResponse", - (_message.Message,), - dict( - DESCRIPTOR=_GENERATEACCESSTOKENRESPONSE, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - access_token: - The OAuth 2.0 access token. - expire_time: - Token expiration time. The expiration time is always set. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateAccessTokenResponse) - ), -) -_sym_db.RegisterMessage(GenerateAccessTokenResponse) - -SignBlobRequest = _reflection.GeneratedProtocolMessageType( - "SignBlobRequest", - (_message.Message,), - dict( - DESCRIPTOR=_SIGNBLOBREQUEST, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - name: - Required. The resource name of the service account for which - the credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - delegates: - The sequence of service accounts in a delegation chain. Each - service account must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on its next - service account in the chain. The last service account in the - chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service - account that is specified in the ``name`` field of the - request. The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - payload: - Required. The bytes to sign. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignBlobRequest) - ), -) -_sym_db.RegisterMessage(SignBlobRequest) - -SignBlobResponse = _reflection.GeneratedProtocolMessageType( - "SignBlobResponse", - (_message.Message,), - dict( - DESCRIPTOR=_SIGNBLOBRESPONSE, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - key_id: - The ID of the key used to sign the blob. - signed_blob: - The signed blob. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignBlobResponse) - ), -) -_sym_db.RegisterMessage(SignBlobResponse) - -SignJwtRequest = _reflection.GeneratedProtocolMessageType( - "SignJwtRequest", - (_message.Message,), - dict( - DESCRIPTOR=_SIGNJWTREQUEST, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - name: - Required. The resource name of the service account for which - the credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - delegates: - The sequence of service accounts in a delegation chain. Each - service account must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on its next - service account in the chain. The last service account in the - chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service - account that is specified in the ``name`` field of the - request. The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - payload: - Required. The JWT payload to sign: a JSON object that contains - a JWT Claims Set. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignJwtRequest) - ), -) -_sym_db.RegisterMessage(SignJwtRequest) - -SignJwtResponse = _reflection.GeneratedProtocolMessageType( - "SignJwtResponse", - (_message.Message,), - dict( - DESCRIPTOR=_SIGNJWTRESPONSE, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - key_id: - The ID of the key used to sign the JWT. - signed_jwt: - The signed JWT. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.SignJwtResponse) - ), -) -_sym_db.RegisterMessage(SignJwtResponse) - -GenerateIdTokenRequest = _reflection.GeneratedProtocolMessageType( - "GenerateIdTokenRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GENERATEIDTOKENREQUEST, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - name: - Required. The resource name of the service account for which - the credentials are requested, in the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - delegates: - The sequence of service accounts in a delegation chain. Each - service account must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on its next - service account in the chain. The last service account in the - chain must be granted the - ``roles/iam.serviceAccountTokenCreator`` role on the service - account that is specified in the ``name`` field of the - request. The delegates must have the following format: - ``projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}``. - The ``-`` wildcard character is required; replacing it with a - project ID is invalid. - audience: - Required. The audience for the token, such as the API or - account that this token grants access to. - include_email: - Include the service account email in the token. If set to - ``true``, the token will contain ``email`` and - ``email_verified`` claims. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateIdTokenRequest) - ), -) -_sym_db.RegisterMessage(GenerateIdTokenRequest) - -GenerateIdTokenResponse = _reflection.GeneratedProtocolMessageType( - "GenerateIdTokenResponse", - (_message.Message,), - dict( - DESCRIPTOR=_GENERATEIDTOKENRESPONSE, - __module__="google.iam.credentials.v1.common_pb2", - __doc__=""" -Attributes: - token: - The OpenId Connect ID token. - """, - # @@protoc_insertion_point(class_scope:google.iam.credentials.v1.GenerateIdTokenResponse) - ), -) -_sym_db.RegisterMessage(GenerateIdTokenResponse) - - -DESCRIPTOR._options = None -_GENERATEACCESSTOKENREQUEST.fields_by_name["name"]._options = None -_GENERATEACCESSTOKENREQUEST.fields_by_name["scope"]._options = None -_SIGNBLOBREQUEST.fields_by_name["name"]._options = None -_SIGNBLOBREQUEST.fields_by_name["payload"]._options = None -_SIGNJWTREQUEST.fields_by_name["name"]._options = None -_SIGNJWTREQUEST.fields_by_name["payload"]._options = None -_GENERATEIDTOKENREQUEST.fields_by_name["name"]._options = None -_GENERATEIDTOKENREQUEST.fields_by_name["audience"]._options = None -# @@protoc_insertion_point(module_scope) diff --git a/iam/google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py b/iam/google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py deleted file mode 100644 index 07cb78fe03a9..000000000000 --- a/iam/google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py +++ /dev/null @@ -1,2 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc diff --git a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials.proto b/iam/google/cloud/iam_credentials_v1/proto/iamcredentials.proto deleted file mode 100644 index 29554c567db1..000000000000 --- a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials.proto +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.iam.credentials.v1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/iam/credentials/v1/common.proto"; - -option cc_enable_arenas = true; -option go_package = "google.golang.org/genproto/googleapis/iam/credentials/v1;credentials"; -option java_multiple_files = true; -option java_outer_classname = "IAMCredentialsProto"; -option java_package = "com.google.cloud.iam.credentials.v1"; - -// A service account is a special type of Google account that belongs to your -// application or a virtual machine (VM), instead of to an individual end user. -// Your application assumes the identity of the service account to call Google -// APIs, so that the users aren't directly involved. -// -// Service account credentials are used to temporarily assume the identity -// of the service account. Supported credential types include OAuth 2.0 access -// tokens, OpenID Connect ID tokens, self-signed JSON Web Tokens (JWTs), and -// more. -service IAMCredentials { - option (google.api.default_host) = "iamcredentials.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Generates an OAuth 2.0 access token for a service account. - rpc GenerateAccessToken(GenerateAccessTokenRequest) returns (GenerateAccessTokenResponse) { - option (google.api.http) = { - post: "/v1/{name=projects/*/serviceAccounts/*}:generateAccessToken" - body: "*" - }; - option (google.api.method_signature) = "name,delegates,scope,lifetime"; - } - - // Generates an OpenID Connect ID token for a service account. - rpc GenerateIdToken(GenerateIdTokenRequest) returns (GenerateIdTokenResponse) { - option (google.api.http) = { - post: "/v1/{name=projects/*/serviceAccounts/*}:generateIdToken" - body: "*" - }; - option (google.api.method_signature) = "name,delegates,audience,include_email"; - } - - // Signs a blob using a service account's system-managed private key. - rpc SignBlob(SignBlobRequest) returns (SignBlobResponse) { - option (google.api.http) = { - post: "/v1/{name=projects/*/serviceAccounts/*}:signBlob" - body: "*" - }; - option (google.api.method_signature) = "name,delegates,payload"; - } - - // Signs a JWT using a service account's system-managed private key. - rpc SignJwt(SignJwtRequest) returns (SignJwtResponse) { - option (google.api.http) = { - post: "/v1/{name=projects/*/serviceAccounts/*}:signJwt" - body: "*" - }; - option (google.api.method_signature) = "name,delegates,payload"; - } -} diff --git a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py b/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py deleted file mode 100644 index 9269e5f6bec4..000000000000 --- a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py +++ /dev/null @@ -1,109 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/iam/credentials/v1/iamcredentials.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.cloud.iam_credentials_v1.proto import ( - common_pb2 as google_dot_iam_dot_credentials_dot_v1_dot_common__pb2, -) - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/iam/credentials/v1/iamcredentials.proto", - package="google.iam.credentials.v1", - syntax="proto3", - serialized_options=_b( - "\n#com.google.cloud.iam.credentials.v1B\023IAMCredentialsProtoP\001ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\370\001\001" - ), - serialized_pb=_b( - '\n.google/iam/credentials/v1/iamcredentials.proto\x12\x19google.iam.credentials.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a&google/iam/credentials/v1/common.proto2\xad\x07\n\x0eIAMCredentials\x12\xec\x01\n\x13GenerateAccessToken\x12\x35.google.iam.credentials.v1.GenerateAccessTokenRequest\x1a\x36.google.iam.credentials.v1.GenerateAccessTokenResponse"f\x82\xd3\xe4\x93\x02@";/v1/{name=projects/*/serviceAccounts/*}:generateAccessToken:\x01*\xda\x41\x1dname,delegates,scope,lifetime\x12\xe4\x01\n\x0fGenerateIdToken\x12\x31.google.iam.credentials.v1.GenerateIdTokenRequest\x1a\x32.google.iam.credentials.v1.GenerateIdTokenResponse"j\x82\xd3\xe4\x93\x02<"7/v1/{name=projects/*/serviceAccounts/*}:generateIdToken:\x01*\xda\x41%name,delegates,audience,include_email\x12\xb9\x01\n\x08SignBlob\x12*.google.iam.credentials.v1.SignBlobRequest\x1a+.google.iam.credentials.v1.SignBlobResponse"T\x82\xd3\xe4\x93\x02\x35"0/v1/{name=projects/*/serviceAccounts/*}:signBlob:\x01*\xda\x41\x16name,delegates,payload\x12\xb5\x01\n\x07SignJwt\x12).google.iam.credentials.v1.SignJwtRequest\x1a*.google.iam.credentials.v1.SignJwtResponse"S\x82\xd3\xe4\x93\x02\x34"//v1/{name=projects/*/serviceAccounts/*}:signJwt:\x01*\xda\x41\x16name,delegates,payload\x1aQ\xca\x41\x1diamcredentials.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformB\x85\x01\n#com.google.cloud.iam.credentials.v1B\x13IAMCredentialsProtoP\x01ZDgoogle.golang.org/genproto/googleapis/iam/credentials/v1;credentials\xf8\x01\x01\x62\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.DESCRIPTOR, - ], -) - - -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - - -DESCRIPTOR._options = None - -_IAMCREDENTIALS = _descriptor.ServiceDescriptor( - name="IAMCredentials", - full_name="google.iam.credentials.v1.IAMCredentials", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\035iamcredentials.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=173, - serialized_end=1114, - methods=[ - _descriptor.MethodDescriptor( - name="GenerateAccessToken", - full_name="google.iam.credentials.v1.IAMCredentials.GenerateAccessToken", - index=0, - containing_service=None, - input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEACCESSTOKENREQUEST, - output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEACCESSTOKENRESPONSE, - serialized_options=_b( - '\202\323\344\223\002@";/v1/{name=projects/*/serviceAccounts/*}:generateAccessToken:\001*\332A\035name,delegates,scope,lifetime' - ), - ), - _descriptor.MethodDescriptor( - name="GenerateIdToken", - full_name="google.iam.credentials.v1.IAMCredentials.GenerateIdToken", - index=1, - containing_service=None, - input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEIDTOKENREQUEST, - output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._GENERATEIDTOKENRESPONSE, - serialized_options=_b( - '\202\323\344\223\002<"7/v1/{name=projects/*/serviceAccounts/*}:generateIdToken:\001*\332A%name,delegates,audience,include_email' - ), - ), - _descriptor.MethodDescriptor( - name="SignBlob", - full_name="google.iam.credentials.v1.IAMCredentials.SignBlob", - index=2, - containing_service=None, - input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNBLOBREQUEST, - output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNBLOBRESPONSE, - serialized_options=_b( - '\202\323\344\223\0025"0/v1/{name=projects/*/serviceAccounts/*}:signBlob:\001*\332A\026name,delegates,payload' - ), - ), - _descriptor.MethodDescriptor( - name="SignJwt", - full_name="google.iam.credentials.v1.IAMCredentials.SignJwt", - index=3, - containing_service=None, - input_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNJWTREQUEST, - output_type=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2._SIGNJWTRESPONSE, - serialized_options=_b( - '\202\323\344\223\0024"//v1/{name=projects/*/serviceAccounts/*}:signJwt:\001*\332A\026name,delegates,payload' - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_IAMCREDENTIALS) - -DESCRIPTOR.services_by_name["IAMCredentials"] = _IAMCREDENTIALS - -# @@protoc_insertion_point(module_scope) diff --git a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py b/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py deleted file mode 100644 index 277e7249eef8..000000000000 --- a/iam/google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py +++ /dev/null @@ -1,116 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.iam_credentials_v1.proto import ( - common_pb2 as google_dot_iam_dot_credentials_dot_v1_dot_common__pb2, -) - - -class IAMCredentialsStub(object): - """A service account is a special type of Google account that belongs to your - application or a virtual machine (VM), instead of to an individual end user. - Your application assumes the identity of the service account to call Google - APIs, so that the users aren't directly involved. - - Service account credentials are used to temporarily assume the identity - of the service account. Supported credential types include OAuth 2.0 access - tokens, OpenID Connect ID tokens, self-signed JSON Web Tokens (JWTs), and - more. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.GenerateAccessToken = channel.unary_unary( - "/google.iam.credentials.v1.IAMCredentials/GenerateAccessToken", - request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenRequest.SerializeToString, - response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenResponse.FromString, - ) - self.GenerateIdToken = channel.unary_unary( - "/google.iam.credentials.v1.IAMCredentials/GenerateIdToken", - request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenRequest.SerializeToString, - response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenResponse.FromString, - ) - self.SignBlob = channel.unary_unary( - "/google.iam.credentials.v1.IAMCredentials/SignBlob", - request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobRequest.SerializeToString, - response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobResponse.FromString, - ) - self.SignJwt = channel.unary_unary( - "/google.iam.credentials.v1.IAMCredentials/SignJwt", - request_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtRequest.SerializeToString, - response_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtResponse.FromString, - ) - - -class IAMCredentialsServicer(object): - """A service account is a special type of Google account that belongs to your - application or a virtual machine (VM), instead of to an individual end user. - Your application assumes the identity of the service account to call Google - APIs, so that the users aren't directly involved. - - Service account credentials are used to temporarily assume the identity - of the service account. Supported credential types include OAuth 2.0 access - tokens, OpenID Connect ID tokens, self-signed JSON Web Tokens (JWTs), and - more. - """ - - def GenerateAccessToken(self, request, context): - """Generates an OAuth 2.0 access token for a service account. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GenerateIdToken(self, request, context): - """Generates an OpenID Connect ID token for a service account. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def SignBlob(self, request, context): - """Signs a blob using a service account's system-managed private key. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def SignJwt(self, request, context): - """Signs a JWT using a service account's system-managed private key. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_IAMCredentialsServicer_to_server(servicer, server): - rpc_method_handlers = { - "GenerateAccessToken": grpc.unary_unary_rpc_method_handler( - servicer.GenerateAccessToken, - request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenRequest.FromString, - response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateAccessTokenResponse.SerializeToString, - ), - "GenerateIdToken": grpc.unary_unary_rpc_method_handler( - servicer.GenerateIdToken, - request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenRequest.FromString, - response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.GenerateIdTokenResponse.SerializeToString, - ), - "SignBlob": grpc.unary_unary_rpc_method_handler( - servicer.SignBlob, - request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobRequest.FromString, - response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignBlobResponse.SerializeToString, - ), - "SignJwt": grpc.unary_unary_rpc_method_handler( - servicer.SignJwt, - request_deserializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtRequest.FromString, - response_serializer=google_dot_iam_dot_credentials_dot_v1_dot_common__pb2.SignJwtResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.iam.credentials.v1.IAMCredentials", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/iam/google/cloud/iam_credentials_v1/types.py b/iam/google/cloud/iam_credentials_v1/types.py deleted file mode 100644 index 0e1eb556f250..000000000000 --- a/iam/google/cloud/iam_credentials_v1/types.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.iam_credentials_v1.proto import common_pb2 -from google.protobuf import duration_pb2 -from google.protobuf import timestamp_pb2 - - -_shared_modules = [duration_pb2, timestamp_pb2] - -_local_modules = [common_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.iam_credentials_v1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/iam/noxfile.py b/iam/noxfile.py deleted file mode 100644 index 7949a4e3925a..000000000000 --- a/iam/noxfile.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by synthtool. DO NOT EDIT! - -from __future__ import absolute_import -import os -import shutil - -import nox - - -LOCAL_DEPS = (os.path.join("..", "api_core"), os.path.join("..", "core")) -BLACK_VERSION = "black==19.3b0" -BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] - -if os.path.exists("samples"): - BLACK_PATHS.append("samples") - - -@nox.session(python="3.7") -def lint(session): - """Run linters. - - Returns a failure if the linters find linting errors or sufficiently - serious code quality issues. - """ - session.install("flake8", BLACK_VERSION, *LOCAL_DEPS) - session.run("black", "--check", *BLACK_PATHS) - session.run("flake8", "google", "tests") - - -@nox.session(python="3.6") -def blacken(session): - """Run black. - - Format code to uniform standard. - - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. - That run uses an image that doesn't have 3.6 installed. Before updating this - check the state of the `gcp_ubuntu_config` we use for that Kokoro run. - """ - session.install(BLACK_VERSION) - session.run("black", *BLACK_PATHS) - - -@nox.session(python="3.7") -def lint_setup_py(session): - """Verify that setup.py is valid (including RST check).""" - session.install("docutils", "pygments") - session.run("python", "setup.py", "check", "--restructuredtext", "--strict") - - -def default(session): - # Install all test dependencies, then install this package in-place. - session.install("mock", "pytest", "pytest-cov") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", ".") - - # Run py.test against the unit tests. - session.run( - "py.test", - "--quiet", - "--cov=google.cloud", - "--cov=tests.unit", - "--cov-append", - "--cov-config=.coveragerc", - "--cov-report=", - "--cov-fail-under=0", - os.path.join("tests", "unit"), - *session.posargs, - ) - - -@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"]) -def unit(session): - """Run the unit test suite.""" - default(session) - - -@nox.session(python=["2.7", "3.7"]) -def system(session): - """Run the system test suite.""" - system_test_path = os.path.join("tests", "system.py") - system_test_folder_path = os.path.join("tests", "system") - # Sanity check: Only run tests if the environment variable is set. - if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): - session.skip("Credentials must be set via environment variable") - - system_test_exists = os.path.exists(system_test_path) - system_test_folder_exists = os.path.exists(system_test_folder_path) - # Sanity check: only run tests if found. - if not system_test_exists and not system_test_folder_exists: - session.skip("System tests were not found") - - # Use pre-release gRPC for system tests. - session.install("--pre", "grpcio") - - # Install all test dependencies, then install this package into the - # virtualenv's dist-packages. - session.install("mock", "pytest") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", "../test_utils/") - session.install("-e", ".") - - # Run py.test against the system tests. - if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) - if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) - - -@nox.session(python="3.7") -def cover(session): - """Run the final coverage report. - - This outputs the coverage report aggregating coverage from the unit - test runs (not system test runs), and then erases coverage data. - """ - session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=100") - - session.run("coverage", "erase") - - -@nox.session(python="3.7") -def docs(session): - """Build the docs for this library.""" - - session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark") - - shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) - session.run( - "sphinx-build", - "-W", # warnings as errors - "-T", # show full traceback on exception - "-N", # no colors - "-b", - "html", - "-d", - os.path.join("docs", "_build", "doctrees", ""), - os.path.join("docs", ""), - os.path.join("docs", "_build", "html", ""), - ) diff --git a/iam/setup.cfg b/iam/setup.cfg deleted file mode 100644 index 3bd555500e37..000000000000 --- a/iam/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[bdist_wheel] -universal = 1 diff --git a/iam/setup.py b/iam/setup.py deleted file mode 100644 index a74b425fd7a1..000000000000 --- a/iam/setup.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import io -import os - -import setuptools - -name = "google-cloud-iam" -description = "IAM Service Account Credentials API client library" -version = "0.2.1" -# Should be one of: -# 'Development Status :: 3 - Alpha' -# 'Development Status :: 4 - Beta' -# 'Development Status :: 5 - Production/Stable' -release_status = "Development Status :: 3 - Alpha" -dependencies = [ - "google-api-core[grpc] >= 1.14.0, < 2.0.0dev", - 'enum34; python_version < "3.4"', -] - -package_root = os.path.abspath(os.path.dirname(__file__)) - -readme_filename = os.path.join(package_root, "README.rst") -with io.open(readme_filename, encoding="utf-8") as readme_file: - readme = readme_file.read() - -packages = [ - package for package in setuptools.find_packages() if package.startswith("google") -] - -namespaces = ["google"] -if "google.cloud" in packages: - namespaces.append("google.cloud") - -setuptools.setup( - name=name, - version=version, - description=description, - long_description=readme, - author="Google LLC", - author_email="googleapis-packages@google.com", - license="Apache 2.0", - url="https://github.com/GoogleCloudPlatform/google-cloud-python", - classifiers=[ - release_status, - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Operating System :: OS Independent", - "Topic :: Internet", - ], - platforms="Posix; MacOS X; Windows", - packages=packages, - namespace_packages=namespaces, - install_requires=dependencies, - python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", - include_package_data=True, - zip_safe=False, -) diff --git a/iam/synth.metadata b/iam/synth.metadata deleted file mode 100644 index 806c27a78ac5..000000000000 --- a/iam/synth.metadata +++ /dev/null @@ -1,156 +0,0 @@ -{ - "updateTime": "2020-01-29T13:21:38.098637Z", - "sources": [ - { - "generator": { - "name": "artman", - "version": "0.44.4", - "dockerImage": "googleapis/artman@sha256:19e945954fc960a4bdfee6cb34695898ab21a8cf0bac063ee39b91f00a1faec8" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "cf3b61102ed5f36b827bc82ec39be09525f018c8", - "internalRef": "292034635", - "log": "cf3b61102ed5f36b827bc82ec39be09525f018c8\n Fix to protos for v1p1beta1 release of Cloud Security Command Center\n\nPiperOrigin-RevId: 292034635\n\n4e1cfaa7c0fede9e65d64213ca3da1b1255816c0\nUpdate the public proto to support UTF-8 encoded id for CatalogService API, increase the ListCatalogItems deadline to 300s and some minor documentation change\n\nPiperOrigin-RevId: 292030970\n\n9c483584f8fd5a1b862ae07973f4cc7bb3e46648\nasset: add annotations to v1p1beta1\n\nPiperOrigin-RevId: 292009868\n\ne19209fac29731d0baf6d9ac23da1164f7bdca24\nAdd the google.rpc.context.AttributeContext message to the open source\ndirectories.\n\nPiperOrigin-RevId: 291999930\n\nae5662960573f279502bf98a108a35ba1175e782\noslogin API: move file level option on top of the file to avoid protobuf.js bug.\n\nPiperOrigin-RevId: 291990506\n\neba3897fff7c49ed85d3c47fc96fe96e47f6f684\nAdd cc_proto_library and cc_grpc_library targets for Spanner and IAM protos.\n\nPiperOrigin-RevId: 291988651\n\n8e981acfd9b97ea2f312f11bbaa7b6c16e412dea\nBeta launch for PersonDetection and FaceDetection features.\n\nPiperOrigin-RevId: 291821782\n\n994e067fae3b21e195f7da932b08fff806d70b5d\nasset: add annotations to v1p2beta1\n\nPiperOrigin-RevId: 291815259\n\n244e1d2c89346ca2e0701b39e65552330d68545a\nAdd Playable Locations service\n\nPiperOrigin-RevId: 291806349\n\n909f8f67963daf45dd88d020877fb9029b76788d\nasset: add annotations to v1beta2\n\nPiperOrigin-RevId: 291805301\n\n3c39a1d6e23c1ef63c7fba4019c25e76c40dfe19\nKMS: add file-level message for CryptoKeyPath, it is defined in gapic yaml but not\nin proto files.\n\nPiperOrigin-RevId: 291420695\n\nc6f3f350b8387f8d1b85ed4506f30187ebaaddc3\ncontaineranalysis: update v1beta1 and bazel build with annotations\n\nPiperOrigin-RevId: 291401900\n\n92887d74b44e4e636252b7b8477d0d2570cd82db\nfix: fix the location of grpc config file.\n\nPiperOrigin-RevId: 291396015\n\ne26cab8afd19d396b929039dac5d874cf0b5336c\nexpr: add default_host and method_signature annotations to CelService\n\nPiperOrigin-RevId: 291240093\n\n06093ae3952441c34ec176d1f7431b8765cec0be\nirm: fix v1alpha2 bazel build by adding missing proto imports\n\nPiperOrigin-RevId: 291227940\n\na8a2514af326e4673063f9a3c9d0ef1091c87e6c\nAdd proto annotation for cloud/irm API\n\nPiperOrigin-RevId: 291217859\n\n8d16f76de065f530d395a4c7eabbf766d6a120fd\nGenerate Memcache v1beta2 API protos and gRPC ServiceConfig files\n\nPiperOrigin-RevId: 291008516\n\n3af1dabd93df9a9f17bf3624d3b875c11235360b\ngrafeas: Add containeranalysis default_host to Grafeas service\n\nPiperOrigin-RevId: 290965849\n\nbe2663fa95e31cba67d0cd62611a6674db9f74b7\nfix(google/maps/roads): add missing opening bracket\n\nPiperOrigin-RevId: 290964086\n\nfacc26550a0af0696e0534bc9cae9df14275aa7c\nUpdating v2 protos with the latest inline documentation (in comments) and adding a per-service .yaml file.\n\nPiperOrigin-RevId: 290952261\n\ncda99c1f7dc5e4ca9b1caeae1dc330838cbc1461\nChange api_name to 'asset' for v1p1beta1\n\nPiperOrigin-RevId: 290800639\n\n94e9e90c303a820ce40643d9129e7f0d2054e8a1\nAdds Google Maps Road service\n\nPiperOrigin-RevId: 290795667\n\na3b23dcb2eaecce98c600c7d009451bdec52dbda\nrpc: new message ErrorInfo, other comment updates\n\nPiperOrigin-RevId: 290781668\n\n26420ef4e46c37f193c0fbe53d6ebac481de460e\nAdd proto definition for Org Policy v1.\n\nPiperOrigin-RevId: 290771923\n\n7f0dab8177cf371ae019a082e2512de7ac102888\nPublish Routes Preferred API v1 service definitions.\n\nPiperOrigin-RevId: 290326986\n\nad6e508d0728e1d1bca6e3f328cd562718cb772d\nFix: Qualify resource type references with \"jobs.googleapis.com/\"\n\nPiperOrigin-RevId: 290285762\n\n58e770d568a2b78168ddc19a874178fee8265a9d\ncts client library\n\nPiperOrigin-RevId: 290146169\n\naf9daa4c3b4c4a8b7133b81588dd9ffd37270af2\nAdd more programming language options to public proto\n\nPiperOrigin-RevId: 290144091\n\nd9f2bbf2df301ef84641d4cec7c828736a0bd907\ntalent: add missing resource.proto dep to Bazel build target\n\nPiperOrigin-RevId: 290143164\n\n3b3968237451d027b42471cd28884a5a1faed6c7\nAnnotate Talent API.\nAdd gRPC service config for retry.\nUpdate bazel file with google.api.resource dependency.\n\nPiperOrigin-RevId: 290125172\n\n0735b4b096872960568d1f366bfa75b7b0e1f1a3\nWeekly library update.\n\nPiperOrigin-RevId: 289939042\n\n8760d3d9a4543d7f9c0d1c7870aca08b116e4095\nWeekly library update.\n\nPiperOrigin-RevId: 289939020\n\n8607df842f782a901805187e02fff598145b0b0e\nChange Talent API timeout to 30s.\n\nPiperOrigin-RevId: 289912621\n\n908155991fe32570653bcb72ecfdcfc896642f41\nAdd Recommendations AI V1Beta1\n\nPiperOrigin-RevId: 289901914\n\n5c9a8c2bebd8b71aa66d1cc473edfaac837a2c78\nAdding no-arg method signatures for ListBillingAccounts and ListServices\n\nPiperOrigin-RevId: 289891136\n\n50b0e8286ac988b0593bd890eb31fef6ea2f5767\nlongrunning: add grpc service config and default_host annotation to operations.proto\n\nPiperOrigin-RevId: 289876944\n\n6cac27dabe51c54807b0401698c32d34998948a9\n Updating default deadline for Cloud Security Command Center's v1 APIs.\n\nPiperOrigin-RevId: 289875412\n\nd99df0d67057a233c711187e0689baa4f8e6333d\nFix: Correct spelling in C# namespace option\n\nPiperOrigin-RevId: 289709813\n\n2fa8d48165cc48e35b0c62e6f7bdade12229326c\nfeat: Publish Recommender v1 to GitHub.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289619243\n\n9118db63d1ab493a2e44a3b4973fde810a835c49\nfirestore: don't retry reads that fail with Aborted\n\nFor transaction reads that fail with ABORTED, we need to rollback and start a new transaction. Our current configuration makes it so that GAPIC retries ABORTED reads multiple times without making any progress. Instead, we should retry at the transaction level.\n\nPiperOrigin-RevId: 289532382\n\n1dbfd3fe4330790b1e99c0bb20beb692f1e20b8a\nFix bazel build\nAdd other langauges (Java was already there) for bigquery/storage/v1alpha2 api.\n\nPiperOrigin-RevId: 289519766\n\nc06599cdd7d11f8d3fd25f8d3249e5bb1a3d5d73\nInitial commit of google.cloud.policytroubleshooter API, The API helps in troubleshooting GCP policies. Refer https://cloud.google.com/iam/docs/troubleshooting-access for more information\n\nPiperOrigin-RevId: 289491444\n\nfce7d80fa16ea241e87f7bc33d68595422e94ecd\nDo not pass samples option for Artman config of recommender v1 API.\n\nPiperOrigin-RevId: 289477403\n\nef179e8c61436297e6bb124352e47e45c8c80cb1\nfix: Address missing Bazel dependency.\n\nBazel builds stopped working in 06ec6d5 because\nthe google/longrunning/operations.proto file took\nan import from google/api/client.proto, but that\nimport was not added to BUILD.bazel.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289446074\n\n8841655b242c84fd691d77d7bcf21b61044f01ff\nMigrate Data Labeling v1beta1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289446026\n\n06ec6d5d053fff299eaa6eaa38afdd36c5e2fc68\nAdd annotations to google.longrunning.v1\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289413169\n\n0480cf40be1d3cc231f4268a2fdb36a8dd60e641\nMigrate IAM Admin v1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289411084\n\n1017173e9adeb858587639af61889ad970c728b1\nSpecify a C# namespace for BigQuery Connection v1beta1\n\nPiperOrigin-RevId: 289396763\n\nb08714b378e8e5b0c4ecdde73f92c36d6303b4b6\nfix: Integrate latest proto-docs-plugin fix.\nFixes dialogflow v2\n\nPiperOrigin-RevId: 289189004\n\n51217a67e79255ee1f2e70a6a3919df082513327\nCreate BUILD file for recommender v1\n\nPiperOrigin-RevId: 289183234\n\nacacd87263c0a60e458561b8b8ce9f67c760552a\nGenerate recommender v1 API protos and gRPC ServiceConfig files\n\nPiperOrigin-RevId: 289177510\n\n9d2f7133b97720b1fa3601f6dcd30760ba6d8a1e\nFix kokoro build script\n\nPiperOrigin-RevId: 289166315\n\nc43a67530d2a47a0220cad20ca8de39b3fbaf2c5\ncloudtasks: replace missing RPC timeout config for v2beta2 and v2beta3\n\nPiperOrigin-RevId: 289162391\n\n4cefc229a9197236fc0adf02d69b71c0c5cf59de\nSynchronize new proto/yaml changes.\n\nPiperOrigin-RevId: 289158456\n\n56f263fe959c50786dab42e3c61402d32d1417bd\nCatalog API: Adding config necessary to build client libraries\n\nPiperOrigin-RevId: 289149879\n\n4543762b23a57fc3c53d409efc3a9affd47b6ab3\nFix Bazel build\nbilling/v1 and dialogflow/v2 remain broken (not bazel-related issues).\nBilling has wrong configuration, dialogflow failure is caused by a bug in documentation plugin.\n\nPiperOrigin-RevId: 289140194\n\nc9dce519127b97e866ca133a01157f4ce27dcceb\nUpdate Bigtable docs\n\nPiperOrigin-RevId: 289114419\n\n802c5c5f2bf94c3facb011267d04e71942e0d09f\nMigrate DLP to proto annotations (but not GAPIC v2).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289102579\n\n6357f30f2ec3cff1d8239d18b707ff9d438ea5da\nRemove gRPC configuration file that was in the wrong place.\n\nPiperOrigin-RevId: 289096111\n\n360a8792ed62f944109d7e22d613a04a010665b4\n Protos for v1p1beta1 release of Cloud Security Command Center\n\nPiperOrigin-RevId: 289011995\n\na79211c20c4f2807eec524d00123bf7c06ad3d6e\nRoll back containeranalysis v1 to GAPIC v1.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288999068\n\n9e60345ba603e03484a8aaa33ce5ffa19c1c652b\nPublish Routes Preferred API v1 proto definitions.\n\nPiperOrigin-RevId: 288941399\n\nd52885b642ad2aa1f42b132ee62dbf49a73e1e24\nMigrate the service management API to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288909426\n\n6ace586805c08896fef43e28a261337fcf3f022b\ncloudtasks: replace missing RPC timeout config\n\nPiperOrigin-RevId: 288783603\n\n51d906cabee4876b12497054b15b05d4a50ad027\nImport of Grafeas from Github.\n\nUpdate BUILD.bazel accordingly.\n\nPiperOrigin-RevId: 288783426\n\n5ef42bcd363ba0440f0ee65b3c80b499e9067ede\nMigrate Recommender v1beta1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288713066\n\n94f986afd365b7d7e132315ddcd43d7af0e652fb\nMigrate Container Analysis v1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288708382\n\n7a751a279184970d3b6ba90e4dd4d22a382a0747\nRemove Container Analysis v1alpha1 (nobody publishes it).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288707473\n\n3c0d9c71242e70474b2b640e15bb0a435fd06ff0\nRemove specious annotation from BigQuery Data Transfer before\nanyone accidentally does anything that uses it.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288701604\n\n1af307a4764bd415ef942ac5187fa1def043006f\nMigrate BigQuery Connection to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288698681\n\n08b488e0660c59842a7dee0e3e2b65d9e3a514a9\nExposing cloud_catalog.proto (This API is already available through REST)\n\nPiperOrigin-RevId: 288625007\n\na613482977e11ac09fa47687a5d1b5a01efcf794\nUpdate the OS Login v1beta API description to render better in the UI.\n\nPiperOrigin-RevId: 288547940\n\n5e182b8d9943f1b17008d69d4c7e865dc83641a7\nUpdate the OS Login API description to render better in the UI.\n\nPiperOrigin-RevId: 288546443\n\ncb79155f596e0396dd900da93872be7066f6340d\nFix: Add a resource annotation for Agent\nFix: Correct the service name in annotations for Intent and SessionEntityType\n\nPiperOrigin-RevId: 288441307\n\nf7f6e9daec3315fd47cb638789bd8415bf4a27cc\nAdded cloud asset api v1p1beta1\n\nPiperOrigin-RevId: 288427239\n\nf2880f5b342c6345f3dcaad24fcb3c6ca9483654\nBilling account API: Adding config necessary to build client libraries\n\nPiperOrigin-RevId: 288351810\n\ndc250ffe071729f8f8bef9d6fd0fbbeb0254c666\nFix: Remove incorrect resource annotations in requests\n\nPiperOrigin-RevId: 288321208\n\n91ef2d9dd69807b0b79555f22566fb2d81e49ff9\nAdd GAPIC annotations to Cloud KMS (but do not migrate the GAPIC config yet).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 287999179\n\n" - } - }, - { - "template": { - "name": "python_library", - "origin": "synthtool.gcp", - "version": "2019.10.17" - } - } - ], - "destinations": [ - { - "client": { - "source": "googleapis", - "apiName": "iam_credentials", - "apiVersion": "v1", - "language": "python", - "generator": "gapic", - "config": "google/iam/credentials/artman_iamcredentials_v1.yaml" - } - } - ], - "newFiles": [ - { - "path": ".coveragerc" - }, - { - "path": ".flake8" - }, - { - "path": ".repo-metadata.json" - }, - { - "path": "CHANGELOG.md" - }, - { - "path": "LICENSE" - }, - { - "path": "MANIFEST.in" - }, - { - "path": "README.rst" - }, - { - "path": "docs/README.rst" - }, - { - "path": "docs/_static/custom.css" - }, - { - "path": "docs/_templates/layout.html" - }, - { - "path": "docs/changelog.md" - }, - { - "path": "docs/conf.py" - }, - { - "path": "docs/gapic/v1/api.rst" - }, - { - "path": "docs/gapic/v1/types.rst" - }, - { - "path": "docs/index.rst" - }, - { - "path": "google/__init__.py" - }, - { - "path": "google/cloud/__init__.py" - }, - { - "path": "google/cloud/iam_credentials.py" - }, - { - "path": "google/cloud/iam_credentials_v1/__init__.py" - }, - { - "path": "google/cloud/iam_credentials_v1/gapic/__init__.py" - }, - { - "path": "google/cloud/iam_credentials_v1/gapic/iam_credentials_client.py" - }, - { - "path": "google/cloud/iam_credentials_v1/gapic/iam_credentials_client_config.py" - }, - { - "path": "google/cloud/iam_credentials_v1/gapic/transports/__init__.py" - }, - { - "path": "google/cloud/iam_credentials_v1/gapic/transports/iam_credentials_grpc_transport.py" - }, - { - "path": "google/cloud/iam_credentials_v1/proto/__init__.py" - }, - { - "path": "google/cloud/iam_credentials_v1/proto/common.proto" - }, - { - "path": "google/cloud/iam_credentials_v1/proto/common_pb2.py" - }, - { - "path": "google/cloud/iam_credentials_v1/proto/common_pb2_grpc.py" - }, - { - "path": "google/cloud/iam_credentials_v1/proto/iamcredentials.proto" - }, - { - "path": "google/cloud/iam_credentials_v1/proto/iamcredentials_pb2.py" - }, - { - "path": "google/cloud/iam_credentials_v1/proto/iamcredentials_pb2_grpc.py" - }, - { - "path": "google/cloud/iam_credentials_v1/types.py" - }, - { - "path": "noxfile.py" - }, - { - "path": "setup.cfg" - }, - { - "path": "setup.py" - }, - { - "path": "synth.metadata" - }, - { - "path": "synth.py" - }, - { - "path": "tests/unit/gapic/v1/test_iam_credentials_client_v1.py" - } - ] -} \ No newline at end of file diff --git a/iam/synth.py b/iam/synth.py deleted file mode 100644 index 8c486fa26a0d..000000000000 --- a/iam/synth.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This script is used to synthesize generated parts of this library.""" - -import synthtool as s -from synthtool import gcp - -gapic = gcp.GAPICGenerator() -common = gcp.CommonTemplates() - -# ---------------------------------------------------------------------------- -# Generate automl GAPIC layer -# ---------------------------------------------------------------------------- -library = gapic.py_library( - "iam_credentials", - "v1", - config_path="/google/iam/credentials/artman_iamcredentials_v1.yaml", - artman_output_name="iamcredentials-v1", - include_protos=True, -) - -excludes = [ - "README.rst", - "setup.py", - "docs/index.rst", - "nox.py", -] -s.copy(library, excludes=excludes) - -s.replace( - "google/**/*.py", - "google-cloud-iamcredentials", - "google-cloud-iam" -) -s.replace( - "docs/**/*.py", - "google-cloud-iamcredentials", - "google-cloud-iam" -) - -s.replace( - "**/*.py", - "from google\.iam\.credentials\.v1 import common_pb2", - "from google.cloud.iam_credentials_v1.proto import common_pb2" -) -s.replace( - "**/*.py", - "from google\.iam\.credentials\.v1 import iamcredentials_pb2_grpc", - "from google.cloud.iam_credentials_v1.proto import iamcredentials_pb2_grpc" -) - -s.replace( - "google/cloud/iam_credentials_v1/proto/common_pb2.py", - "\"\"\"Attributes:\n", - "\"\"\"\nAttributes:\n" -) - -# ---------------------------------------------------------------------------- -# Add templated files -# ---------------------------------------------------------------------------- -templated_files = common.py_library(unit_cov_level=97, cov_level=100) -s.move(templated_files) - -s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/iam/tests/unit/gapic/v1/test_iam_credentials_client_v1.py b/iam/tests/unit/gapic/v1/test_iam_credentials_client_v1.py deleted file mode 100644 index b90f179a3394..000000000000 --- a/iam/tests/unit/gapic/v1/test_iam_credentials_client_v1.py +++ /dev/null @@ -1,225 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit tests.""" - -import mock -import pytest - -from google.cloud import iam_credentials_v1 -from google.cloud.iam_credentials_v1.proto import common_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestIAMCredentialsClient(object): - def test_generate_access_token(self): - # Setup Expected Response - access_token = "accessToken-1938933922" - expected_response = {"access_token": access_token} - expected_response = common_pb2.GenerateAccessTokenResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup Request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - scope = [] - - response = client.generate_access_token(name, scope) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = common_pb2.GenerateAccessTokenRequest(name=name, scope=scope) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_generate_access_token_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - scope = [] - - with pytest.raises(CustomException): - client.generate_access_token(name, scope) - - def test_generate_id_token(self): - # Setup Expected Response - token = "token110541305" - expected_response = {"token": token} - expected_response = common_pb2.GenerateIdTokenResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup Request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - audience = "audience975628804" - - response = client.generate_id_token(name, audience) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = common_pb2.GenerateIdTokenRequest( - name=name, audience=audience - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_generate_id_token_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - audience = "audience975628804" - - with pytest.raises(CustomException): - client.generate_id_token(name, audience) - - def test_sign_blob(self): - # Setup Expected Response - key_id = "keyId-1134673157" - signed_blob = b"-32" - expected_response = {"key_id": key_id, "signed_blob": signed_blob} - expected_response = common_pb2.SignBlobResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup Request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - payload = b"-114" - - response = client.sign_blob(name, payload) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = common_pb2.SignBlobRequest(name=name, payload=payload) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_sign_blob_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - payload = b"-114" - - with pytest.raises(CustomException): - client.sign_blob(name, payload) - - def test_sign_jwt(self): - # Setup Expected Response - key_id = "keyId-1134673157" - signed_jwt = "signedJwt-979546844" - expected_response = {"key_id": key_id, "signed_jwt": signed_jwt} - expected_response = common_pb2.SignJwtResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup Request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - payload = "-114" - - response = client.sign_jwt(name, payload) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = common_pb2.SignJwtRequest(name=name, payload=payload) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_sign_jwt_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = iam_credentials_v1.IAMCredentialsClient() - - # Setup request - name = client.service_account_path("[PROJECT]", "[SERVICE_ACCOUNT]") - payload = "-114" - - with pytest.raises(CustomException): - client.sign_jwt(name, payload) diff --git a/pubsub/.coveragerc b/pubsub/.coveragerc deleted file mode 100644 index b178b094aa1d..000000000000 --- a/pubsub/.coveragerc +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[run] -branch = True - -[report] -fail_under = 100 -show_missing = True -exclude_lines = - # Re-enable the standard pragma - pragma: NO COVER - # Ignore debug-only repr - def __repr__ - # Ignore abstract methods - raise NotImplementedError -omit = - */gapic/*.py - */proto/*.py - */core/*.py - */site-packages/*.py \ No newline at end of file diff --git a/pubsub/.flake8 b/pubsub/.flake8 deleted file mode 100644 index 0268ecc9c55c..000000000000 --- a/pubsub/.flake8 +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[flake8] -ignore = E203, E266, E501, W503 -exclude = - # Exclude generated code. - **/proto/** - **/gapic/** - *_pb2.py - - # Standard linting exemptions. - __pycache__, - .git, - *.pyc, - conf.py diff --git a/pubsub/.repo-metadata.json b/pubsub/.repo-metadata.json deleted file mode 100644 index e14db4392f0a..000000000000 --- a/pubsub/.repo-metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "pubsub", - "name_pretty": "Google Cloud Pub/Sub", - "product_documentation": "https://cloud.google.com/pubsub/docs/", - "client_documentation": "https://googleapis.dev/python/pubsub/latest", - "issue_tracker": "https://issuetracker.google.com/savedsearches/559741", - "release_level": "ga", - "language": "python", - "repo": "googleapis/google-cloud-python", - "distribution_name": "google-cloud-pubsub", - "api_id": "pubsub.googleapis.com", - "requires_billing": true -} diff --git a/pubsub/CHANGELOG.md b/pubsub/CHANGELOG.md deleted file mode 100644 index ddca773a09a7..000000000000 --- a/pubsub/CHANGELOG.md +++ /dev/null @@ -1,610 +0,0 @@ -# Changelog - -[PyPI History][1] - -[1]: https://pypi.org/project/google-cloud-pubsub/#history - -## 1.1.0 - -12-09-2019 18:51 PST - -### Implementation Changes -- Update client configurations (via synth). ([#9784](https://github.com/googleapis/google-cloud-python/pull/9784)) -- Include request overhead when computing publish batch size overflow. ([#9911](https://github.com/googleapis/google-cloud-python/pull/9911)) -- Split large (mod)ACK requests into smaller ones. ([#9594](https://github.com/googleapis/google-cloud-python/pull/9594)) -- Fix messages delivered multiple times despite a long ACK deadline. ([#9525](https://github.com/googleapis/google-cloud-python/pull/9525)) -- Update batching and flow control parameters to be same as the other client libraries. ([#9597](https://github.com/googleapis/google-cloud-python/pull/9597)) -- Add `StreamingPullManager._should_terminate`. ([#9335](https://github.com/googleapis/google-cloud-python/pull/9335)) - -### New Features -- Add stop method. ([#9365](https://github.com/googleapis/google-cloud-python/pull/9365)) - -### Dependencies -- Add Python 2 sunset banner to documentation. ([#9036](https://github.com/googleapis/google-cloud-python/pull/9036)) - -### Documentation -- Change spacing in docs templates (via synth). ([#9759](https://github.com/googleapis/google-cloud-python/pull/9759)) - -### Internal / Testing Changes -- Refactor fake leaser test helper. ([#9632](https://github.com/googleapis/google-cloud-python/pull/9632)) -- Add subscriber role test for streaming. ([#9507](https://github.com/googleapis/google-cloud-python/pull/9507)) - -## 1.0.2 - -09-30-2019 11:57 PDT - - -### Implementation Changes - -- Streaming pull shouldn't need `subscriptions.get` permission ([#9360](https://github.com/googleapis/google-cloud-python/pull/9360)). - -## 1.0.1 - -09-27-2019 07:01 PDT - - -### Implementation Changes -- Set default stream ACK deadline to subscriptions'. ([#9268](https://github.com/googleapis/google-cloud-python/pull/9268)) - -### Documentation -- Fix intersphinx reference to requests. ([#9294](https://github.com/googleapis/google-cloud-python/pull/9294)) -- Link to correct TimeoutError in futures docs. ([#9216](https://github.com/googleapis/google-cloud-python/pull/9216)) - -### Internal / Testing Changes -- Adjust messaging RPC timeout settings (via synth). [#9279](https://github.com/googleapis/google-cloud-python/pull/9279) - -## 1.0.0 - -08-29-2019 09:27 PDT - -### Implementation Changes -- Add 'ReceivedMessage.delivery_attempt' field (via synth). ([#9098](https://github.com/googleapis/google-cloud-python/pull/9098)) -- Remove send/recv msg size limit, update docstrings (via synth). ([#8964](https://github.com/googleapis/google-cloud-python/pull/8964)) - -### Documentation -- Update docstrings for client kwargs and fix return types uris ([#9037](https://github.com/googleapis/google-cloud-python/pull/9037)) -- Remove CI for gh-pages, use googleapis.dev for api_core refs. ([#9085](https://github.com/googleapis/google-cloud-python/pull/9085)) -- Remove compatability badges from READMEs. ([#9035](https://github.com/googleapis/google-cloud-python/pull/9035)) - -### Internal / Testing Changes -- Add dead-letter-policy field in preparation for its implementation (via synth) ([#9078](https://github.com/googleapis/google-cloud-python/pull/9078)) - -## 0.45.0 - -07-31-2019 02:03 PDT - - -### Implementation Changes - -- Remove deprecated methods and settings ([#8836](https://github.com/googleapis/google-cloud-python/pull/8836)) - - -### Documentation - -- Use double backticks for ReST correctness. ([#8829](https://github.com/googleapis/google-cloud-python/pull/8829)) -- Update intersphinx mapping for requests. ([#8805](https://github.com/googleapis/google-cloud-python/pull/8805)) - -## 0.44.0 - -07-29-2019 04:28 PDT - - -### Implementation Changes - -- PubSub: Deprecate several FlowControl settings and things in Message class ([#8796](https://github.com/googleapis/google-cloud-python/pull/8796)) - -### Documentation - -- Pub/Sub: document regional endpoint ([#8789](https://github.com/googleapis/google-cloud-python/pull/8789)) - -## 0.43.0 - -07-24-2019 17:13 PDT - - -### Implementation Changes -- Accomodate new location of 'IAMPolicyStub' (via synth). ([#8680](https://github.com/googleapis/google-cloud-python/pull/8680)) -- Use kwargs in test_subscriber_client ([#8414](https://github.com/googleapis/google-cloud-python/pull/8414)) - -### New Features -- Add 'options_' argument to clients' 'get_iam_policy'; pin black version (via synth). ([#8657](https://github.com/googleapis/google-cloud-python/pull/8657)) -- Add 'client_options' support, update list method docstrings (via synth). ([#8518](https://github.com/googleapis/google-cloud-python/pull/8518)) - -### Dependencies -- Bump minimum version for google-api-core to 1.14.0. ([#8709](https://github.com/googleapis/google-cloud-python/pull/8709)) -- Update pin for 'grpc-google-iam-v1' to 0.12.3+. ([#8647](https://github.com/googleapis/google-cloud-python/pull/8647)) - -### Documentation -- Link to googleapis.dev documentation in READMEs. ([#8705](https://github.com/googleapis/google-cloud-python/pull/8705)) -- Add compatibility check badges to READMEs. ([#8288](https://github.com/googleapis/google-cloud-python/pull/8288)) -- Fix typo in publisher index. ([#8619](https://github.com/googleapis/google-cloud-python/pull/8619)) -- Document how to choose the PubSub auth method ([#8429](https://github.com/googleapis/google-cloud-python/pull/8429)) -- Document different PuSub received message types ([#8468](https://github.com/googleapis/google-cloud-python/pull/8468)) -- PubSub: Document batch settings, make synth operations idempotent ([#8448](https://github.com/googleapis/google-cloud-python/pull/8448)) -- Add custom docstrings for FlowControl enum and values (via synth). ([#8426](https://github.com/googleapis/google-cloud-python/pull/8426)) - -### Internal / Testing Changes -- Add docs job to publish to googleapis.dev. ([#8464](https://github.com/googleapis/google-cloud-python/pull/8464)) -- Add system tests for PubSub clients ([#8277](https://github.com/googleapis/google-cloud-python/pull/8277)) - -## 0.42.1 - -06-18-2019 15:14 PDT - - -### Implementation Changes -- Increase the minimum allowed version for api core. ([#8419](https://github.com/googleapis/google-cloud-python/pull/8419)) -- Allow kwargs to be passed to create_channel. ([#8399](https://github.com/googleapis/google-cloud-python/pull/8399)) - -## 0.42.0 - -06-18-2019 11:32 PDT - -### Implementation Changes -- Core: Mitigate busy reopen loop in ResumableBidiRpc consuming 100% CPU ([#8193](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8193)) -- Pub/Sub: Increase initial_rpc_timeout for messaging (via synth). ([#8219](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8219)) -- PubSub: Release the state lock before calling the publish api ([#8234](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8234)) -- Pub/Sub: Expose publish retry settings ([#8231](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8231)) -- Prevent unhandled background error on SPM shutdown ([#8111](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8111)) -- Update timeouts, blacken noxfile.py, setup.py (via synth). ([#8128](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8128)) -- PubSub: Fix streaming pull incorrectly handling FlowControl max_messages setting ([#7948](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7948)) - -### Documentation -- Document PubSub FlowControl settings ([#8293](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8293)) -- Replace readthedocs links with links to github docs. ([#8291](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8291)) -- Pub/Sub: surface publish future in documentation ([#8229](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8229)) -- Pubsub: Separate subscriber and publish future documentation. ([#8205](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8205)) -- Drop mention of long-removed 'policy' object. ([#8081](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8081)) - -### Internal / Testing Changes -- Pub/Sub: staticmethod check ([#8091](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8091)) -- Add empty lines (via synth). ([#8067](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/8067)) - -## 0.41.0 - -05-15-2019 13:57 PDT - - -### New Features -- Add `kms_key_name` arg to `create_topic`; remove BETA warnings (via synth). ([#7936](https://github.com/googleapis/google-cloud-python/pull/7936)) -- Add message ordering (via synth). ([#7551](https://github.com/googleapis/google-cloud-python/pull/7551)) - -### Implementation Changes -- Propagate subscribe callback errors to main thread ([#7954](https://github.com/googleapis/google-cloud-python/pull/7954)) -- Fix pubsub Streaming Pull shutdown on RetryError ([#7863](https://github.com/googleapis/google-cloud-python/pull/7863)) -- Make PubSub subscriber Scheduler inherit from ABC ([#7690](https://github.com/googleapis/google-cloud-python/pull/7690)) -- Add routing header to method metadata (via synth). ([#7623](https://github.com/googleapis/google-cloud-python/pull/7623)) - -### Internal / Testing Changes -- Remove classifier for Python 3.4 for end-of-life. ([#7535](https://github.com/googleapis/google-cloud-python/pull/7535)) -- Add nox session `docs` (via synth). ([#7778](https://github.com/googleapis/google-cloud-python/pull/7778)) -- Pub/Sub (nit): wrong var name in sample ([#7705](https://github.com/googleapis/google-cloud-python/pull/7705)) - -## 0.40.0 - -03-15-2019 14:09 PDT - - -### Implementation Changes -- Propagate 'RetryError' in 'PublisherClient.publish'. ([#7071](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7071)) -- Protoc-generated serialization update.. ([#7091](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7091)) - -### New Features -- Add 'authentication_method' to 'PushConfig' (via synth). ([#7512](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7512)) -- Add protos as an artifact to library ([#7205](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7205)) -- Pub/sub: pass transport w/ custom channel to GAPIC API clients. ([#7008](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7008)) - -### Dependencies - -### Documentation -- Updated client library documentation URLs. ([#7307](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7307)) -- Update copyright headers -- Fix broken docstring cross-reference links. ([#7132](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7132)) -- Docstring changes from updates to .proto files. ([#7054](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/7054)) -- Pick up stub docstring fix in GAPIC generator. ([#6978](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6978)) - -### Internal / Testing Changes -- Copy proto files alongside protoc versions. - -## 0.39.1 - -12-17-2018 16:57 PST - - -### Implementation Changes -- Initialize `StreamingPullFuture._cancelled` as True. ([#6901](https://github.com/googleapis/google-cloud-python/pull/6901)) -- Import `iam.policy` from `google.api_core`. ([#6741](https://github.com/googleapis/google-cloud-python/pull/6741)) - -### Documentation -- Document Python 2 deprecation ([#6910](https://github.com/googleapis/google-cloud-python/pull/6910)) -- Emphasize that returned futures may differ from stdlib futures. ([#6875](https://github.com/googleapis/google-cloud-python/pull/6875)) - -### Internal / Testing Changes -- Add baseline for synth.metadata -- Update noxfile. -- blacken all gen'd libs ([#6792](https://github.com/googleapis/google-cloud-python/pull/6792)) -- omit local deps ([#6701](https://github.com/googleapis/google-cloud-python/pull/6701)) -- Run black at end of synth.py ([#6698](https://github.com/googleapis/google-cloud-python/pull/6698)) -- Run Black on Generated libraries ([#6666](https://github.com/googleapis/google-cloud-python/pull/6666)) -- Add templates for flake8, coveragerc, noxfile, and black. ([#6642](https://github.com/googleapis/google-cloud-python/pull/6642)) - -## 0.39.0 - -11-27-2018 13:32 PST - -### Implementation Changes -- Pick up fixes to GAPIC generator. ([#6503](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6503)) -- Override client classmethod factories inherited from GAPIC. ([#6453](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6453)) -- Fix imports for hand-written client docstring examples. ([#6345](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6345)) -- Fix path for patch of 'bidi' elements. ([#6243](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6243)) -- Move bidi to api-core. ([#6211](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6211)) -- Re-generate library using pubsub/synth.py ([#6059](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6059)) -- Re-generate library using pubsub/synth.py ([#5978](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5978)) - -### New Features -- Add 'expiration_policy' to subscriber client. ([#6223](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6223)) - -### Dependencies -- Bump minimum 'api_core' version for all GAPIC libs to 1.4.1. ([#6391](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6391)) -- Update IAM version in dependencies. ([#6362](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6362)) -- Bump minimum 'api_core' version to '1.4.1'. ([#6134](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6134)) - -### Documentation -- Fix client_info bug, update docstrings. ([#6418](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6418)) -- Fix docstring reference to wrong future class. ([#6382](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6382)) -- Normalize use of support level badges. ([#6159](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6159)) -- Update subscriber example in README to current patterns. ([#6194](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6194)) -- Prep pubsub docs for repo split. ([#6001](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6001)) - -### Internal / Testing Changes -- Fix error from new flake8 version. ([#6346](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6346)) -- Use new Nox. ([#6175](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/6175)) - -## 0.38.0 - -### Implementation Changes - -- Fix race condition in recv()'s usage of self.call. ([#5935](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5935)) -- Re-generate the underlying library from protos. ([#5953](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5953)) -- Change 'BatchSettings.max_bytes' default. ([#5899](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5899)) -- Fix race condition where pending Ack IDs can be modified by another thread. ([#5929](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5929)) - -### Internal / Testing Changes - -- Nox: use inplace installs ([#5865](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5865)) - -## 0.37.2 - -### Implementation Changes - -- Fix classmethod wrapping (#5826) - -### Documentation - -- Fix Sphinx rendering for publisher client. (#5822) - -### Internal / Testing Changes - -- Re-generate library, removing obsolete synth modifications. (#5825) -- Add test for testing invoking a wrapped class method on the class itself (#5828) - -## 0.37.1 - -### Implementation Changes - -- Make get_initial_request more resilient to race conditions. (#5803) - -## 0.37.0 - -### Implementation Changes - -- Make Publisher batch-related interfaces private (#5784) - -## 0.36.0 - -### Implementation Changes -- Pubsub: Make 'Message.publish_time' return datetime (#5633) -- Ensure SPM methods check that 'self._consumer' is not None before use. (#5758) - -### New Features -- PubSub: add geo-fencing support (#5769) -- Add 'Message.ack_id' property. (#5693) - -## 0.35.4 - -### Implementation Changes - -- Recover streams during the gRPC error callback. (#5446) -- Use operational lock when checking for activity on streams. (#5445) - -## 0.35.3 - -### Implementation Changes - -- Add additional error handling to unary RPCs (#5438) - -## 0.35.2 - -### Implementation Changes -- Add heartbeating to the streaming pull manager (#5413) -- Fix retrying of bidirectional RPCs and closing the streaming pull manager (#5412) - -## 0.35.1 - -### Implementation Changes -- Catch errors when re-retying send() or recv() in addition to open() (#5402) - -## 0.35.0 - -### Implementation Changes - -- Send requests during streaming pull over a separate unary RPC (#5377) -- Initialize references to helper threads before starting them (#5374) -- Make leaser exit more quickly (#5373) -- Make re-open failures bubble to callbacks (#5372) -- Avoid overwriting '__module__' of messages from shared modules. (#5364) -- Normalize overflow handling for max count and bytes (#5343) - -### New Features - -- Restore the synchronous pull method (#5379) -- Promote subscribe_experimental() to subscribe(), remove old subscriber implementation. (#5274) -- Wire up scheduler argument for subscribe() (#5279) - -### Documentation - -- Add link to streaming pull behavior documentation (#5378) -- Fix example in subscribe's documentation (#5375) - -### Internal / Testing Changes - -- Add Test runs for Python 3.7 and remove 3.4 (#5295) -- Modify system tests to use prerelease versions of grpcio (#5304) - -## 0.34.0 - -### Implementation Changes - -- Lower the flow control defaults. (#5248) - -### New Features - -- A new implementation of the subscriber has been added. This is available as `SubscriberClient.subscribe_experimental`. In the next release, this will be replace the current `subscribe` method. If you use this, please report your -findings to us on GitHub. (#5189, #5201, #5210, #5229, #5230, #5237, #5256) - -### Dependencies - -- Remove psutil dependency. (#5248) - -## 0.33.1 - -### Implementation changes - -- Surface publish RPC errors back to the publish futures (#5124) -- Make the pausable response iterator aware of the RPC state to prevent deadlock (#5108) -- Properly handle graceful stop in request generator (#5097) - -## 0.33.0 - -### Implementation changes - -- Drop leased messages after flow_control.max_lease_duration has passed. (#5020) -- Fix mantain leases to not modack messages it just dropped (#5045) -- Avoid race condition in maintain_leases by copying leased_messages (#5035) -- Retry subscription stream on InternalServerError, Unknown, and GatewayTimeout (#5021) -- Use the rpc's status to determine when to exit the request generator thread (#5054) -- Fix missing iter on request stream (#5078) -- Nack messages when the subscriber callback errors (#5019) - -### Testing - -- pubsub nox.py cleanup (#5056) -- Fix test that checks for retryable exceptions (#5034) - -## 0.32.1 - -### Dependencies - -- Update dependency range for api-core to include v1.0.0 releases (#4944) - -### Testing and internal changes - -- Install local dependencies when running lint (#4936) -- Re-enable lint for tests, remove usage of pylint (#4921) - -## 0.32.0 - -### Implementation changes - -- Added support for streaming pull receipts. (#4878) - -## 0.31.0 - -### New features - -- Added the ability for subscriber to batch requests. (#4895) -- Added pending request backpressure for subscriber. (#4892) - -### Implementation changes - -- Raise `ValueError` when a message is too large for a batch. (#4872) -- Updated the default batch size to 10 MB. (#4857) -- Allow a custom `Event` type in Pub / Sub futures. (#4643) - -### Documentation - -- Clarify that `modify_ack_deadline` resets the deadline. (#4822) - -### Testing - -- Fix unit test for default `max_bytes` value. (#4860) - -## 0.30.1 - -### Notable Implementation Changes - -- Moving lock factory used in publisher client to the Batch - implementation (#4628). -- Use a UUID (rather than a sentinel object) on `Future` (#4634). -- Apply scopes to explicitly provided credentials if needed (#4594). - Fixes #4479. This feature comes as part of `google-api-core==0.1.3`. - -### Dependencies - -- Upgrading to `google-api-core==0.1.3` which depends on the latest - `grpcio==1.8.2` (#4642). This fixes #4600. For details, see related - gRPC [bug](https://github.com/grpc/grpc/issues/9688) and - [fix](https://github.com/grpc/grpc/pull/13665). - -PyPI: https://pypi.org/project/google-cloud-pubsub/0.30.1/ - -## 0.30.0 - -### Notable Implementation Changes - -- Dropping redundant `Policy._paused` data member (#4568). -- Removing redundant "active" check in policy (#4603). -- Adding a `Consumer.active` property (#4604). -- Making it impossible to call `Policy.open()` on an already opened - policy (#4606). -- **Bug fix** (#4575): Fix bug with async publish for batches. There - were two related bugs. The first: if a batch exceeds the `max_messages` - from the batch settings, then the `commit()` will fail. The second: - when a "monitor" worker calls `commit()` after `max_latency` seconds, - a failure can occur if a new message is added to the batch **during** - the commit. To fix, the following changes were implemented: - - Adding a "STARTING" status for `Batch.commit()` (#4614). This - fixes the issue when the batch exceeds `max_messages`. - - Adding extra check in `Batch.will_accept` for the number of - messages (#4612). - - Moving `will_accept()` check out of `PublisherClient.batch()` - factory (#4613). - - Checking `Batch.will_accept` in thread-safe way (#4616). -- **Breaking API change**: As part of #4613, changing `PublisherClient.batch()` - to no longer accept a `message` (since the `will_accept` check needs to - happen in a more concurrency friendly way). In addition, changing the - `create` argument so that it means "create even if batch already exists" - rather than "create if missing". - -### Documentation - -- Add more explicit documentation for `Message.attributes` (#4601). -- Make `Message.__repr__` a bit prettier / more useful (#4602). - -PyPI: https://pypi.org/project/google-cloud-pubsub/0.30.0/ - -## 0.29.4 - -### Notable Implementation Changes - -- **Bug fix**: Restore previous behavior of the subscription lease - maintenance worker. This was accidentally "stopped" in `0.29.3` - due to a change in implementation that went from an `active` - boolean to an "inactive" / `stopped` boolean, so `True` became - `False` and vice-versa (#4564). - -PyPI: https://pypi.org/project/google-cloud-pubsub/0.29.4/ - -## 0.29.3 - -### Notable Implementation Changes - -- In subscription consumer thread: Making sure the request generator - attached to an inactive bidirectional streaming pull is stopped before - spawning a new request generator. This way we have a (fairly strong) - guarantee that requests in the queue don't get sent into an inactive - stream (#4503, #4554). -- Adding `pause` / `resume` to subscription consumer thread and using these - methods during flow control. The previous implementation tried to close the - subscription (which involved 3 worker threads and 10 executors in a thread - pool) and then re-open a new subscription. But, this was not entirely - possible to shut down correctly from **within** one of the worker threads. - Instead, we only pause the worker (of the 3) that is pulling new responses - from the bidirectional streaming pull (#4558). -- **Bug fix** (#4516): Using `max` where `min` was used by mistake to - ensure the number of bytes tracked for subscription flow control - remained non-negative (#4514). -- Raising `TypeError` if `SubscriberClient.subscribe` receives a - non-callable callback (#4497). -- Shutting down thread pool executor when closing a subscriber - policy (#4522). -- Renaming `Policy.on_callback_request` to `Policy.dispatch_callback` - and making the behavior much less dynamic (#4511). -- Make sure subscription consumer thread doesn't try to join itself - when exiting in error (#4540). - -### Dependencies - -- Upgrading `google-api-core` dependency to latest revision (`0.1.2`) - since we rely on the latest version of the `concurrent.futures` backport - to provide the `thread_name_prefix` argument for thread pool - executor (#4521, #4559). - -PyPI: https://pypi.org/project/google-cloud-pubsub/0.29.3/ - -## 0.29.2 - -### Notable Implementation Changes - -- **Bug fix** (#4463): Making a subscription consumer actually stop - running after encountering an exception (#4472, #4498). This bug - is the **only** reason for the `0.29.2` release. -- Thread Changes - - Added names to all threads created directly by Pub / Sub (#4474, - #4476, #4480). Also removing spaces and colons from thread - names (#4476). -- Logging changes - - Adding debug logs when lease management exits (#4484) - - Adding debug logs when `QueueCallbackThread` exits (#4494). - Instances handle the processing of messages in a - subscription (e.g. to `ack`). - - Using a named logger in `publisher.batch.thread` (#4473) - - Adding newlines before logging protobuf payloads (#4471) - -PyPI: https://pypi.org/project/google-cloud-pubsub/0.29.2/ - -## 0.29.1 - -### Notable Implementation Changes - -- **Bug fix** (#4234): Adding retries for connection `UNAVAILABLE`. This - bug made the Pub / Sub client mostly unusable for subscribers to topics - that don't have a steady stream of messages. After ~2 minutes of inactivity, - the gRPC connection would timeout and raise `UNAVAILABLE` locally, i.e. not - due to a response from the backend. (#4444) -- Updating autogenerated packages (#4438) - -### Documentation - -- Fixing broken examples in quick start (#4398) -- Fixing broken example in README (#4402, h/t to @mehmetboraezer) -- Updating old/dead link to usage doc in README (#4406, h/t to @mehmetboraezer) - -### Dependencies - -- Dropping dependency on `google-cloud-core` in exchange for - `google-api-core` (#4438) - -PyPI: https://pypi.org/project/google-cloud-pubsub/0.29.1/ - -## 0.29.0 - -### Notable Implementation Changes - -- Honor `max_messages` always (#4262) -- Add futures for subscriptions (#4265) -- Set gRPC message options and keepalive (#4269) - -### Documentation - -- Added link to "Python Development Environment Setup Guide" in - project README (#4187, h/t to @michaelawyu) - -### Dependencies - -- Upgrading to `google-cloud-core >= 0.28.0` and adding dependency - on `google-api-core` (#4221, #4280) -- Deferring to `google-api-core` for `grpcio` and - `googleapis-common-protos`dependencies (#4096, #4098) - -PyPI: https://pypi.org/project/google-cloud-pubsub/0.29.0/ diff --git a/pubsub/LICENSE b/pubsub/LICENSE deleted file mode 100644 index a8ee855de2aa..000000000000 --- a/pubsub/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/pubsub/MANIFEST.in b/pubsub/MANIFEST.in deleted file mode 100644 index 9cbf175afe6b..000000000000 --- a/pubsub/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include README.rst LICENSE -recursive-include google *.json *.proto -recursive-include tests * -global-exclude *.py[co] -global-exclude __pycache__ diff --git a/pubsub/README.rst b/pubsub/README.rst deleted file mode 100644 index a92a43087052..000000000000 --- a/pubsub/README.rst +++ /dev/null @@ -1,229 +0,0 @@ -Python Client for Google Cloud Pub / Sub -======================================== - -|GA| |pypi| |versions| - -`Google Cloud Pub / Sub`_ is a fully-managed real-time messaging service that -allows you to send and receive messages between independent applications. You -can leverage Cloud Pub/Sub’s flexibility to decouple systems and components -hosted on Google Cloud Platform or elsewhere on the Internet. By building on -the same technology Google uses, Cloud Pub / Sub is designed to provide “at -least once” delivery at low latency with on-demand scalability to 1 million -messages per second (and beyond). - -Publisher applications can send messages to a ``topic`` and other applications -can subscribe to that topic to receive the messages. By decoupling senders and -receivers, Google Cloud Pub/Sub allows developers to communicate between -independently written applications. - -- `Product Documentation`_ -- `Client Library Documentation`_ - -.. |GA| image:: https://img.shields.io/badge/support-GA-gold.svg - :target: https://github.com/googleapis/google-cloud-python/blob/master/README.rst#general-availability -.. |pypi| image:: https://img.shields.io/pypi/v/google-cloud-pubsub.svg - :target: https://pypi.org/project/google-cloud-pubsub/ -.. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-pubsub.svg - :target: https://pypi.org/project/google-cloud-pubsub/ -.. _Google Cloud Pub / Sub: https://cloud.google.com/pubsub/ -.. _Product Documentation: https://cloud.google.com/pubsub/docs -.. _Client Library Documentation: https://googleapis.dev/python/pubsub/latest - -Quick Start ------------ - -In order to use this library, you first need to go through the following steps: - -1. `Select or create a Cloud Platform project.`_ -2. `Enable billing for your project.`_ -3. `Enable the Google Cloud Pub / Sub API.`_ -4. `Setup Authentication.`_ - -.. _Select or create a Cloud Platform project.: https://console.cloud.google.com/project -.. _Enable billing for your project.: https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project -.. _Enable the Google Cloud Pub / Sub API.: https://cloud.google.com/pubsub -.. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html - -Installation -~~~~~~~~~~~~ - -Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to -create isolated Python environments. The basic problem it addresses is one of -dependencies and versions, and indirectly permissions. - -With `virtualenv`_, it's possible to install this library without needing system -install permissions, and without clashing with the installed system -dependencies. - -.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ - - -Supported Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.5 - -Deprecated Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^^ -Python == 2.7. Python 2.7 support will be removed on January 1, 2020. - - -Mac/Linux -^^^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - source /bin/activate - /bin/pip install google-cloud-pubsub - - -Windows -^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - \Scripts\activate - \Scripts\pip.exe install google-cloud-pubsub - - -Example Usage -~~~~~~~~~~~~~ - -Publishing -^^^^^^^^^^ - -To publish data to Cloud Pub/Sub you must create a topic, and then publish -messages to it - -.. code-block:: python - - import os - from google.cloud import pubsub_v1 - - publisher = pubsub_v1.PublisherClient() - topic_name = 'projects/{project_id}/topics/{topic}'.format( - project_id=os.getenv('GOOGLE_CLOUD_PROJECT'), - topic='MY_TOPIC_NAME', # Set this to something appropriate. - ) - publisher.create_topic(topic_name) - publisher.publish(topic_name, b'My first message!', spam='eggs') - -To learn more, consult the `publishing documentation`_. - -.. _publishing documentation: https://googleapis.dev/python/pubsub/latest - - -Subscribing -^^^^^^^^^^^ - -To subscribe to data in Cloud Pub/Sub, you create a subscription based on -the topic, and subscribe to that, passing a callback function. - -.. code-block:: python - - import os - from google.cloud import pubsub_v1 - - subscriber = pubsub_v1.SubscriberClient() - topic_name = 'projects/{project_id}/topics/{topic}'.format( - project_id=os.getenv('GOOGLE_CLOUD_PROJECT'), - topic='MY_TOPIC_NAME', # Set this to something appropriate. - ) - subscription_name = 'projects/{project_id}/subscriptions/{sub}'.format( - project_id=os.getenv('GOOGLE_CLOUD_PROJECT'), - sub='MY_SUBSCRIPTION_NAME', # Set this to something appropriate. - ) - subscriber.create_subscription( - name=subscription_name, topic=topic_name) - - def callback(message): - print(message.data) - message.ack() - - future = subscriber.subscribe(subscription_name, callback) - -The future returned by the call to ``subscriber.subscribe`` can be used to -block the current thread until a given condition obtains: - -.. code-block:: python - - try: - future.result() - except KeyboardInterrupt: - future.cancel() - -It is also possible to pull messages in a synchronous (blocking) fashion. To -learn more about subscribing, consult the `subscriber documentation`_. - -.. _subscriber documentation: https://googleapis.dev/python/pubsub/latest - - -Authentication -^^^^^^^^^^^^^^ - -It is possible to specify the authentication method to use with the Pub/Sub -clients. This can be done by providing an explicit `Credentials`_ instance. Support -for various authentication methods is available from the `google-auth`_ library. - -For example, to use JSON Web Tokens, provide a `google.auth.jwt.Credentials`_ instance: - -.. code-block:: python - - import json - from google.auth import jwt - - service_account_info = json.load(open("service-account-info.json")) - audience = "https://pubsub.googleapis.com/google.pubsub.v1.Subscriber" - - credentials = jwt.Credentials.from_service_account_info( - service_account_info, audience=audience - ) - - subscriber = pubsub_v1.SubscriberClient(credentials=credentials) - - # The same for the publisher, except that the "audience" claim needs to be adjusted - publisher_audience = "https://pubsub.googleapis.com/google.pubsub.v1.Publisher" - credentials_pub = credentials.with_claims(audience=publisher_audience) - publisher = pubsub_v1.PublisherClient(credentials=credentials_pub) - -.. _Credentials: https://google-auth.readthedocs.io/en/latest/reference/google.auth.credentials.html#google.auth.credentials.Credentials -.. _google-auth: https://google-auth.readthedocs.io/en/latest/index.html -.. _google.auth.jwt.Credentials: https://google-auth.readthedocs.io/en/latest/reference/google.auth.jwt.html#google.auth.jwt.Credentials - - -Versioning ----------- - -This library follows `Semantic Versioning`_. - -It is currently in major version one (1.y.z), which means that the public API should be considered stable. - -.. _Semantic Versioning: http://semver.org/ - -Contributing ------------- - -Contributions to this library are always welcome and highly encouraged. - -See the `CONTRIBUTING doc`_ for more information on how to get started. - -.. _CONTRIBUTING doc: https://github.com/googleapis/google-cloud-python/blob/master/CONTRIBUTING.rst - -Community ---------- - -Google Cloud Platform Python developers hang out in `Slack`_ in the ``#python`` -channel, click here to `get an invitation`_. - -.. _Slack: https://googlecloud-community.slack.com -.. _get an invitation: https://gcp-slack.appspot.com/ - -License -------- - -Apache 2.0 - See `the LICENSE`_ for more information. - -.. _the LICENSE: https://github.com/googleapis/google-cloud-python/blob/master/LICENSE diff --git a/pubsub/docs/README.rst b/pubsub/docs/README.rst deleted file mode 120000 index 89a0106941ff..000000000000 --- a/pubsub/docs/README.rst +++ /dev/null @@ -1 +0,0 @@ -../README.rst \ No newline at end of file diff --git a/pubsub/docs/_static/custom.css b/pubsub/docs/_static/custom.css deleted file mode 100644 index 0abaf229fce3..000000000000 --- a/pubsub/docs/_static/custom.css +++ /dev/null @@ -1,4 +0,0 @@ -div#python2-eol { - border-color: red; - border-width: medium; -} \ No newline at end of file diff --git a/pubsub/docs/_templates/layout.html b/pubsub/docs/_templates/layout.html deleted file mode 100644 index 228529efe2d2..000000000000 --- a/pubsub/docs/_templates/layout.html +++ /dev/null @@ -1,50 +0,0 @@ - -{% extends "!layout.html" %} -{%- block content %} -{%- if theme_fixed_sidebar|lower == 'true' %} -
- {{ sidebar() }} - {%- block document %} -
- {%- if render_sidebar %} -
- {%- endif %} - - {%- block relbar_top %} - {%- if theme_show_relbar_top|tobool %} - - {%- endif %} - {% endblock %} - -
-
- On January 1, 2020 this library will no longer support Python 2 on the latest released version. - Previously released library versions will continue to be available. For more information please - visit Python 2 support on Google Cloud. -
- {% block body %} {% endblock %} -
- - {%- block relbar_bottom %} - {%- if theme_show_relbar_bottom|tobool %} - - {%- endif %} - {% endblock %} - - {%- if render_sidebar %} -
- {%- endif %} -
- {%- endblock %} -
-
-{%- else %} -{{ super() }} -{%- endif %} -{%- endblock %} diff --git a/pubsub/docs/changelog.md b/pubsub/docs/changelog.md deleted file mode 120000 index 04c99a55caae..000000000000 --- a/pubsub/docs/changelog.md +++ /dev/null @@ -1 +0,0 @@ -../CHANGELOG.md \ No newline at end of file diff --git a/pubsub/docs/conf.py b/pubsub/docs/conf.py deleted file mode 100644 index 778fe480b370..000000000000 --- a/pubsub/docs/conf.py +++ /dev/null @@ -1,356 +0,0 @@ -# -*- coding: utf-8 -*- -# -# google-cloud-pubsub documentation build configuration file -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -import shlex - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath("..")) - -__version__ = "0.1.0" - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "1.6.3" - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.intersphinx", - "sphinx.ext.coverage", - "sphinx.ext.napoleon", - "sphinx.ext.todo", - "sphinx.ext.viewcode", -] - -# autodoc/autosummary flags -autoclass_content = "both" -autodoc_default_flags = ["members"] -autosummary_generate = True - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# Allow markdown includes (so releases.md can include CHANGLEOG.md) -# http://www.sphinx-doc.org/en/master/markdown.html -source_parsers = {".md": "recommonmark.parser.CommonMarkParser"} - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = [".rst", ".md"] - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = u"google-cloud-pubsub" -copyright = u"2017, Google" -author = u"Google APIs" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The full version, including alpha/beta/rc tags. -release = __version__ -# The short X.Y version. -version = ".".join(release.split(".")[0:2]) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["_build"] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "alabaster" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = { - "description": "Google Cloud Client Libraries for Python", - "github_user": "googleapis", - "github_repo": "google-cloud-python", - "github_banner": True, - "font_family": "'Roboto', Georgia, sans", - "head_font_family": "'Roboto', Georgia, serif", - "code_font_family": "'Roboto Mono', 'Consolas', monospace", -} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -# html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -# html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = "google-cloud-pubsub-doc" - -# -- Options for warnings ------------------------------------------------------ - -suppress_warnings = [ - # Temporarily suppress this to avoid "more than one target found for - # cross-reference" warning, which are intractable for us to avoid while in - # a mono-repo. - # See https://github.com/sphinx-doc/sphinx/blob - # /2a65ffeef5c107c19084fabdd706cdff3f52d93c/sphinx/domains/python.py#L843 - "ref.python" -] - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - #'preamble': '', - # Latex figure (float) alignment - #'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "google-cloud-pubsub.tex", - u"google-cloud-pubsub Documentation", - author, - "manual", - ) -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ( - master_doc, - "google-cloud-pubsub", - u"google-cloud-pubsub Documentation", - [author], - 1, - ) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "google-cloud-pubsub", - u"google-cloud-pubsub Documentation", - author, - "google-cloud-pubsub", - "GAPIC library for the {metadata.shortName} service", - "APIs", - ) -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - "python": ("http://python.readthedocs.org/en/latest/", None), - "gax": ("https://gax-python.readthedocs.org/en/latest/", None), - "google-auth": ("https://google-auth.readthedocs.io/en/stable", None), - "google-gax": ("https://gax-python.readthedocs.io/en/latest/", None), - "google.api_core": ("https://googleapis.dev/python/google-api-core/latest", None), - "grpc": ("https://grpc.io/grpc/python/", None), - "requests": ("https://requests.kennethreitz.org/en/stable/", None), - "fastavro": ("https://fastavro.readthedocs.io/en/stable/", None), - "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), -} - -# Napoleon settings -napoleon_google_docstring = True -napoleon_numpy_docstring = True -napoleon_include_private_with_doc = False -napoleon_include_special_with_doc = True -napoleon_use_admonition_for_examples = False -napoleon_use_admonition_for_notes = False -napoleon_use_admonition_for_references = False -napoleon_use_ivar = False -napoleon_use_param = True -napoleon_use_rtype = True diff --git a/pubsub/docs/index.rst b/pubsub/docs/index.rst deleted file mode 100644 index 5f6f8d4d26d1..000000000000 --- a/pubsub/docs/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. include:: README.rst - -API Documentation ------------------ - -.. toctree:: - :maxdepth: 3 - - publisher/index - subscriber/index - types - -Changelog ---------- - -For a list of all ``google-cloud-pubsub`` releases: - -.. toctree:: - :maxdepth: 2 - - changelog - diff --git a/pubsub/docs/publisher/api/client.rst b/pubsub/docs/publisher/api/client.rst deleted file mode 100644 index 47a3aa3d5d7a..000000000000 --- a/pubsub/docs/publisher/api/client.rst +++ /dev/null @@ -1,6 +0,0 @@ -Publisher Client API -==================== - -.. automodule:: google.cloud.pubsub_v1.publisher.client - :members: - :inherited-members: diff --git a/pubsub/docs/publisher/api/futures.rst b/pubsub/docs/publisher/api/futures.rst deleted file mode 100644 index b02b9bf9039d..000000000000 --- a/pubsub/docs/publisher/api/futures.rst +++ /dev/null @@ -1,6 +0,0 @@ -Futures -======= - -.. automodule:: google.cloud.pubsub_v1.publisher.futures - :members: - :inherited-members: diff --git a/pubsub/docs/publisher/index.rst b/pubsub/docs/publisher/index.rst deleted file mode 100644 index 2a785359c443..000000000000 --- a/pubsub/docs/publisher/index.rst +++ /dev/null @@ -1,138 +0,0 @@ -Publishing Messages -=================== - -Publishing messages is handled through the -:class:`~.pubsub_v1.publisher.client.Client` class (aliased as -``google.cloud.pubsub.PublisherClient``). This class provides methods to -create topics, and (most importantly) a -:meth:`~.pubsub_v1.publisher.client.Client.publish` method that publishes -messages to Pub/Sub. - -Instantiating a publishing client is straightforward: - -.. code-block:: python - - from google.cloud import pubsub - publish_client = pubsub.PublisherClient() - - -Publish a Message ------------------ - -To publish a message, use the -:meth:`~.pubsub_v1.publisher.client.Client.publish` method. This method accepts -two positional arguments: the topic to publish to, and the body of the message. -It also accepts arbitrary keyword arguments, which are passed along as -attributes of the message. - -The topic is passed along as a string; all topics have the canonical form of -``projects/{project_name}/topics/{topic_name}``. - -Therefore, a very basic publishing call looks like: - -.. code-block:: python - - topic = 'projects/{project}/topics/{topic}' - publish_client.publish(topic, b'This is my message.') - -.. note:: - - The message data in Pub/Sub is an opaque blob of bytes, and as such, you - *must* send a ``bytes`` object in Python 3 (``str`` object in Python 2). - If you send a text string (``str`` in Python 3, ``unicode`` in Python 2), - the method will raise :exc:`TypeError`. - - The reason it works this way is because there is no reasonable guarantee - that the same language or environment is being used by the subscriber, - and so it is the responsibility of the publisher to properly encode - the payload. - -If you want to include attributes, simply add keyword arguments: - -.. code-block:: python - - topic = 'projects/{project}/topics/{topic}' - publish_client.publish(topic, b'This is my message.', foo='bar') - - -Batching --------- - -Whenever you publish a message, the publisher will automatically batch the -messages over a small time window to avoid making too many separate requests to -the service. This helps increase throughput. - -.. note:: - - By default, this uses ``threading``, and you will need to be in an - environment with threading enabled. It is possible to provide an - alternative batch class that uses another concurrency strategy. - -The way that this works is that on the first message that you send, a new batch -is created automatically. For every subsequent message, if there is already a -valid batch that is still accepting messages, then that batch is used. When the -batch is created, it begins a countdown that publishes the batch once -sufficient time has elapsed (by default, this is 0.05 seconds). - -If you need different batching settings, simply provide a -:class:`~.pubsub_v1.types.BatchSettings` object when you instantiate the -:class:`~.pubsub_v1.publisher.client.Client`: - -.. code-block:: python - - from google.cloud import pubsub - from google.cloud.pubsub import types - - client = pubsub.PublisherClient( - batch_settings=types.BatchSettings(max_messages=500), - ) - -Pub/Sub accepts a maximum of 1,000 messages in a batch, and the size of a -batch can not exceed 10 megabytes. - - -Futures -------- - -Every call to :meth:`~.pubsub_v1.publisher.client.Client.publish` returns -an instance of :class:`~.pubsub_v1.publisher.futures.Future`. - -.. note:: - - The returned future conforms for the most part to the interface of - the standard library's :class:`~concurrent.futures.Future`, but might not - be usable in all cases which expect that exact implementaton. - -You can use this to ensure that the publish succeeded: - -.. code-block:: python - - # The .result() method will block until the future is complete. - # If there is an error, it will raise an exception. - future = client.publish(topic, b'My awesome message.') - message_id = future.result() - -You can also attach a callback to the future: - -.. code-block:: python - - # Callbacks receive the future as their only argument, as defined in - # the Future interface. - def callback(future): - message_id = future.result() - do_something_with(message_id) - - # The callback is added once you get the future. If you add a callback - # and the future is already done, it will simply be executed immediately. - future = client.publish(topic, b'My awesome message.') - future.add_done_callback(callback) - - -API Reference -------------- - -.. toctree:: - :maxdepth: 2 - - api/client - api/futures diff --git a/pubsub/docs/subscriber/api/client.rst b/pubsub/docs/subscriber/api/client.rst deleted file mode 100644 index 965880c5a640..000000000000 --- a/pubsub/docs/subscriber/api/client.rst +++ /dev/null @@ -1,6 +0,0 @@ -Subscriber Client API -===================== - -.. automodule:: google.cloud.pubsub_v1.subscriber.client - :members: - :inherited-members: diff --git a/pubsub/docs/subscriber/api/futures.rst b/pubsub/docs/subscriber/api/futures.rst deleted file mode 100644 index fb0264279cf6..000000000000 --- a/pubsub/docs/subscriber/api/futures.rst +++ /dev/null @@ -1,6 +0,0 @@ -Futures -======= - -.. automodule:: google.cloud.pubsub_v1.subscriber.futures - :members: - :inherited-members: diff --git a/pubsub/docs/subscriber/api/message.rst b/pubsub/docs/subscriber/api/message.rst deleted file mode 100644 index cc5b0e37c9b4..000000000000 --- a/pubsub/docs/subscriber/api/message.rst +++ /dev/null @@ -1,5 +0,0 @@ -Messages -======== - -.. autoclass:: google.cloud.pubsub_v1.subscriber.message.Message - :members: diff --git a/pubsub/docs/subscriber/api/scheduler.rst b/pubsub/docs/subscriber/api/scheduler.rst deleted file mode 100644 index 06e839f219e6..000000000000 --- a/pubsub/docs/subscriber/api/scheduler.rst +++ /dev/null @@ -1,6 +0,0 @@ -Scheduler -========= - -.. automodule:: google.cloud.pubsub_v1.subscriber.scheduler - :members: - :inherited-members: diff --git a/pubsub/docs/subscriber/index.rst b/pubsub/docs/subscriber/index.rst deleted file mode 100644 index d3d1cb5415b5..000000000000 --- a/pubsub/docs/subscriber/index.rst +++ /dev/null @@ -1,190 +0,0 @@ -Subscribing to Messages -======================= - -Subscribing to messages is handled through the -:class:`~.pubsub_v1.subscriber.client.Client` class (aliased as -``google.cloud.pubsub.SubscriberClient``). This class provides a -:meth:`~.pubsub_v1.subscriber.client.Client.subscribe` method to -attach to subscriptions on existing topics. - -Instantiating a subscriber client is straightforward: - -.. code-block:: python - - from google.cloud import pubsub - subscriber = pubsub.SubscriberClient() - - -Creating a Subscription ------------------------ - -In Pub/Sub, a **subscription** is a discrete pull of messages from a topic. -If multiple clients pull the same subscription, then messages are split -between them. If multiple clients create a subscription each, then each client -will get every message. - -.. note:: - - Remember that Pub/Sub operates under the principle of "everything at least - once". Even in the case where multiple clients pull the same subscription, - *some* redundancy is likely. - -Creating a subscription requires that you already know what topic you want -to subscribe to, and it must already exist. Once you have that, it is easy: - -.. code-block:: python - - # Substitute PROJECT, SUBSCRIPTION, and TOPIC with appropriate values for - # your application. - sub_path = subscriber.subscription_path(PROJECT, SUBSCRIPTION) - topic_path = subscriber.topic_path(PROJECT, TOPIC) - subscriber.create_subscription(sub_path, topic_path) - -Once you have created a subscription (or if you already had one), the next -step is to pull data from it. - - -Pulling a Subscription Synchronously ------------------------------------- - -To pull the messages synchronously, use the client's -:meth:`~.pubsub_v1.subscriber.client.Client.pull` method. - -.. code-block:: python - - # Substitute PROJECT and SUBSCRIPTION with appropriate values for your - # application. - subscription_path = subscriber.subscription_path(PROJECT, SUBSCRIPTION) - response = subscriber.pull(subscription_path, max_messages=5) - - for msg in response.received_messages: - print("Received message:", msg.message.data) - - ack_ids = [msg.ack_id for msg in response.received_messages] - subscriber.acknowledge(subscription_path, ack_ids) - -The method returns a :class:`~.pubsub_v1.types.PullResponse` instance that -cointains a list of received :class:`~.pubsub_v1.types.ReceivedMessage` -instances. - - -Pulling a Subscription Asynchronously -------------------------------------- - -The subscriber client uses the -:meth:`~.pubsub_v1.subscriber.client.Client.subscribe` method to start a -background thread to receive messages from Pub/Sub and calls a callback with -each message received. - -.. code-block:: python - - # Substitute PROJECT and SUBSCRIPTION with appropriate values for your - # application. - subscription_path = subscriber.subscription_path(PROJECT, SUBSCRIPTION) - future = subscriber.subscribe(subscription_path, callback) - -This will return a -:class:`~.pubsub_v1.subscriber.futures.StreamingPullFuture`. This future allows -you to control the background thread that is managing the subscription. - - -Subscription Callbacks ----------------------- - -Messages received from a subscription are processed asynchronously through -**callbacks**. - -The basic idea: Define a function that takes one argument; this argument -will be a :class:`~.pubsub_v1.subscriber.message.Message` instance, which is -a convenience wrapper around the :class:`~.pubsub_v1.types.PubsubMessage` -instance received from the server (and stored under the ``message`` attribute). - -This function should do whatever processing is necessary. At the end, the -function should either :meth:`~.pubsub_v1.subscriber.message.Message.ack` -or :meth:`~.pubsub_v1.subscriber.message.Message.nack` the message. - -When you call :meth:`~.pubsub_v1.subscriber.client.Client.subscribe`, you -must pass the callback that will be used. - -Here is an example: - -.. code-block:: python - - # Define the callback. - # Note that the callback is defined *before* the subscription is opened. - def callback(message): - do_something_with(message) # Replace this with your actual logic. - message.ack() # Asynchronously acknowledge the message. - - # Substitute PROJECT and SUBSCRIPTION with appropriate values for your - # application. - subscription_path = subscriber.subscription_path(PROJECT, SUBSCRIPTION) - - # Open the subscription, passing the callback. - future = subscriber.subscribe(subscription_path, callback) - -The :meth:`~.pubsub_v1.subscriber.client.Client.subscribe` method returns -a :class:`~.pubsub_v1.subscriber.futures.StreamingPullFuture`, which is both -the interface to wait on messages (e.g. block the primary thread) and to -address exceptions. - -To block the thread you are in while messages are coming in the stream, -use the :meth:`~.pubsub_v1.subscriber.futures.Future.result` method: - -.. code-block:: python - - future.result() - -.. note: This will block forever assuming no errors or that ``cancel`` is never - called. - -You can also use this for error handling; any exceptions that crop up on a -thread will be set on the future. - -.. code-block:: python - - try: - future.result() - except Exception as ex: - subscription.close() - raise - -Finally, you can use -:meth:`~.pubsub_v1.subscriber.futures.StreamingPullFuture.cancel` to stop -receiving messages. - - -.. code-block:: python - - future.cancel() - - -Explaining Ack --------------- - -In Pub/Sub, the term **ack** stands for "acknowledge". You should ack a -message when your processing of that message *has completed*. When you ack -a message, you are telling Pub/Sub that you do not need to see it again. - -It might be tempting to ack messages immediately on receipt. While there -are valid use cases for this, in general it is unwise. The reason why: If -there is some error or edge case in your processing logic, and processing -of the message fails, you will have already told Pub/Sub that you successfully -processed the message. By contrast, if you ack only upon completion, then -Pub/Sub will eventually re-deliver the unacknowledged message. - -It is also possible to **nack** a message, which is the opposite. When you -nack, it tells Pub/Sub that you are unable or unwilling to deal with the -message, and that the service should redeliver it. - - -API Reference -------------- - -.. toctree:: - :maxdepth: 2 - - api/client - api/message - api/futures - api/scheduler diff --git a/pubsub/docs/types.rst b/pubsub/docs/types.rst deleted file mode 100644 index 87c987571766..000000000000 --- a/pubsub/docs/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Pub/Sub Client Types -==================== - -.. automodule:: google.cloud.pubsub_v1.types - :members: diff --git a/pubsub/google/__init__.py b/pubsub/google/__init__.py deleted file mode 100644 index 8fcc60e2b9c6..000000000000 --- a/pubsub/google/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/pubsub/google/cloud/__init__.py b/pubsub/google/cloud/__init__.py deleted file mode 100644 index 8fcc60e2b9c6..000000000000 --- a/pubsub/google/cloud/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/pubsub/google/cloud/pubsub.py b/pubsub/google/cloud/pubsub.py deleted file mode 100644 index b9f92e991aa6..000000000000 --- a/pubsub/google/cloud/pubsub.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import - -from google.cloud.pubsub_v1 import PublisherClient -from google.cloud.pubsub_v1 import SubscriberClient -from google.cloud.pubsub_v1 import types - - -__all__ = ("types", "PublisherClient", "SubscriberClient") diff --git a/pubsub/google/cloud/pubsub_v1/__init__.py b/pubsub/google/cloud/pubsub_v1/__init__.py deleted file mode 100644 index 67bec51b248b..000000000000 --- a/pubsub/google/cloud/pubsub_v1/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1 import publisher -from google.cloud.pubsub_v1 import subscriber - - -class PublisherClient(publisher.Client): - __doc__ = publisher.Client.__doc__ - - -class SubscriberClient(subscriber.Client): - __doc__ = subscriber.Client.__doc__ - - -__all__ = ("types", "PublisherClient", "SubscriberClient") diff --git a/pubsub/google/cloud/pubsub_v1/_gapic.py b/pubsub/google/cloud/pubsub_v1/_gapic.py deleted file mode 100644 index da755dfbca09..000000000000 --- a/pubsub/google/cloud/pubsub_v1/_gapic.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2019, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import functools - - -def add_methods(source_class, blacklist=()): - """Add wrapped versions of the `api` member's methods to the class. - - Any methods passed in `blacklist` are not added. - Additionally, any methods explicitly defined on the wrapped class are - not added. - """ - - def wrap(wrapped_fx, lookup_fx): - """Wrap a GAPIC method; preserve its name and docstring.""" - # If this is a static or class method, then we do *not* - # send self as the first argument. - # - # For instance methods, we need to send self.api rather - # than self, since that is where the actual methods were declared. - - if isinstance(lookup_fx, (classmethod, staticmethod)): - fx = lambda *a, **kw: wrapped_fx(*a, **kw) # noqa - return staticmethod(functools.wraps(wrapped_fx)(fx)) - else: - fx = lambda self, *a, **kw: wrapped_fx(self.api, *a, **kw) # noqa - return functools.wraps(wrapped_fx)(fx) - - def actual_decorator(cls): - # Reflectively iterate over most of the methods on the source class - # (the GAPIC) and make wrapped versions available on this client. - for name in dir(source_class): - # Ignore all private and magic methods. - if name.startswith("_"): - continue - - # Ignore anything on our blacklist. - if name in blacklist: - continue - - # Retrieve the attribute, and ignore it if it is not callable. - attr = getattr(source_class, name) - if not callable(attr): - continue - - # Add a wrapper method to this object. - lookup_fx = source_class.__dict__[name] - fx = wrap(attr, lookup_fx) - - setattr(cls, name, fx) - - # Return the augmented class. - return cls - - # Simply return the actual decorator; this is returned from this method - # and actually used to decorate the class. - return actual_decorator diff --git a/pubsub/google/cloud/pubsub_v1/exceptions.py b/pubsub/google/cloud/pubsub_v1/exceptions.py deleted file mode 100644 index 5ab750d0477c..000000000000 --- a/pubsub/google/cloud/pubsub_v1/exceptions.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from concurrent.futures import TimeoutError - - -__all__ = ("TimeoutError",) diff --git a/pubsub/google/cloud/pubsub_v1/futures.py b/pubsub/google/cloud/pubsub_v1/futures.py deleted file mode 100644 index ba861e40c653..000000000000 --- a/pubsub/google/cloud/pubsub_v1/futures.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import threading -import uuid - -import google.api_core.future -from google.cloud.pubsub_v1.publisher import exceptions - - -class Future(google.api_core.future.Future): - """Encapsulation of the asynchronous execution of an action. - - This object is returned from asychronous Pub/Sub calls, and is the - interface to determine the status of those calls. - - This object should not be created directly, but is returned by other - methods in this library. - - Args: - completed (Optional[Any]): An event, with the same interface as - :class:`threading.Event`. This is provided so that callers - with different concurrency models (e.g. ``threading`` or - ``multiprocessing``) can supply an event that is compatible - with that model. The ``wait()`` and ``set()`` methods will be - used. If this argument is not provided, then a new - :class:`threading.Event` will be created and used. - """ - - # This could be a sentinel object or None, but the sentinel object's ID - # can change if the process is forked, and None has the possibility of - # actually being a result. - _SENTINEL = uuid.uuid4() - - def __init__(self, completed=None): - self._result = self._SENTINEL - self._exception = self._SENTINEL - self._callbacks = [] - if completed is None: - completed = threading.Event() - self._completed = completed - - def cancel(self): - """Actions in Pub/Sub generally may not be canceled. - - This method always returns False. - """ - return False - - def cancelled(self): - """Actions in Pub/Sub generally may not be canceled. - - This method always returns False. - """ - return False - - def running(self): - """Actions in Pub/Sub generally may not be canceled. - - Returns: - bool: ``True`` if this method has not yet completed, or - ``False`` if it has completed. - """ - return not self.done() - - def done(self): - """Return True the future is done, False otherwise. - - This still returns True in failure cases; checking :meth:`result` or - :meth:`exception` is the canonical way to assess success or failure. - """ - return self._exception != self._SENTINEL or self._result != self._SENTINEL - - def result(self, timeout=None): - """Resolve the future and return a value where appropriate. - - Args: - timeout (Union[int, float]): The number of seconds before this call - times out and raises TimeoutError. - - Raises: - concurrent.futures.TimeoutError: If the request times out. - Exception: For undefined exceptions in the underlying - call execution. - """ - # Attempt to get the exception if there is one. - # If there is not one, then we know everything worked, and we can - # return an appropriate value. - err = self.exception(timeout=timeout) - if err is None: - return self._result - raise err - - def exception(self, timeout=None): - """Return the exception raised by the call, if any. - - Args: - timeout (Union[int, float]): The number of seconds before this call - times out and raises TimeoutError. - - Raises: - concurrent.futures.TimeoutError: If the request times out. - - Returns: - Exception: The exception raised by the call, if any. - """ - # Wait until the future is done. - if not self._completed.wait(timeout=timeout): - raise exceptions.TimeoutError("Timed out waiting for result.") - - # If the batch completed successfully, this should return None. - if self._result != self._SENTINEL: - return None - - # Okay, this batch had an error; this should return it. - return self._exception - - def add_done_callback(self, callback): - """Attach the provided callable to the future. - - The provided function is called, with this future as its only argument, - when the future finishes running. - - Args: - callback (Callable): The function to call. - - Returns: - None - """ - if self.done(): - return callback(self) - self._callbacks.append(callback) - - def set_result(self, result): - """Set the result of the future to the provided result. - - Args: - result (Any): The result - """ - # Sanity check: A future can only complete once. - if self.done(): - raise RuntimeError("set_result can only be called once.") - - # Set the result and trigger the future. - self._result = result - self._trigger() - - def set_exception(self, exception): - """Set the result of the future to the given exception. - - Args: - exception (:exc:`Exception`): The exception raised. - """ - # Sanity check: A future can only complete once. - if self.done(): - raise RuntimeError("set_exception can only be called once.") - - # Set the exception and trigger the future. - self._exception = exception - self._trigger() - - def _trigger(self): - """Trigger all callbacks registered to this Future. - - This method is called internally by the batch once the batch - completes. - - Args: - message_id (str): The message ID, as a string. - """ - self._completed.set() - for callback in self._callbacks: - callback(self) diff --git a/pubsub/google/cloud/pubsub_v1/gapic/__init__.py b/pubsub/google/cloud/pubsub_v1/gapic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/pubsub/google/cloud/pubsub_v1/gapic/publisher_client.py b/pubsub/google/cloud/pubsub_v1/gapic/publisher_client.py deleted file mode 100644 index 774fda25d622..000000000000 --- a/pubsub/google/cloud/pubsub_v1/gapic/publisher_client.py +++ /dev/null @@ -1,1095 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.pubsub.v1 Publisher API.""" - -import collections -from copy import deepcopy -import functools -import pkg_resources -import six -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.path_template -import google.api_core.gapic_v1.routing_header -import google.api_core.grpc_helpers -import google.api_core.page_iterator -import google.api_core.path_template -import grpc - -from google.cloud.pubsub_v1.gapic import publisher_client_config -from google.cloud.pubsub_v1.gapic.transports import publisher_grpc_transport -from google.cloud.pubsub_v1.proto import pubsub_pb2 -from google.cloud.pubsub_v1.proto import pubsub_pb2_grpc -from google.iam.v1 import iam_policy_pb2 -from google.iam.v1 import iam_policy_pb2_grpc -from google.iam.v1 import options_pb2 -from google.iam.v1 import policy_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-pubsub").version - - -# TODO: remove conditional import after Python 2 support is dropped -if six.PY3: - from collections.abc import Mapping -else: - from collections import Mapping - - -def _merge_dict(d1, d2): - # Modifies d1 in-place to take values from d2 - # if the nested keys from d2 are present in d1. - # https://stackoverflow.com/a/10704003/4488789 - for k, v2 in d2.items(): - v1 = d1.get(k) # returns None if v1 has no such key - if v1 is None: - raise Exception("{} is not recognized by client_config".format(k)) - if isinstance(v1, Mapping) and isinstance(v2, Mapping): - _merge_dict(v1, v2) - else: - d1[k] = v2 - return d1 - - -class PublisherClient(object): - """ - The service that an application uses to manipulate topics, and to send - messages to a topic. - """ - - SERVICE_ADDRESS = "pubsub.googleapis.com:443" - """The default address of the service.""" - - # The scopes needed to make gRPC calls to all of the methods defined in - # this service - _DEFAULT_SCOPES = ( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/pubsub", - ) - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.pubsub.v1.Publisher" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - PublisherClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - @classmethod - def project_path(cls, project): - """Return a fully-qualified project string.""" - return google.api_core.path_template.expand( - "projects/{project}", project=project - ) - - @classmethod - def topic_path(cls, project, topic): - """Return a fully-qualified topic string.""" - return google.api_core.path_template.expand( - "projects/{project}/topics/{topic}", project=project, topic=topic - ) - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.PublisherGrpcTransport, - Callable[[~.Credentials, type], ~.PublisherGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - default_client_config = deepcopy(publisher_client_config.config) - - if client_config is None: - client_config = default_client_config - else: - client_config = _merge_dict(default_client_config, client_config) - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=publisher_grpc_transport.PublisherGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = publisher_grpc_transport.PublisherGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def create_topic( - self, - name, - labels=None, - message_storage_policy=None, - kms_key_name=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Creates the given topic with the given name. See the resource name - rules. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> name = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> response = client.create_topic(name) - - Args: - name (str): The name of the topic. It must have the format - `"projects/{project}/topics/{topic}"`. `{topic}` must start with a letter, - and contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`), - underscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent - signs (`%`). It must be between 3 and 255 characters in length, and it - must not start with `"goog"`. - labels (dict[str -> str]): See Creating and - managing labels. - message_storage_policy (Union[dict, ~google.cloud.pubsub_v1.types.MessageStoragePolicy]): Policy constraining the set of Google Cloud Platform regions where messages - published to the topic may be stored. If not present, then no constraints - are in effect. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.MessageStoragePolicy` - kms_key_name (str): The resource name of the Cloud KMS CryptoKey to be used to protect - access to messages published on this topic. - - The expected format is - ``projects/*/locations/*/keyRings/*/cryptoKeys/*``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Topic` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "create_topic" not in self._inner_api_calls: - self._inner_api_calls[ - "create_topic" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_topic, - default_retry=self._method_configs["CreateTopic"].retry, - default_timeout=self._method_configs["CreateTopic"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.Topic( - name=name, - labels=labels, - message_storage_policy=message_storage_policy, - kms_key_name=kms_key_name, - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["create_topic"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def update_topic( - self, - topic, - update_mask, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Updates an existing topic. Note that certain properties of a - topic are not modifiable. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> # TODO: Initialize `topic`: - >>> topic = {} - >>> - >>> # TODO: Initialize `update_mask`: - >>> update_mask = {} - >>> - >>> response = client.update_topic(topic, update_mask) - - Args: - topic (Union[dict, ~google.cloud.pubsub_v1.types.Topic]): The updated topic object. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.Topic` - update_mask (Union[dict, ~google.cloud.pubsub_v1.types.FieldMask]): Indicates which fields in the provided topic to update. Must be - specified and non-empty. Note that if ``update_mask`` contains - "message\_storage\_policy" then the new value will be determined based - on the policy configured at the project or organization level. The - ``message_storage_policy`` must not be set in the ``topic`` provided - above. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.FieldMask` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Topic` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "update_topic" not in self._inner_api_calls: - self._inner_api_calls[ - "update_topic" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.update_topic, - default_retry=self._method_configs["UpdateTopic"].retry, - default_timeout=self._method_configs["UpdateTopic"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.UpdateTopicRequest(topic=topic, update_mask=update_mask) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("topic.name", topic.name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["update_topic"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def publish( - self, - topic, - messages, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Adds one or more messages to the topic. Returns ``NOT_FOUND`` if the - topic does not exist. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> topic = client.topic_path('[PROJECT]', '[TOPIC]') - >>> data = b'' - >>> messages_element = {'data': data} - >>> messages = [messages_element] - >>> - >>> response = client.publish(topic, messages) - - Args: - topic (str): The messages in the request will be published on this topic. Format is - ``projects/{project}/topics/{topic}``. - messages (list[Union[dict, ~google.cloud.pubsub_v1.types.PubsubMessage]]): The messages to publish. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.PubsubMessage` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.PublishResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "publish" not in self._inner_api_calls: - self._inner_api_calls[ - "publish" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.publish, - default_retry=self._method_configs["Publish"].retry, - default_timeout=self._method_configs["Publish"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.PublishRequest(topic=topic, messages=messages) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("topic", topic)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["publish"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def get_topic( - self, - topic, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets the configuration of a topic. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> topic = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> response = client.get_topic(topic) - - Args: - topic (str): The name of the topic to get. Format is - ``projects/{project}/topics/{topic}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Topic` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_topic" not in self._inner_api_calls: - self._inner_api_calls[ - "get_topic" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_topic, - default_retry=self._method_configs["GetTopic"].retry, - default_timeout=self._method_configs["GetTopic"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.GetTopicRequest(topic=topic) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("topic", topic)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_topic"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def list_topics( - self, - project, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Lists matching topics. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> project = client.project_path('[PROJECT]') - >>> - >>> # Iterate over all results - >>> for element in client.list_topics(project): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_topics(project).pages: - ... for element in page: - ... # process element - ... pass - - Args: - project (str): The name of the project in which to list topics. Format is - ``projects/{project-id}``. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.GRPCIterator` instance. - An iterable of :class:`~google.cloud.pubsub_v1.types.Topic` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_topics" not in self._inner_api_calls: - self._inner_api_calls[ - "list_topics" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_topics, - default_retry=self._method_configs["ListTopics"].retry, - default_timeout=self._method_configs["ListTopics"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.ListTopicsRequest(project=project, page_size=page_size) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("project", project)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_topics"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="topics", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def list_topic_subscriptions( - self, - topic, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Lists the names of the subscriptions on this topic. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> topic = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> # Iterate over all results - >>> for element in client.list_topic_subscriptions(topic): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_topic_subscriptions(topic).pages: - ... for element in page: - ... # process element - ... pass - - Args: - topic (str): The name of the topic that subscriptions are attached to. Format is - ``projects/{project}/topics/{topic}``. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.GRPCIterator` instance. - An iterable of :class:`str` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_topic_subscriptions" not in self._inner_api_calls: - self._inner_api_calls[ - "list_topic_subscriptions" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_topic_subscriptions, - default_retry=self._method_configs["ListTopicSubscriptions"].retry, - default_timeout=self._method_configs["ListTopicSubscriptions"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.ListTopicSubscriptionsRequest( - topic=topic, page_size=page_size - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("topic", topic)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_topic_subscriptions"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="subscriptions", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def delete_topic( - self, - topic, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Deletes the topic with the given name. Returns ``NOT_FOUND`` if the - topic does not exist. After a topic is deleted, a new topic may be - created with the same name; this is an entirely new topic with none of - the old configuration or subscriptions. Existing subscriptions to this - topic are not deleted, but their ``topic`` field is set to - ``_deleted-topic_``. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> topic = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> client.delete_topic(topic) - - Args: - topic (str): Name of the topic to delete. Format is - ``projects/{project}/topics/{topic}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "delete_topic" not in self._inner_api_calls: - self._inner_api_calls[ - "delete_topic" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_topic, - default_retry=self._method_configs["DeleteTopic"].retry, - default_timeout=self._method_configs["DeleteTopic"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.DeleteTopicRequest(topic=topic) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("topic", topic)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["delete_topic"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def set_iam_policy( - self, - resource, - policy, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Sets the access control policy on the specified resource. Replaces any - existing policy. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> resource = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> # TODO: Initialize `policy`: - >>> policy = {} - >>> - >>> response = client.set_iam_policy(resource, policy) - - Args: - resource (str): REQUIRED: The resource for which the policy is being specified. - See the operation documentation for the appropriate value for this field. - policy (Union[dict, ~google.cloud.pubsub_v1.types.Policy]): REQUIRED: The complete policy to be applied to the ``resource``. The - size of the policy is limited to a few 10s of KB. An empty policy is a - valid policy but certain Cloud Platform services (such as Projects) - might reject them. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.Policy` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Policy` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "set_iam_policy" not in self._inner_api_calls: - self._inner_api_calls[ - "set_iam_policy" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.set_iam_policy, - default_retry=self._method_configs["SetIamPolicy"].retry, - default_timeout=self._method_configs["SetIamPolicy"].timeout, - client_info=self._client_info, - ) - - request = iam_policy_pb2.SetIamPolicyRequest(resource=resource, policy=policy) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("resource", resource)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["set_iam_policy"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def get_iam_policy( - self, - resource, - options_=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets the access control policy for a resource. - Returns an empty policy if the resource exists and does not have a policy - set. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> resource = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> response = client.get_iam_policy(resource) - - Args: - resource (str): REQUIRED: The resource for which the policy is being requested. - See the operation documentation for the appropriate value for this field. - options_ (Union[dict, ~google.cloud.pubsub_v1.types.GetPolicyOptions]): OPTIONAL: A ``GetPolicyOptions`` object for specifying options to - ``GetIamPolicy``. This field is only used by Cloud IAM. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.GetPolicyOptions` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Policy` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_iam_policy" not in self._inner_api_calls: - self._inner_api_calls[ - "get_iam_policy" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_iam_policy, - default_retry=self._method_configs["GetIamPolicy"].retry, - default_timeout=self._method_configs["GetIamPolicy"].timeout, - client_info=self._client_info, - ) - - request = iam_policy_pb2.GetIamPolicyRequest( - resource=resource, options=options_ - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("resource", resource)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_iam_policy"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def test_iam_permissions( - self, - resource, - permissions, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns permissions that a caller has on the specified resource. If the - resource does not exist, this will return an empty set of permissions, - not a NOT\_FOUND error. - - Note: This operation is designed to be used for building - permission-aware UIs and command-line tools, not for authorization - checking. This operation may "fail open" without warning. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.PublisherClient() - >>> - >>> resource = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> # TODO: Initialize `permissions`: - >>> permissions = [] - >>> - >>> response = client.test_iam_permissions(resource, permissions) - - Args: - resource (str): REQUIRED: The resource for which the policy detail is being requested. - See the operation documentation for the appropriate value for this field. - permissions (list[str]): The set of permissions to check for the ``resource``. Permissions with - wildcards (such as '*' or 'storage.*') are not allowed. For more - information see `IAM - Overview `__. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.TestIamPermissionsResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "test_iam_permissions" not in self._inner_api_calls: - self._inner_api_calls[ - "test_iam_permissions" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.test_iam_permissions, - default_retry=self._method_configs["TestIamPermissions"].retry, - default_timeout=self._method_configs["TestIamPermissions"].timeout, - client_info=self._client_info, - ) - - request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, permissions=permissions - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("resource", resource)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["test_iam_permissions"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/pubsub/google/cloud/pubsub_v1/gapic/publisher_client_config.py b/pubsub/google/cloud/pubsub_v1/gapic/publisher_client_config.py deleted file mode 100644 index 055b3424e6cd..000000000000 --- a/pubsub/google/cloud/pubsub_v1/gapic/publisher_client_config.py +++ /dev/null @@ -1,99 +0,0 @@ -config = { - "interfaces": { - "google.pubsub.v1.Publisher": { - "retry_codes": { - "idempotent": ["ABORTED", "UNAVAILABLE", "UNKNOWN"], - "non_idempotent": ["UNAVAILABLE"], - "none": [], - "publish": [ - "ABORTED", - "CANCELLED", - "DEADLINE_EXCEEDED", - "INTERNAL", - "RESOURCE_EXHAUSTED", - "UNAVAILABLE", - "UNKNOWN", - ], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 60000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 60000, - "total_timeout_millis": 600000, - }, - "messaging": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 5000, - "rpc_timeout_multiplier": 1.3, - "max_rpc_timeout_millis": 60000, - "total_timeout_millis": 60000, - }, - }, - "methods": { - "CreateTopic": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "UpdateTopic": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "Publish": { - "timeout_millis": 60000, - "retry_codes_name": "publish", - "retry_params_name": "messaging", - "bundling": { - "element_count_threshold": 100, - "element_count_limit": 1000, - "request_byte_threshold": 1048576, - "request_byte_limit": 10485760, - "delay_threshold_millis": 10, - }, - }, - "GetTopic": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "ListTopics": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "ListTopicSubscriptions": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "DeleteTopic": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "SetIamPolicy": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "GetIamPolicy": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "TestIamPermissions": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/pubsub/google/cloud/pubsub_v1/gapic/subscriber_client.py b/pubsub/google/cloud/pubsub_v1/gapic/subscriber_client.py deleted file mode 100644 index 0ecce7ac9d1c..000000000000 --- a/pubsub/google/cloud/pubsub_v1/gapic/subscriber_client.py +++ /dev/null @@ -1,1885 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.pubsub.v1 Subscriber API.""" - -import functools -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.gapic_v1.routing_header -import google.api_core.grpc_helpers -import google.api_core.page_iterator -import google.api_core.path_template -import google.api_core.protobuf_helpers -import grpc - -from google.cloud.pubsub_v1.gapic import subscriber_client_config -from google.cloud.pubsub_v1.gapic.transports import subscriber_grpc_transport -from google.cloud.pubsub_v1.proto import pubsub_pb2 -from google.cloud.pubsub_v1.proto import pubsub_pb2_grpc -from google.iam.v1 import iam_policy_pb2 -from google.iam.v1 import iam_policy_pb2_grpc -from google.iam.v1 import options_pb2 -from google.iam.v1 import policy_pb2 -from google.protobuf import duration_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 -from google.protobuf import timestamp_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-pubsub").version - - -class SubscriberClient(object): - """ - The service that an application uses to manipulate subscriptions and to - consume messages from a subscription via the ``Pull`` method or by - establishing a bi-directional stream using the ``StreamingPull`` method. - """ - - SERVICE_ADDRESS = "pubsub.googleapis.com:443" - """The default address of the service.""" - - # The scopes needed to make gRPC calls to all of the methods defined in - # this service - _DEFAULT_SCOPES = ( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/pubsub", - ) - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.pubsub.v1.Subscriber" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - SubscriberClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - @classmethod - def project_path(cls, project): - """Return a fully-qualified project string.""" - return google.api_core.path_template.expand( - "projects/{project}", project=project - ) - - @classmethod - def snapshot_path(cls, project, snapshot): - """Return a fully-qualified snapshot string.""" - return google.api_core.path_template.expand( - "projects/{project}/snapshots/{snapshot}", - project=project, - snapshot=snapshot, - ) - - @classmethod - def subscription_path(cls, project, subscription): - """Return a fully-qualified subscription string.""" - return google.api_core.path_template.expand( - "projects/{project}/subscriptions/{subscription}", - project=project, - subscription=subscription, - ) - - @classmethod - def topic_path(cls, project, topic): - """Return a fully-qualified topic string.""" - return google.api_core.path_template.expand( - "projects/{project}/topics/{topic}", project=project, topic=topic - ) - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.SubscriberGrpcTransport, - Callable[[~.Credentials, type], ~.SubscriberGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = subscriber_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=subscriber_grpc_transport.SubscriberGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = subscriber_grpc_transport.SubscriberGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def create_subscription( - self, - name, - topic, - push_config=None, - ack_deadline_seconds=None, - retain_acked_messages=None, - message_retention_duration=None, - labels=None, - enable_message_ordering=None, - expiration_policy=None, - dead_letter_policy=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Creates a subscription to a given topic. See the resource name rules. If - the subscription already exists, returns ``ALREADY_EXISTS``. If the - corresponding topic doesn't exist, returns ``NOT_FOUND``. - - If the name is not provided in the request, the server will assign a - random name for this subscription on the same project as the topic, - conforming to the `resource name - format `__. - The generated name is populated in the returned Subscription object. - Note that for REST API requests, you must specify a name in the request. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> name = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> topic = client.topic_path('[PROJECT]', '[TOPIC]') - >>> - >>> response = client.create_subscription(name, topic) - - Args: - name (str): The name of the subscription. It must have the format - `"projects/{project}/subscriptions/{subscription}"`. `{subscription}` must - start with a letter, and contain only letters (`[A-Za-z]`), numbers - (`[0-9]`), dashes (`-`), underscores (`_`), periods (`.`), tildes (`~`), - plus (`+`) or percent signs (`%`). It must be between 3 and 255 characters - in length, and it must not start with `"goog"` - topic (str): The name of the topic from which this subscription is receiving - messages. Format is ``projects/{project}/topics/{topic}``. The value of - this field will be ``_deleted-topic_`` if the topic has been deleted. - push_config (Union[dict, ~google.cloud.pubsub_v1.types.PushConfig]): If push delivery is used with this subscription, this field is used to - configure it. An empty ``pushConfig`` signifies that the subscriber will - pull and ack messages using API methods. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.PushConfig` - ack_deadline_seconds (int): The approximate amount of time (on a best-effort basis) Pub/Sub waits - for the subscriber to acknowledge receipt before resending the message. - In the interval after the message is delivered and before it is - acknowledged, it is considered to be outstanding. During that time - period, the message will not be redelivered (on a best-effort basis). - - For pull subscriptions, this value is used as the initial value for the - ack deadline. To override this value for a given message, call - ``ModifyAckDeadline`` with the corresponding ``ack_id`` if using - non-streaming pull or send the ``ack_id`` in a - ``StreamingModifyAckDeadlineRequest`` if using streaming pull. The - minimum custom deadline you can specify is 10 seconds. The maximum - custom deadline you can specify is 600 seconds (10 minutes). If this - parameter is 0, a default value of 10 seconds is used. - - For push delivery, this value is also used to set the request timeout - for the call to the push endpoint. - - If the subscriber never acknowledges the message, the Pub/Sub system - will eventually redeliver the message. - retain_acked_messages (bool): Indicates whether to retain acknowledged messages. If true, then - messages are not expunged from the subscription's backlog, even if they - are acknowledged, until they fall out of the - ``message_retention_duration`` window. This must be true if you would - like to Seek to a timestamp. - message_retention_duration (Union[dict, ~google.cloud.pubsub_v1.types.Duration]): How long to retain unacknowledged messages in the subscription's - backlog, from the moment a message is published. If - ``retain_acked_messages`` is true, then this also configures the - retention of acknowledged messages, and thus configures how far back in - time a ``Seek`` can be done. Defaults to 7 days. Cannot be more than 7 - days or less than 10 minutes. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.Duration` - labels (dict[str -> str]): See Creating and - managing labels. - enable_message_ordering (bool): If true, messages published with the same ``ordering_key`` in - ``PubsubMessage`` will be delivered to the subscribers in the order in - which they are received by the Pub/Sub system. Otherwise, they may be - delivered in any order. EXPERIMENTAL: This feature is part of a closed - alpha release. This API might be changed in backward-incompatible ways - and is not recommended for production use. It is not subject to any SLA - or deprecation policy. - expiration_policy (Union[dict, ~google.cloud.pubsub_v1.types.ExpirationPolicy]): A policy that specifies the conditions for this subscription's - expiration. A subscription is considered active as long as any connected - subscriber is successfully consuming messages from the subscription or - is issuing operations on the subscription. If ``expiration_policy`` is - not set, a *default policy* with ``ttl`` of 31 days will be used. The - minimum allowed value for ``expiration_policy.ttl`` is 1 day. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.ExpirationPolicy` - dead_letter_policy (Union[dict, ~google.cloud.pubsub_v1.types.DeadLetterPolicy]): A policy that specifies the conditions for dead lettering messages in - this subscription. If dead\_letter\_policy is not set, dead lettering is - disabled. - - The Cloud Pub/Sub service account associated with this subscriptions's - parent project (i.e., - service-{project\_number}@gcp-sa-pubsub.iam.gserviceaccount.com) must - have permission to Acknowledge() messages on this subscription. - EXPERIMENTAL: This feature is part of a closed alpha release. This API - might be changed in backward-incompatible ways and is not recommended - for production use. It is not subject to any SLA or deprecation policy. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.DeadLetterPolicy` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Subscription` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "create_subscription" not in self._inner_api_calls: - self._inner_api_calls[ - "create_subscription" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_subscription, - default_retry=self._method_configs["CreateSubscription"].retry, - default_timeout=self._method_configs["CreateSubscription"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.Subscription( - name=name, - topic=topic, - push_config=push_config, - ack_deadline_seconds=ack_deadline_seconds, - retain_acked_messages=retain_acked_messages, - message_retention_duration=message_retention_duration, - labels=labels, - enable_message_ordering=enable_message_ordering, - expiration_policy=expiration_policy, - dead_letter_policy=dead_letter_policy, - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["create_subscription"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def get_subscription( - self, - subscription, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets the configuration details of a subscription. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> response = client.get_subscription(subscription) - - Args: - subscription (str): The name of the subscription to get. Format is - ``projects/{project}/subscriptions/{sub}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Subscription` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_subscription" not in self._inner_api_calls: - self._inner_api_calls[ - "get_subscription" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_subscription, - default_retry=self._method_configs["GetSubscription"].retry, - default_timeout=self._method_configs["GetSubscription"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.GetSubscriptionRequest(subscription=subscription) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription", subscription)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_subscription"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def update_subscription( - self, - subscription, - update_mask, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Updates an existing subscription. Note that certain properties of a - subscription, such as its topic, are not modifiable. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> ack_deadline_seconds = 42 - >>> subscription = {'ack_deadline_seconds': ack_deadline_seconds} - >>> paths_element = 'ack_deadline_seconds' - >>> paths = [paths_element] - >>> update_mask = {'paths': paths} - >>> - >>> response = client.update_subscription(subscription, update_mask) - - Args: - subscription (Union[dict, ~google.cloud.pubsub_v1.types.Subscription]): The updated subscription object. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.Subscription` - update_mask (Union[dict, ~google.cloud.pubsub_v1.types.FieldMask]): Indicates which fields in the provided subscription to update. - Must be specified and non-empty. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.FieldMask` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Subscription` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "update_subscription" not in self._inner_api_calls: - self._inner_api_calls[ - "update_subscription" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.update_subscription, - default_retry=self._method_configs["UpdateSubscription"].retry, - default_timeout=self._method_configs["UpdateSubscription"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.UpdateSubscriptionRequest( - subscription=subscription, update_mask=update_mask - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription.name", subscription.name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["update_subscription"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def list_subscriptions( - self, - project, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Lists matching subscriptions. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> project = client.project_path('[PROJECT]') - >>> - >>> # Iterate over all results - >>> for element in client.list_subscriptions(project): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_subscriptions(project).pages: - ... for element in page: - ... # process element - ... pass - - Args: - project (str): The name of the project in which to list subscriptions. Format is - ``projects/{project-id}``. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.GRPCIterator` instance. - An iterable of :class:`~google.cloud.pubsub_v1.types.Subscription` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_subscriptions" not in self._inner_api_calls: - self._inner_api_calls[ - "list_subscriptions" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_subscriptions, - default_retry=self._method_configs["ListSubscriptions"].retry, - default_timeout=self._method_configs["ListSubscriptions"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.ListSubscriptionsRequest( - project=project, page_size=page_size - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("project", project)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_subscriptions"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="subscriptions", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def delete_subscription( - self, - subscription, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Deletes an existing subscription. All messages retained in the - subscription are immediately dropped. Calls to ``Pull`` after deletion - will return ``NOT_FOUND``. After a subscription is deleted, a new one - may be created with the same name, but the new one has no association - with the old subscription or its topic unless the same topic is - specified. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> client.delete_subscription(subscription) - - Args: - subscription (str): The subscription to delete. Format is - ``projects/{project}/subscriptions/{sub}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "delete_subscription" not in self._inner_api_calls: - self._inner_api_calls[ - "delete_subscription" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_subscription, - default_retry=self._method_configs["DeleteSubscription"].retry, - default_timeout=self._method_configs["DeleteSubscription"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.DeleteSubscriptionRequest(subscription=subscription) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription", subscription)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["delete_subscription"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def modify_ack_deadline( - self, - subscription, - ack_ids, - ack_deadline_seconds, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Modifies the ack deadline for a specific message. This method is useful - to indicate that more time is needed to process a message by the - subscriber, or to make the message available for redelivery if the - processing was interrupted. Note that this does not modify the - subscription-level ``ackDeadlineSeconds`` used for subsequent messages. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> # TODO: Initialize `ack_ids`: - >>> ack_ids = [] - >>> - >>> # TODO: Initialize `ack_deadline_seconds`: - >>> ack_deadline_seconds = 0 - >>> - >>> client.modify_ack_deadline(subscription, ack_ids, ack_deadline_seconds) - - Args: - subscription (str): The name of the subscription. Format is - ``projects/{project}/subscriptions/{sub}``. - ack_ids (list[str]): List of acknowledgment IDs. - ack_deadline_seconds (int): The new ack deadline with respect to the time this request was sent to - the Pub/Sub system. For example, if the value is 10, the new ack - deadline will expire 10 seconds after the ``ModifyAckDeadline`` call was - made. Specifying zero might immediately make the message available for - delivery to another subscriber client. This typically results in an - increase in the rate of message redeliveries (that is, duplicates). The - minimum deadline you can specify is 0 seconds. The maximum deadline you - can specify is 600 seconds (10 minutes). - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "modify_ack_deadline" not in self._inner_api_calls: - self._inner_api_calls[ - "modify_ack_deadline" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.modify_ack_deadline, - default_retry=self._method_configs["ModifyAckDeadline"].retry, - default_timeout=self._method_configs["ModifyAckDeadline"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.ModifyAckDeadlineRequest( - subscription=subscription, - ack_ids=ack_ids, - ack_deadline_seconds=ack_deadline_seconds, - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription", subscription)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["modify_ack_deadline"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def acknowledge( - self, - subscription, - ack_ids, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Acknowledges the messages associated with the ``ack_ids`` in the - ``AcknowledgeRequest``. The Pub/Sub system can remove the relevant - messages from the subscription. - - Acknowledging a message whose ack deadline has expired may succeed, but - such a message may be redelivered later. Acknowledging a message more - than once will not result in an error. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> # TODO: Initialize `ack_ids`: - >>> ack_ids = [] - >>> - >>> client.acknowledge(subscription, ack_ids) - - Args: - subscription (str): The subscription whose message is being acknowledged. Format is - ``projects/{project}/subscriptions/{sub}``. - ack_ids (list[str]): The acknowledgment ID for the messages being acknowledged that was - returned by the Pub/Sub system in the ``Pull`` response. Must not be - empty. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "acknowledge" not in self._inner_api_calls: - self._inner_api_calls[ - "acknowledge" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.acknowledge, - default_retry=self._method_configs["Acknowledge"].retry, - default_timeout=self._method_configs["Acknowledge"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.AcknowledgeRequest( - subscription=subscription, ack_ids=ack_ids - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription", subscription)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["acknowledge"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def pull( - self, - subscription, - max_messages, - return_immediately=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Pulls messages from the server. The server may return ``UNAVAILABLE`` if - there are too many concurrent pull requests pending for the given - subscription. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> # TODO: Initialize `max_messages`: - >>> max_messages = 0 - >>> - >>> response = client.pull(subscription, max_messages) - - Args: - subscription (str): The subscription from which messages should be pulled. Format is - ``projects/{project}/subscriptions/{sub}``. - max_messages (int): The maximum number of messages to return for this request. Must be a - positive integer. The Pub/Sub system may return fewer than the number - specified. - return_immediately (bool): If this field set to true, the system will respond immediately even if - it there are no messages available to return in the ``Pull`` response. - Otherwise, the system may wait (for a bounded amount of time) until at - least one message is available, rather than returning no messages. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.PullResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "pull" not in self._inner_api_calls: - self._inner_api_calls["pull"] = google.api_core.gapic_v1.method.wrap_method( - self.transport.pull, - default_retry=self._method_configs["Pull"].retry, - default_timeout=self._method_configs["Pull"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.PullRequest( - subscription=subscription, - max_messages=max_messages, - return_immediately=return_immediately, - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription", subscription)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["pull"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def streaming_pull( - self, - requests, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Establishes a stream with the server, which sends messages down to the - client. The client streams acknowledgements and ack deadline - modifications back to the server. The server will close the stream and - return the status on any error. The server may close the stream with - status ``UNAVAILABLE`` to reassign server-side resources, in which case, - the client should re-establish the stream. Flow control can be achieved - by configuring the underlying RPC channel. - - EXPERIMENTAL: This method interface might change in the future. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> # TODO: Initialize `stream_ack_deadline_seconds`: - >>> stream_ack_deadline_seconds = 0 - >>> request = {'subscription': subscription, 'stream_ack_deadline_seconds': stream_ack_deadline_seconds} - >>> - >>> requests = [request] - >>> for element in client.streaming_pull(requests): - ... # process element - ... pass - - Args: - requests (iterator[dict|google.cloud.pubsub_v1.proto.pubsub_pb2.StreamingPullRequest]): The input objects. If a dict is provided, it must be of the - same form as the protobuf message :class:`~google.cloud.pubsub_v1.types.StreamingPullRequest` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - Iterable[~google.cloud.pubsub_v1.types.StreamingPullResponse]. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "streaming_pull" not in self._inner_api_calls: - self._inner_api_calls[ - "streaming_pull" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.streaming_pull, - default_retry=self._method_configs["StreamingPull"].retry, - default_timeout=self._method_configs["StreamingPull"].timeout, - client_info=self._client_info, - ) - - return self._inner_api_calls["streaming_pull"]( - requests, retry=retry, timeout=timeout, metadata=metadata - ) - - def modify_push_config( - self, - subscription, - push_config, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Modifies the ``PushConfig`` for a specified subscription. - - This may be used to change a push subscription to a pull one (signified - by an empty ``PushConfig``) or vice versa, or change the endpoint URL - and other attributes of a push subscription. Messages will accumulate - for delivery continuously through the call regardless of changes to the - ``PushConfig``. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> # TODO: Initialize `push_config`: - >>> push_config = {} - >>> - >>> client.modify_push_config(subscription, push_config) - - Args: - subscription (str): The name of the subscription. Format is - ``projects/{project}/subscriptions/{sub}``. - push_config (Union[dict, ~google.cloud.pubsub_v1.types.PushConfig]): The push configuration for future deliveries. - - An empty ``pushConfig`` indicates that the Pub/Sub system should stop - pushing messages from the given subscription and allow messages to be - pulled and acknowledged - effectively pausing the subscription if - ``Pull`` or ``StreamingPull`` is not called. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.PushConfig` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "modify_push_config" not in self._inner_api_calls: - self._inner_api_calls[ - "modify_push_config" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.modify_push_config, - default_retry=self._method_configs["ModifyPushConfig"].retry, - default_timeout=self._method_configs["ModifyPushConfig"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.ModifyPushConfigRequest( - subscription=subscription, push_config=push_config - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription", subscription)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["modify_push_config"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def list_snapshots( - self, - project, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Lists the existing snapshots. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> project = client.project_path('[PROJECT]') - >>> - >>> # Iterate over all results - >>> for element in client.list_snapshots(project): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_snapshots(project).pages: - ... for element in page: - ... # process element - ... pass - - Args: - project (str): The name of the project in which to list snapshots. Format is - ``projects/{project-id}``. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.GRPCIterator` instance. - An iterable of :class:`~google.cloud.pubsub_v1.types.Snapshot` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_snapshots" not in self._inner_api_calls: - self._inner_api_calls[ - "list_snapshots" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_snapshots, - default_retry=self._method_configs["ListSnapshots"].retry, - default_timeout=self._method_configs["ListSnapshots"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.ListSnapshotsRequest(project=project, page_size=page_size) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("project", project)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_snapshots"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="snapshots", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def create_snapshot( - self, - name, - subscription, - labels=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Creates a snapshot from the requested subscription. Snapshots are used - in Seek operations, which allow you to manage message acknowledgments in - bulk. That is, you can set the acknowledgment state of messages in an - existing subscription to the state captured by a snapshot. If the - snapshot already exists, returns ``ALREADY_EXISTS``. If the requested - subscription doesn't exist, returns ``NOT_FOUND``. If the backlog in the - subscription is too old -- and the resulting snapshot would expire in - less than 1 hour -- then ``FAILED_PRECONDITION`` is returned. See also - the ``Snapshot.expire_time`` field. If the name is not provided in the - request, the server will assign a random name for this snapshot on the - same project as the subscription, conforming to the `resource name - format `__. - The generated name is populated in the returned Snapshot object. Note - that for REST API requests, you must specify a name in the request. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> name = client.snapshot_path('[PROJECT]', '[SNAPSHOT]') - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> response = client.create_snapshot(name, subscription) - - Args: - name (str): Optional user-provided name for this snapshot. If the name is not - provided in the request, the server will assign a random name for this - snapshot on the same project as the subscription. Note that for REST API - requests, you must specify a name. See the resource name rules. Format - is ``projects/{project}/snapshots/{snap}``. - subscription (str): The subscription whose backlog the snapshot retains. Specifically, the - created snapshot is guaranteed to retain: (a) The existing backlog on - the subscription. More precisely, this is defined as the messages in the - subscription's backlog that are unacknowledged upon the successful - completion of the ``CreateSnapshot`` request; as well as: (b) Any - messages published to the subscription's topic following the successful - completion of the CreateSnapshot request. Format is - ``projects/{project}/subscriptions/{sub}``. - labels (dict[str -> str]): See Creating and - managing labels. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Snapshot` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "create_snapshot" not in self._inner_api_calls: - self._inner_api_calls[ - "create_snapshot" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_snapshot, - default_retry=self._method_configs["CreateSnapshot"].retry, - default_timeout=self._method_configs["CreateSnapshot"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.CreateSnapshotRequest( - name=name, subscription=subscription, labels=labels - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["create_snapshot"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def update_snapshot( - self, - snapshot, - update_mask, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Updates an existing snapshot. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> seconds = 123456 - >>> expire_time = {'seconds': seconds} - >>> snapshot = {'expire_time': expire_time} - >>> paths_element = 'expire_time' - >>> paths = [paths_element] - >>> update_mask = {'paths': paths} - >>> - >>> response = client.update_snapshot(snapshot, update_mask) - - Args: - snapshot (Union[dict, ~google.cloud.pubsub_v1.types.Snapshot]): The updated snapshot object. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.Snapshot` - update_mask (Union[dict, ~google.cloud.pubsub_v1.types.FieldMask]): Indicates which fields in the provided snapshot to update. - Must be specified and non-empty. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.FieldMask` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Snapshot` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "update_snapshot" not in self._inner_api_calls: - self._inner_api_calls[ - "update_snapshot" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.update_snapshot, - default_retry=self._method_configs["UpdateSnapshot"].retry, - default_timeout=self._method_configs["UpdateSnapshot"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.UpdateSnapshotRequest( - snapshot=snapshot, update_mask=update_mask - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("snapshot.name", snapshot.name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["update_snapshot"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def delete_snapshot( - self, - snapshot, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Removes an existing snapshot. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot.

- When the snapshot is deleted, all messages retained in the snapshot - are immediately dropped. After a snapshot is deleted, a new one may be - created with the same name, but the new one has no association with the old - snapshot or its subscription, unless the same subscription is specified. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> snapshot = client.snapshot_path('[PROJECT]', '[SNAPSHOT]') - >>> - >>> client.delete_snapshot(snapshot) - - Args: - snapshot (str): The name of the snapshot to delete. Format is - ``projects/{project}/snapshots/{snap}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "delete_snapshot" not in self._inner_api_calls: - self._inner_api_calls[ - "delete_snapshot" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_snapshot, - default_retry=self._method_configs["DeleteSnapshot"].retry, - default_timeout=self._method_configs["DeleteSnapshot"].timeout, - client_info=self._client_info, - ) - - request = pubsub_pb2.DeleteSnapshotRequest(snapshot=snapshot) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("snapshot", snapshot)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - self._inner_api_calls["delete_snapshot"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def seek( - self, - subscription, - time=None, - snapshot=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Seeks an existing subscription to a point in time or to a given snapshot, - whichever is provided in the request. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. Note that both the subscription and the snapshot - must be on the same topic. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> subscription = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> response = client.seek(subscription) - - Args: - subscription (str): The subscription to affect. - time (Union[dict, ~google.cloud.pubsub_v1.types.Timestamp]): The time to seek to. Messages retained in the subscription that were - published before this time are marked as acknowledged, and messages - retained in the subscription that were published after this time are - marked as unacknowledged. Note that this operation affects only those - messages retained in the subscription (configured by the combination of - ``message_retention_duration`` and ``retain_acked_messages``). For - example, if ``time`` corresponds to a point before the message retention - window (or to a point before the system's notion of the subscription - creation time), only retained messages will be marked as unacknowledged, - and already-expunged messages will not be restored. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.Timestamp` - snapshot (str): The snapshot to seek to. The snapshot's topic must be the same as that - of the provided subscription. Format is - ``projects/{project}/snapshots/{snap}``. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.SeekResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "seek" not in self._inner_api_calls: - self._inner_api_calls["seek"] = google.api_core.gapic_v1.method.wrap_method( - self.transport.seek, - default_retry=self._method_configs["Seek"].retry, - default_timeout=self._method_configs["Seek"].timeout, - client_info=self._client_info, - ) - - # Sanity check: We have some fields which are mutually exclusive; - # raise ValueError if more than one is sent. - google.api_core.protobuf_helpers.check_oneof(time=time, snapshot=snapshot) - - request = pubsub_pb2.SeekRequest( - subscription=subscription, time=time, snapshot=snapshot - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("subscription", subscription)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["seek"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def set_iam_policy( - self, - resource, - policy, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Sets the access control policy on the specified resource. Replaces any - existing policy. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> resource = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> # TODO: Initialize `policy`: - >>> policy = {} - >>> - >>> response = client.set_iam_policy(resource, policy) - - Args: - resource (str): REQUIRED: The resource for which the policy is being specified. - See the operation documentation for the appropriate value for this field. - policy (Union[dict, ~google.cloud.pubsub_v1.types.Policy]): REQUIRED: The complete policy to be applied to the ``resource``. The - size of the policy is limited to a few 10s of KB. An empty policy is a - valid policy but certain Cloud Platform services (such as Projects) - might reject them. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.Policy` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Policy` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "set_iam_policy" not in self._inner_api_calls: - self._inner_api_calls[ - "set_iam_policy" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.set_iam_policy, - default_retry=self._method_configs["SetIamPolicy"].retry, - default_timeout=self._method_configs["SetIamPolicy"].timeout, - client_info=self._client_info, - ) - - request = iam_policy_pb2.SetIamPolicyRequest(resource=resource, policy=policy) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("resource", resource)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["set_iam_policy"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def get_iam_policy( - self, - resource, - options_=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets the access control policy for a resource. - Returns an empty policy if the resource exists and does not have a policy - set. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> resource = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> response = client.get_iam_policy(resource) - - Args: - resource (str): REQUIRED: The resource for which the policy is being requested. - See the operation documentation for the appropriate value for this field. - options_ (Union[dict, ~google.cloud.pubsub_v1.types.GetPolicyOptions]): OPTIONAL: A ``GetPolicyOptions`` object for specifying options to - ``GetIamPolicy``. This field is only used by Cloud IAM. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.pubsub_v1.types.GetPolicyOptions` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.Policy` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_iam_policy" not in self._inner_api_calls: - self._inner_api_calls[ - "get_iam_policy" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_iam_policy, - default_retry=self._method_configs["GetIamPolicy"].retry, - default_timeout=self._method_configs["GetIamPolicy"].timeout, - client_info=self._client_info, - ) - - request = iam_policy_pb2.GetIamPolicyRequest( - resource=resource, options=options_ - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("resource", resource)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_iam_policy"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def test_iam_permissions( - self, - resource, - permissions, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Returns permissions that a caller has on the specified resource. If the - resource does not exist, this will return an empty set of permissions, - not a NOT\_FOUND error. - - Note: This operation is designed to be used for building - permission-aware UIs and command-line tools, not for authorization - checking. This operation may "fail open" without warning. - - Example: - >>> from google.cloud import pubsub_v1 - >>> - >>> client = pubsub_v1.SubscriberClient() - >>> - >>> resource = client.subscription_path('[PROJECT]', '[SUBSCRIPTION]') - >>> - >>> # TODO: Initialize `permissions`: - >>> permissions = [] - >>> - >>> response = client.test_iam_permissions(resource, permissions) - - Args: - resource (str): REQUIRED: The resource for which the policy detail is being requested. - See the operation documentation for the appropriate value for this field. - permissions (list[str]): The set of permissions to check for the ``resource``. Permissions with - wildcards (such as '*' or 'storage.*') are not allowed. For more - information see `IAM - Overview `__. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.pubsub_v1.types.TestIamPermissionsResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "test_iam_permissions" not in self._inner_api_calls: - self._inner_api_calls[ - "test_iam_permissions" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.test_iam_permissions, - default_retry=self._method_configs["TestIamPermissions"].retry, - default_timeout=self._method_configs["TestIamPermissions"].timeout, - client_info=self._client_info, - ) - - request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, permissions=permissions - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("resource", resource)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["test_iam_permissions"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/pubsub/google/cloud/pubsub_v1/gapic/subscriber_client_config.py b/pubsub/google/cloud/pubsub_v1/gapic/subscriber_client_config.py deleted file mode 100644 index 3955f2da1dcb..000000000000 --- a/pubsub/google/cloud/pubsub_v1/gapic/subscriber_client_config.py +++ /dev/null @@ -1,138 +0,0 @@ -config = { - "interfaces": { - "google.pubsub.v1.Subscriber": { - "retry_codes": { - "idempotent": ["ABORTED", "UNAVAILABLE", "UNKNOWN"], - "non_idempotent": ["UNAVAILABLE"], - "streaming_pull": [ - "ABORTED", - "DEADLINE_EXCEEDED", - "INTERNAL", - "RESOURCE_EXHAUSTED", - "UNAVAILABLE", - ], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 60000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 60000, - "total_timeout_millis": 600000, - }, - "messaging": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 5000, - "rpc_timeout_multiplier": 1.3, - "max_rpc_timeout_millis": 600000, - "total_timeout_millis": 600000, - }, - "streaming_messaging": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 600000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 600000, - "total_timeout_millis": 600000, - }, - }, - "methods": { - "CreateSubscription": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "GetSubscription": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "UpdateSubscription": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "ListSubscriptions": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "DeleteSubscription": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "ModifyAckDeadline": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "Acknowledge": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "messaging", - }, - "Pull": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "messaging", - }, - "StreamingPull": { - "timeout_millis": 900000, - "retry_codes_name": "streaming_pull", - "retry_params_name": "streaming_messaging", - }, - "ModifyPushConfig": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "ListSnapshots": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "CreateSnapshot": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "UpdateSnapshot": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "DeleteSnapshot": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "Seek": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "SetIamPolicy": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "GetIamPolicy": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "TestIamPermissions": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/pubsub/google/cloud/pubsub_v1/gapic/transports/__init__.py b/pubsub/google/cloud/pubsub_v1/gapic/transports/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/pubsub/google/cloud/pubsub_v1/gapic/transports/publisher_grpc_transport.py b/pubsub/google/cloud/pubsub_v1/gapic/transports/publisher_grpc_transport.py deleted file mode 100644 index aedcc8c465e1..000000000000 --- a/pubsub/google/cloud/pubsub_v1/gapic/transports/publisher_grpc_transport.py +++ /dev/null @@ -1,260 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers - -from google.cloud.pubsub_v1.proto import pubsub_pb2_grpc -from google.iam.v1 import iam_policy_pb2_grpc as iam_policy_pb2_grpc - - -class PublisherGrpcTransport(object): - """gRPC transport class providing stubs for - google.pubsub.v1 Publisher API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/pubsub", - ) - - def __init__( - self, channel=None, credentials=None, address="pubsub.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = { - "iam_policy_stub": iam_policy_pb2_grpc.IAMPolicyStub(channel), - "publisher_stub": pubsub_pb2_grpc.PublisherStub(channel), - } - - @classmethod - def create_channel( - cls, address="pubsub.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def create_topic(self): - """Return the gRPC stub for :meth:`PublisherClient.create_topic`. - - Creates the given topic with the given name. See the resource name - rules. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["publisher_stub"].CreateTopic - - @property - def update_topic(self): - """Return the gRPC stub for :meth:`PublisherClient.update_topic`. - - Updates an existing topic. Note that certain properties of a - topic are not modifiable. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["publisher_stub"].UpdateTopic - - @property - def publish(self): - """Return the gRPC stub for :meth:`PublisherClient.publish`. - - Adds one or more messages to the topic. Returns ``NOT_FOUND`` if the - topic does not exist. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["publisher_stub"].Publish - - @property - def get_topic(self): - """Return the gRPC stub for :meth:`PublisherClient.get_topic`. - - Gets the configuration of a topic. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["publisher_stub"].GetTopic - - @property - def list_topics(self): - """Return the gRPC stub for :meth:`PublisherClient.list_topics`. - - Lists matching topics. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["publisher_stub"].ListTopics - - @property - def list_topic_subscriptions(self): - """Return the gRPC stub for :meth:`PublisherClient.list_topic_subscriptions`. - - Lists the names of the subscriptions on this topic. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["publisher_stub"].ListTopicSubscriptions - - @property - def delete_topic(self): - """Return the gRPC stub for :meth:`PublisherClient.delete_topic`. - - Deletes the topic with the given name. Returns ``NOT_FOUND`` if the - topic does not exist. After a topic is deleted, a new topic may be - created with the same name; this is an entirely new topic with none of - the old configuration or subscriptions. Existing subscriptions to this - topic are not deleted, but their ``topic`` field is set to - ``_deleted-topic_``. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["publisher_stub"].DeleteTopic - - @property - def set_iam_policy(self): - """Return the gRPC stub for :meth:`PublisherClient.set_iam_policy`. - - Sets the access control policy on the specified resource. Replaces any - existing policy. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_policy_stub"].SetIamPolicy - - @property - def get_iam_policy(self): - """Return the gRPC stub for :meth:`PublisherClient.get_iam_policy`. - - Gets the access control policy for a resource. - Returns an empty policy if the resource exists and does not have a policy - set. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_policy_stub"].GetIamPolicy - - @property - def test_iam_permissions(self): - """Return the gRPC stub for :meth:`PublisherClient.test_iam_permissions`. - - Returns permissions that a caller has on the specified resource. If the - resource does not exist, this will return an empty set of permissions, - not a NOT\_FOUND error. - - Note: This operation is designed to be used for building - permission-aware UIs and command-line tools, not for authorization - checking. This operation may "fail open" without warning. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_policy_stub"].TestIamPermissions diff --git a/pubsub/google/cloud/pubsub_v1/gapic/transports/subscriber_grpc_transport.py b/pubsub/google/cloud/pubsub_v1/gapic/transports/subscriber_grpc_transport.py deleted file mode 100644 index fa8ac9f29329..000000000000 --- a/pubsub/google/cloud/pubsub_v1/gapic/transports/subscriber_grpc_transport.py +++ /dev/null @@ -1,434 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers - -from google.cloud.pubsub_v1.proto import pubsub_pb2_grpc -from google.iam.v1 import iam_policy_pb2_grpc as iam_policy_pb2_grpc - - -class SubscriberGrpcTransport(object): - """gRPC transport class providing stubs for - google.pubsub.v1 Subscriber API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ( - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/pubsub", - ) - - def __init__( - self, channel=None, credentials=None, address="pubsub.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = { - "iam_policy_stub": iam_policy_pb2_grpc.IAMPolicyStub(channel), - "subscriber_stub": pubsub_pb2_grpc.SubscriberStub(channel), - } - - @classmethod - def create_channel( - cls, address="pubsub.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def create_subscription(self): - """Return the gRPC stub for :meth:`SubscriberClient.create_subscription`. - - Creates a subscription to a given topic. See the resource name rules. If - the subscription already exists, returns ``ALREADY_EXISTS``. If the - corresponding topic doesn't exist, returns ``NOT_FOUND``. - - If the name is not provided in the request, the server will assign a - random name for this subscription on the same project as the topic, - conforming to the `resource name - format `__. - The generated name is populated in the returned Subscription object. - Note that for REST API requests, you must specify a name in the request. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].CreateSubscription - - @property - def get_subscription(self): - """Return the gRPC stub for :meth:`SubscriberClient.get_subscription`. - - Gets the configuration details of a subscription. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].GetSubscription - - @property - def update_subscription(self): - """Return the gRPC stub for :meth:`SubscriberClient.update_subscription`. - - Updates an existing subscription. Note that certain properties of a - subscription, such as its topic, are not modifiable. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].UpdateSubscription - - @property - def list_subscriptions(self): - """Return the gRPC stub for :meth:`SubscriberClient.list_subscriptions`. - - Lists matching subscriptions. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].ListSubscriptions - - @property - def delete_subscription(self): - """Return the gRPC stub for :meth:`SubscriberClient.delete_subscription`. - - Deletes an existing subscription. All messages retained in the - subscription are immediately dropped. Calls to ``Pull`` after deletion - will return ``NOT_FOUND``. After a subscription is deleted, a new one - may be created with the same name, but the new one has no association - with the old subscription or its topic unless the same topic is - specified. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].DeleteSubscription - - @property - def modify_ack_deadline(self): - """Return the gRPC stub for :meth:`SubscriberClient.modify_ack_deadline`. - - Modifies the ack deadline for a specific message. This method is useful - to indicate that more time is needed to process a message by the - subscriber, or to make the message available for redelivery if the - processing was interrupted. Note that this does not modify the - subscription-level ``ackDeadlineSeconds`` used for subsequent messages. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].ModifyAckDeadline - - @property - def acknowledge(self): - """Return the gRPC stub for :meth:`SubscriberClient.acknowledge`. - - Acknowledges the messages associated with the ``ack_ids`` in the - ``AcknowledgeRequest``. The Pub/Sub system can remove the relevant - messages from the subscription. - - Acknowledging a message whose ack deadline has expired may succeed, but - such a message may be redelivered later. Acknowledging a message more - than once will not result in an error. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].Acknowledge - - @property - def pull(self): - """Return the gRPC stub for :meth:`SubscriberClient.pull`. - - Pulls messages from the server. The server may return ``UNAVAILABLE`` if - there are too many concurrent pull requests pending for the given - subscription. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].Pull - - @property - def streaming_pull(self): - """Return the gRPC stub for :meth:`SubscriberClient.streaming_pull`. - - Establishes a stream with the server, which sends messages down to the - client. The client streams acknowledgements and ack deadline - modifications back to the server. The server will close the stream and - return the status on any error. The server may close the stream with - status ``UNAVAILABLE`` to reassign server-side resources, in which case, - the client should re-establish the stream. Flow control can be achieved - by configuring the underlying RPC channel. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].StreamingPull - - @property - def modify_push_config(self): - """Return the gRPC stub for :meth:`SubscriberClient.modify_push_config`. - - Modifies the ``PushConfig`` for a specified subscription. - - This may be used to change a push subscription to a pull one (signified - by an empty ``PushConfig``) or vice versa, or change the endpoint URL - and other attributes of a push subscription. Messages will accumulate - for delivery continuously through the call regardless of changes to the - ``PushConfig``. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].ModifyPushConfig - - @property - def list_snapshots(self): - """Return the gRPC stub for :meth:`SubscriberClient.list_snapshots`. - - Lists the existing snapshots. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].ListSnapshots - - @property - def create_snapshot(self): - """Return the gRPC stub for :meth:`SubscriberClient.create_snapshot`. - - Creates a snapshot from the requested subscription. Snapshots are used - in Seek operations, which allow you to manage message acknowledgments in - bulk. That is, you can set the acknowledgment state of messages in an - existing subscription to the state captured by a snapshot. If the - snapshot already exists, returns ``ALREADY_EXISTS``. If the requested - subscription doesn't exist, returns ``NOT_FOUND``. If the backlog in the - subscription is too old -- and the resulting snapshot would expire in - less than 1 hour -- then ``FAILED_PRECONDITION`` is returned. See also - the ``Snapshot.expire_time`` field. If the name is not provided in the - request, the server will assign a random name for this snapshot on the - same project as the subscription, conforming to the `resource name - format `__. - The generated name is populated in the returned Snapshot object. Note - that for REST API requests, you must specify a name in the request. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].CreateSnapshot - - @property - def update_snapshot(self): - """Return the gRPC stub for :meth:`SubscriberClient.update_snapshot`. - - Updates an existing snapshot. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].UpdateSnapshot - - @property - def delete_snapshot(self): - """Return the gRPC stub for :meth:`SubscriberClient.delete_snapshot`. - - Removes an existing snapshot. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot.

- When the snapshot is deleted, all messages retained in the snapshot - are immediately dropped. After a snapshot is deleted, a new one may be - created with the same name, but the new one has no association with the old - snapshot or its subscription, unless the same subscription is specified. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].DeleteSnapshot - - @property - def seek(self): - """Return the gRPC stub for :meth:`SubscriberClient.seek`. - - Seeks an existing subscription to a point in time or to a given snapshot, - whichever is provided in the request. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. Note that both the subscription and the snapshot - must be on the same topic. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["subscriber_stub"].Seek - - @property - def set_iam_policy(self): - """Return the gRPC stub for :meth:`SubscriberClient.set_iam_policy`. - - Sets the access control policy on the specified resource. Replaces any - existing policy. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_policy_stub"].SetIamPolicy - - @property - def get_iam_policy(self): - """Return the gRPC stub for :meth:`SubscriberClient.get_iam_policy`. - - Gets the access control policy for a resource. - Returns an empty policy if the resource exists and does not have a policy - set. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_policy_stub"].GetIamPolicy - - @property - def test_iam_permissions(self): - """Return the gRPC stub for :meth:`SubscriberClient.test_iam_permissions`. - - Returns permissions that a caller has on the specified resource. If the - resource does not exist, this will return an empty set of permissions, - not a NOT\_FOUND error. - - Note: This operation is designed to be used for building - permission-aware UIs and command-line tools, not for authorization - checking. This operation may "fail open" without warning. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["iam_policy_stub"].TestIamPermissions diff --git a/pubsub/google/cloud/pubsub_v1/proto/__init__.py b/pubsub/google/cloud/pubsub_v1/proto/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/pubsub/google/cloud/pubsub_v1/proto/pubsub.proto b/pubsub/google/cloud/pubsub_v1/proto/pubsub.proto deleted file mode 100644 index 3ad6355a8bf6..000000000000 --- a/pubsub/google/cloud/pubsub_v1/proto/pubsub.proto +++ /dev/null @@ -1,1067 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.pubsub.v1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/field_mask.proto"; -import "google/protobuf/timestamp.proto"; - -option cc_enable_arenas = true; -option csharp_namespace = "Google.Cloud.PubSub.V1"; -option go_package = "google.golang.org/genproto/googleapis/pubsub/v1;pubsub"; -option java_multiple_files = true; -option java_outer_classname = "PubsubProto"; -option java_package = "com.google.pubsub.v1"; -option php_namespace = "Google\\Cloud\\PubSub\\V1"; -option ruby_package = "Google::Cloud::PubSub::V1"; - -// The service that an application uses to manipulate topics, and to send -// messages to a topic. -service Publisher { - option (google.api.default_host) = "pubsub.googleapis.com"; - option (google.api.oauth_scopes) = - "https://www.googleapis.com/auth/cloud-platform," - "https://www.googleapis.com/auth/pubsub"; - - // Creates the given topic with the given name. See the - // - // resource name rules. - rpc CreateTopic(Topic) returns (Topic) { - option (google.api.http) = { - put: "/v1/{name=projects/*/topics/*}" - body: "*" - }; - } - - // Updates an existing topic. Note that certain properties of a - // topic are not modifiable. - rpc UpdateTopic(UpdateTopicRequest) returns (Topic) { - option (google.api.http) = { - patch: "/v1/{topic.name=projects/*/topics/*}" - body: "*" - }; - } - - // Adds one or more messages to the topic. Returns `NOT_FOUND` if the topic - // does not exist. - rpc Publish(PublishRequest) returns (PublishResponse) { - option (google.api.http) = { - post: "/v1/{topic=projects/*/topics/*}:publish" - body: "*" - }; - } - - // Gets the configuration of a topic. - rpc GetTopic(GetTopicRequest) returns (Topic) { - option (google.api.http) = { - get: "/v1/{topic=projects/*/topics/*}" - }; - } - - // Lists matching topics. - rpc ListTopics(ListTopicsRequest) returns (ListTopicsResponse) { - option (google.api.http) = { - get: "/v1/{project=projects/*}/topics" - }; - } - - // Lists the names of the subscriptions on this topic. - rpc ListTopicSubscriptions(ListTopicSubscriptionsRequest) - returns (ListTopicSubscriptionsResponse) { - option (google.api.http) = { - get: "/v1/{topic=projects/*/topics/*}/subscriptions" - }; - } - - // Lists the names of the snapshots on this topic. Snapshots are used in - // Seek - // operations, which allow - // you to manage message acknowledgments in bulk. That is, you can set the - // acknowledgment state of messages in an existing subscription to the state - // captured by a snapshot. - rpc ListTopicSnapshots(ListTopicSnapshotsRequest) - returns (ListTopicSnapshotsResponse) { - option (google.api.http) = { - get: "/v1/{topic=projects/*/topics/*}/snapshots" - }; - } - - // Deletes the topic with the given name. Returns `NOT_FOUND` if the topic - // does not exist. After a topic is deleted, a new topic may be created with - // the same name; this is an entirely new topic with none of the old - // configuration or subscriptions. Existing subscriptions to this topic are - // not deleted, but their `topic` field is set to `_deleted-topic_`. - rpc DeleteTopic(DeleteTopicRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - delete: "/v1/{topic=projects/*/topics/*}" - }; - } -} - -message MessageStoragePolicy { - // A list of IDs of GCP regions where messages that are published to the topic - // may be persisted in storage. Messages published by publishers running in - // non-allowed GCP regions (or running outside of GCP altogether) will be - // routed for storage in one of the allowed regions. An empty list means that - // no regions are allowed, and is not a valid configuration. - repeated string allowed_persistence_regions = 1; -} - -// A topic resource. -message Topic { - // The name of the topic. It must have the format - // `"projects/{project}/topics/{topic}"`. `{topic}` must start with a letter, - // and contain only letters (`[A-Za-z]`), numbers (`[0-9]`), dashes (`-`), - // underscores (`_`), periods (`.`), tildes (`~`), plus (`+`) or percent - // signs (`%`). It must be between 3 and 255 characters in length, and it - // must not start with `"goog"`. - string name = 1; - - // See Creating and - // managing labels. - map labels = 2; - - // Policy constraining the set of Google Cloud Platform regions where messages - // published to the topic may be stored. If not present, then no constraints - // are in effect. - MessageStoragePolicy message_storage_policy = 3; - - // The resource name of the Cloud KMS CryptoKey to be used to protect access - // to messages published on this topic. - // - // The expected format is `projects/*/locations/*/keyRings/*/cryptoKeys/*`. - string kms_key_name = 5; -} - -// A message that is published by publishers and consumed by subscribers. The -// message must contain either a non-empty data field or at least one attribute. -// Note that client libraries represent this object differently -// depending on the language. See the corresponding -// client -// library documentation for more information. See -// Quotas and limits -// for more information about message limits. -message PubsubMessage { - // The message data field. If this field is empty, the message must contain - // at least one attribute. - bytes data = 1; - - // Optional attributes for this message. - map attributes = 2; - - // ID of this message, assigned by the server when the message is published. - // Guaranteed to be unique within the topic. This value may be read by a - // subscriber that receives a `PubsubMessage` via a `Pull` call or a push - // delivery. It must not be populated by the publisher in a `Publish` call. - string message_id = 3; - - // The time at which the message was published, populated by the server when - // it receives the `Publish` call. It must not be populated by the - // publisher in a `Publish` call. - google.protobuf.Timestamp publish_time = 4; - - // Identifies related messages for which publish order should be respected. - // If a `Subscription` has `enable_message_ordering` set to `true`, messages - // published with the same `ordering_key` value will be delivered to - // subscribers in the order in which they are received by the Pub/Sub system. - // EXPERIMENTAL: This feature is part of a closed alpha release. This - // API might be changed in backward-incompatible ways and is not recommended - // for production use. It is not subject to any SLA or deprecation policy. - string ordering_key = 5; -} - -// Request for the GetTopic method. -message GetTopicRequest { - // The name of the topic to get. - // Format is `projects/{project}/topics/{topic}`. - string topic = 1; -} - -// Request for the UpdateTopic method. -message UpdateTopicRequest { - // The updated topic object. - Topic topic = 1; - - // Indicates which fields in the provided topic to update. Must be specified - // and non-empty. Note that if `update_mask` contains - // "message_storage_policy" then the new value will be determined based on the - // policy configured at the project or organization level. The - // `message_storage_policy` must not be set in the `topic` provided above. - google.protobuf.FieldMask update_mask = 2; -} - -// Request for the Publish method. -message PublishRequest { - // The messages in the request will be published on this topic. - // Format is `projects/{project}/topics/{topic}`. - string topic = 1; - - // The messages to publish. - repeated PubsubMessage messages = 2; -} - -// Response for the `Publish` method. -message PublishResponse { - // The server-assigned ID of each published message, in the same order as - // the messages in the request. IDs are guaranteed to be unique within - // the topic. - repeated string message_ids = 1; -} - -// Request for the `ListTopics` method. -message ListTopicsRequest { - // The name of the project in which to list topics. - // Format is `projects/{project-id}`. - string project = 1; - - // Maximum number of topics to return. - int32 page_size = 2; - - // The value returned by the last `ListTopicsResponse`; indicates that this is - // a continuation of a prior `ListTopics` call, and that the system should - // return the next page of data. - string page_token = 3; -} - -// Response for the `ListTopics` method. -message ListTopicsResponse { - // The resulting topics. - repeated Topic topics = 1; - - // If not empty, indicates that there may be more topics that match the - // request; this value should be passed in a new `ListTopicsRequest`. - string next_page_token = 2; -} - -// Request for the `ListTopicSubscriptions` method. -message ListTopicSubscriptionsRequest { - // The name of the topic that subscriptions are attached to. - // Format is `projects/{project}/topics/{topic}`. - string topic = 1; - - // Maximum number of subscription names to return. - int32 page_size = 2; - - // The value returned by the last `ListTopicSubscriptionsResponse`; indicates - // that this is a continuation of a prior `ListTopicSubscriptions` call, and - // that the system should return the next page of data. - string page_token = 3; -} - -// Response for the `ListTopicSubscriptions` method. -message ListTopicSubscriptionsResponse { - // The names of the subscriptions that match the request. - repeated string subscriptions = 1; - - // If not empty, indicates that there may be more subscriptions that match - // the request; this value should be passed in a new - // `ListTopicSubscriptionsRequest` to get more subscriptions. - string next_page_token = 2; -} - -// Request for the `ListTopicSnapshots` method. -message ListTopicSnapshotsRequest { - // The name of the topic that snapshots are attached to. - // Format is `projects/{project}/topics/{topic}`. - string topic = 1; - - // Maximum number of snapshot names to return. - int32 page_size = 2; - - // The value returned by the last `ListTopicSnapshotsResponse`; indicates - // that this is a continuation of a prior `ListTopicSnapshots` call, and - // that the system should return the next page of data. - string page_token = 3; -} - -// Response for the `ListTopicSnapshots` method. -message ListTopicSnapshotsResponse { - // The names of the snapshots that match the request. - repeated string snapshots = 1; - - // If not empty, indicates that there may be more snapshots that match - // the request; this value should be passed in a new - // `ListTopicSnapshotsRequest` to get more snapshots. - string next_page_token = 2; -} - -// Request for the `DeleteTopic` method. -message DeleteTopicRequest { - // Name of the topic to delete. - // Format is `projects/{project}/topics/{topic}`. - string topic = 1; -} - -// The service that an application uses to manipulate subscriptions and to -// consume messages from a subscription via the `Pull` method or by -// establishing a bi-directional stream using the `StreamingPull` method. -service Subscriber { - option (google.api.default_host) = "pubsub.googleapis.com"; - option (google.api.oauth_scopes) = - "https://www.googleapis.com/auth/cloud-platform," - "https://www.googleapis.com/auth/pubsub"; - - // Creates a subscription to a given topic. See the - // - // resource name rules. - // If the subscription already exists, returns `ALREADY_EXISTS`. - // If the corresponding topic doesn't exist, returns `NOT_FOUND`. - // - // If the name is not provided in the request, the server will assign a random - // name for this subscription on the same project as the topic, conforming - // to the - // [resource name - // format](https://cloud.google.com/pubsub/docs/admin#resource_names). The - // generated name is populated in the returned Subscription object. Note that - // for REST API requests, you must specify a name in the request. - rpc CreateSubscription(Subscription) returns (Subscription) { - option (google.api.http) = { - put: "/v1/{name=projects/*/subscriptions/*}" - body: "*" - }; - } - - // Gets the configuration details of a subscription. - rpc GetSubscription(GetSubscriptionRequest) returns (Subscription) { - option (google.api.http) = { - get: "/v1/{subscription=projects/*/subscriptions/*}" - }; - } - - // Updates an existing subscription. Note that certain properties of a - // subscription, such as its topic, are not modifiable. - rpc UpdateSubscription(UpdateSubscriptionRequest) returns (Subscription) { - option (google.api.http) = { - patch: "/v1/{subscription.name=projects/*/subscriptions/*}" - body: "*" - }; - } - - // Lists matching subscriptions. - rpc ListSubscriptions(ListSubscriptionsRequest) - returns (ListSubscriptionsResponse) { - option (google.api.http) = { - get: "/v1/{project=projects/*}/subscriptions" - }; - } - - // Deletes an existing subscription. All messages retained in the subscription - // are immediately dropped. Calls to `Pull` after deletion will return - // `NOT_FOUND`. After a subscription is deleted, a new one may be created with - // the same name, but the new one has no association with the old - // subscription or its topic unless the same topic is specified. - rpc DeleteSubscription(DeleteSubscriptionRequest) - returns (google.protobuf.Empty) { - option (google.api.http) = { - delete: "/v1/{subscription=projects/*/subscriptions/*}" - }; - } - - // Modifies the ack deadline for a specific message. This method is useful - // to indicate that more time is needed to process a message by the - // subscriber, or to make the message available for redelivery if the - // processing was interrupted. Note that this does not modify the - // subscription-level `ackDeadlineSeconds` used for subsequent messages. - rpc ModifyAckDeadline(ModifyAckDeadlineRequest) - returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/{subscription=projects/*/subscriptions/*}:modifyAckDeadline" - body: "*" - }; - } - - // Acknowledges the messages associated with the `ack_ids` in the - // `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages - // from the subscription. - // - // Acknowledging a message whose ack deadline has expired may succeed, - // but such a message may be redelivered later. Acknowledging a message more - // than once will not result in an error. - rpc Acknowledge(AcknowledgeRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/{subscription=projects/*/subscriptions/*}:acknowledge" - body: "*" - }; - } - - // Pulls messages from the server. The server may return `UNAVAILABLE` if - // there are too many concurrent pull requests pending for the given - // subscription. - rpc Pull(PullRequest) returns (PullResponse) { - option (google.api.http) = { - post: "/v1/{subscription=projects/*/subscriptions/*}:pull" - body: "*" - }; - } - - // Establishes a stream with the server, which sends messages down to the - // client. The client streams acknowledgements and ack deadline modifications - // back to the server. The server will close the stream and return the status - // on any error. The server may close the stream with status `UNAVAILABLE` to - // reassign server-side resources, in which case, the client should - // re-establish the stream. Flow control can be achieved by configuring the - // underlying RPC channel. - rpc StreamingPull(stream StreamingPullRequest) - returns (stream StreamingPullResponse) {} - - // Modifies the `PushConfig` for a specified subscription. - // - // This may be used to change a push subscription to a pull one (signified by - // an empty `PushConfig`) or vice versa, or change the endpoint URL and other - // attributes of a push subscription. Messages will accumulate for delivery - // continuously through the call regardless of changes to the `PushConfig`. - rpc ModifyPushConfig(ModifyPushConfigRequest) - returns (google.protobuf.Empty) { - option (google.api.http) = { - post: "/v1/{subscription=projects/*/subscriptions/*}:modifyPushConfig" - body: "*" - }; - } - - // Gets the configuration details of a snapshot. Snapshots are used in - // Seek - // operations, which allow you to manage message acknowledgments in bulk. That - // is, you can set the acknowledgment state of messages in an existing - // subscription to the state captured by a snapshot. - rpc GetSnapshot(GetSnapshotRequest) returns (Snapshot) { - option (google.api.http) = { - get: "/v1/{snapshot=projects/*/snapshots/*}" - }; - } - - // Lists the existing snapshots. Snapshots are used in - // Seek - // operations, which allow - // you to manage message acknowledgments in bulk. That is, you can set the - // acknowledgment state of messages in an existing subscription to the state - // captured by a snapshot. - rpc ListSnapshots(ListSnapshotsRequest) returns (ListSnapshotsResponse) { - option (google.api.http) = { - get: "/v1/{project=projects/*}/snapshots" - }; - } - - // Creates a snapshot from the requested subscription. Snapshots are used in - // Seek - // operations, which allow - // you to manage message acknowledgments in bulk. That is, you can set the - // acknowledgment state of messages in an existing subscription to the state - // captured by a snapshot. - //

If the snapshot already exists, returns `ALREADY_EXISTS`. - // If the requested subscription doesn't exist, returns `NOT_FOUND`. - // If the backlog in the subscription is too old -- and the resulting snapshot - // would expire in less than 1 hour -- then `FAILED_PRECONDITION` is returned. - // See also the `Snapshot.expire_time` field. If the name is not provided in - // the request, the server will assign a random - // name for this snapshot on the same project as the subscription, conforming - // to the - // [resource name - // format](https://cloud.google.com/pubsub/docs/admin#resource_names). The - // generated name is populated in the returned Snapshot object. Note that for - // REST API requests, you must specify a name in the request. - rpc CreateSnapshot(CreateSnapshotRequest) returns (Snapshot) { - option (google.api.http) = { - put: "/v1/{name=projects/*/snapshots/*}" - body: "*" - }; - } - - // Updates an existing snapshot. Snapshots are used in - // Seek - // operations, which allow - // you to manage message acknowledgments in bulk. That is, you can set the - // acknowledgment state of messages in an existing subscription to the state - // captured by a snapshot. - rpc UpdateSnapshot(UpdateSnapshotRequest) returns (Snapshot) { - option (google.api.http) = { - patch: "/v1/{snapshot.name=projects/*/snapshots/*}" - body: "*" - }; - } - - // Removes an existing snapshot. Snapshots are used in - // Seek - // operations, which allow - // you to manage message acknowledgments in bulk. That is, you can set the - // acknowledgment state of messages in an existing subscription to the state - // captured by a snapshot.

- // When the snapshot is deleted, all messages retained in the snapshot - // are immediately dropped. After a snapshot is deleted, a new one may be - // created with the same name, but the new one has no association with the old - // snapshot or its subscription, unless the same subscription is specified. - rpc DeleteSnapshot(DeleteSnapshotRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - delete: "/v1/{snapshot=projects/*/snapshots/*}" - }; - } - - // Seeks an existing subscription to a point in time or to a given snapshot, - // whichever is provided in the request. Snapshots are used in - // Seek - // operations, which allow - // you to manage message acknowledgments in bulk. That is, you can set the - // acknowledgment state of messages in an existing subscription to the state - // captured by a snapshot. Note that both the subscription and the snapshot - // must be on the same topic. - rpc Seek(SeekRequest) returns (SeekResponse) { - option (google.api.http) = { - post: "/v1/{subscription=projects/*/subscriptions/*}:seek" - body: "*" - }; - } -} - -// A subscription resource. -message Subscription { - // The name of the subscription. It must have the format - // `"projects/{project}/subscriptions/{subscription}"`. `{subscription}` must - // start with a letter, and contain only letters (`[A-Za-z]`), numbers - // (`[0-9]`), dashes (`-`), underscores (`_`), periods (`.`), tildes (`~`), - // plus (`+`) or percent signs (`%`). It must be between 3 and 255 characters - // in length, and it must not start with `"goog"`. - string name = 1; - - // The name of the topic from which this subscription is receiving messages. - // Format is `projects/{project}/topics/{topic}`. - // The value of this field will be `_deleted-topic_` if the topic has been - // deleted. - string topic = 2; - - // If push delivery is used with this subscription, this field is - // used to configure it. An empty `pushConfig` signifies that the subscriber - // will pull and ack messages using API methods. - PushConfig push_config = 4; - - // The approximate amount of time (on a best-effort basis) Pub/Sub waits for - // the subscriber to acknowledge receipt before resending the message. In the - // interval after the message is delivered and before it is acknowledged, it - // is considered to be outstanding. During that time period, the - // message will not be redelivered (on a best-effort basis). - // - // For pull subscriptions, this value is used as the initial value for the ack - // deadline. To override this value for a given message, call - // `ModifyAckDeadline` with the corresponding `ack_id` if using - // non-streaming pull or send the `ack_id` in a - // `StreamingModifyAckDeadlineRequest` if using streaming pull. - // The minimum custom deadline you can specify is 10 seconds. - // The maximum custom deadline you can specify is 600 seconds (10 minutes). - // If this parameter is 0, a default value of 10 seconds is used. - // - // For push delivery, this value is also used to set the request timeout for - // the call to the push endpoint. - // - // If the subscriber never acknowledges the message, the Pub/Sub - // system will eventually redeliver the message. - int32 ack_deadline_seconds = 5; - - // Indicates whether to retain acknowledged messages. If true, then - // messages are not expunged from the subscription's backlog, even if they are - // acknowledged, until they fall out of the `message_retention_duration` - // window. This must be true if you would like to - // - // Seek to a timestamp. - bool retain_acked_messages = 7; - - // How long to retain unacknowledged messages in the subscription's backlog, - // from the moment a message is published. - // If `retain_acked_messages` is true, then this also configures the retention - // of acknowledged messages, and thus configures how far back in time a `Seek` - // can be done. Defaults to 7 days. Cannot be more than 7 days or less than 10 - // minutes. - google.protobuf.Duration message_retention_duration = 8; - - // See Creating and - // managing labels. - map labels = 9; - - // If true, messages published with the same `ordering_key` in `PubsubMessage` - // will be delivered to the subscribers in the order in which they - // are received by the Pub/Sub system. Otherwise, they may be delivered in - // any order. - // EXPERIMENTAL: This feature is part of a closed alpha release. This - // API might be changed in backward-incompatible ways and is not recommended - // for production use. It is not subject to any SLA or deprecation policy. - bool enable_message_ordering = 10; - - // A policy that specifies the conditions for this subscription's expiration. - // A subscription is considered active as long as any connected subscriber is - // successfully consuming messages from the subscription or is issuing - // operations on the subscription. If `expiration_policy` is not set, a - // *default policy* with `ttl` of 31 days will be used. The minimum allowed - // value for `expiration_policy.ttl` is 1 day. - ExpirationPolicy expiration_policy = 11; - - // A policy that specifies the conditions for dead lettering messages in - // this subscription. If dead_letter_policy is not set, dead lettering - // is disabled. - // - // The Cloud Pub/Sub service account associated with this subscriptions's - // parent project (i.e., - // service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com) must have - // permission to Acknowledge() messages on this subscription. - // EXPERIMENTAL: This feature is part of a closed alpha release. This - // API might be changed in backward-incompatible ways and is not recommended - // for production use. It is not subject to any SLA or deprecation policy. - DeadLetterPolicy dead_letter_policy = 13; -} - -// Dead lettering is done on a best effort basis. The same message might be -// dead lettered multiple times. -// -// If validation on any of the fields fails at subscription creation/updation, -// the create/update subscription request will fail. -message DeadLetterPolicy { - // The name of the topic to which dead letter messages should be published. - // Format is `projects/{project}/topics/{topic}`.The Cloud Pub/Sub service - // account associated with the enclosing subscription's parent project (i.e., - // service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com) must have - // permission to Publish() to this topic. - // - // The operation will fail if the topic does not exist. - // Users should ensure that there is a subscription attached to this topic - // since messages published to a topic with no subscriptions are lost. - string dead_letter_topic = 1; - - // The maximum number of delivery attempts for any message. The value must be - // between 5 and 100. - // - // The number of delivery attempts is defined as 1 + (the sum of number of - // NACKs and number of times the acknowledgement deadline has been exceeded - // for the message). - // - // A NACK is any call to ModifyAckDeadline with a 0 deadline. Note that - // client libraries may automatically extend ack_deadlines. - // - // This field will be honored on a best effort basis. - // - // If this parameter is 0, a default value of 5 is used. - int32 max_delivery_attempts = 2; -} - -// A policy that specifies the conditions for resource expiration (i.e., -// automatic resource deletion). -message ExpirationPolicy { - // Specifies the "time-to-live" duration for an associated resource. The - // resource expires if it is not active for a period of `ttl`. The definition - // of "activity" depends on the type of the associated resource. The minimum - // and maximum allowed values for `ttl` depend on the type of the associated - // resource, as well. If `ttl` is not set, the associated resource never - // expires. - google.protobuf.Duration ttl = 1; -} - -// Configuration for a push delivery endpoint. -message PushConfig { - // Contains information needed for generating an - // [OpenID Connect - // token](https://developers.google.com/identity/protocols/OpenIDConnect). - message OidcToken { - // [Service account - // email](https://cloud.google.com/iam/docs/service-accounts) - // to be used for generating the OIDC token. The caller (for - // CreateSubscription, UpdateSubscription, and ModifyPushConfig RPCs) must - // have the iam.serviceAccounts.actAs permission for the service account. - string service_account_email = 1; - - // Audience to be used when generating OIDC token. The audience claim - // identifies the recipients that the JWT is intended for. The audience - // value is a single case-sensitive string. Having multiple values (array) - // for the audience field is not supported. More info about the OIDC JWT - // token audience here: https://tools.ietf.org/html/rfc7519#section-4.1.3 - // Note: if not specified, the Push endpoint URL will be used. - string audience = 2; - } - - // A URL locating the endpoint to which messages should be pushed. - // For example, a Webhook endpoint might use "https://example.com/push". - string push_endpoint = 1; - - // Endpoint configuration attributes that can be used to control different - // aspects of the message delivery. - // - // The only currently supported attribute is `x-goog-version`, which you can - // use to change the format of the pushed message. This attribute - // indicates the version of the data expected by the endpoint. This - // controls the shape of the pushed message (i.e., its fields and metadata). - // - // If not present during the `CreateSubscription` call, it will default to - // the version of the Pub/Sub API used to make such call. If not present in a - // `ModifyPushConfig` call, its value will not be changed. `GetSubscription` - // calls will always return a valid version, even if the subscription was - // created without this attribute. - // - // The only supported values for the `x-goog-version` attribute are: - // - // * `v1beta1`: uses the push format defined in the v1beta1 Pub/Sub API. - // * `v1` or `v1beta2`: uses the push format defined in the v1 Pub/Sub API. - // - // For example: - //
attributes { "x-goog-version": "v1" } 
- map attributes = 2; - - // An authentication method used by push endpoints to verify the source of - // push requests. This can be used with push endpoints that are private by - // default to allow requests only from the Cloud Pub/Sub system, for example. - // This field is optional and should be set only by users interested in - // authenticated push. - oneof authentication_method { - // If specified, Pub/Sub will generate and attach an OIDC JWT token as an - // `Authorization` header in the HTTP request for every pushed message. - OidcToken oidc_token = 3; - } -} - -// A message and its corresponding acknowledgment ID. -message ReceivedMessage { - // This ID can be used to acknowledge the received message. - string ack_id = 1; - - // The message. - PubsubMessage message = 2; - - // Delivery attempt counter is 1 + (the sum of number of NACKs and number of - // ack_deadline exceeds) for this message. - // - // A NACK is any call to ModifyAckDeadline with a 0 deadline. An ack_deadline - // exceeds event is whenever a message is not acknowledged within - // ack_deadline. Note that ack_deadline is initially - // Subscription.ackDeadlineSeconds, but may get extended automatically by - // the client library. - // - // The first delivery of a given message will have this value as 1. The value - // is calculated at best effort and is approximate. - // - // If a DeadLetterPolicy is not set on the subscription, this will be 0. - // EXPERIMENTAL: This feature is part of a closed alpha release. This - // API might be changed in backward-incompatible ways and is not recommended - // for production use. It is not subject to any SLA or deprecation policy. - int32 delivery_attempt = 3; -} - -// Request for the GetSubscription method. -message GetSubscriptionRequest { - // The name of the subscription to get. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 1; -} - -// Request for the UpdateSubscription method. -message UpdateSubscriptionRequest { - // The updated subscription object. - Subscription subscription = 1; - - // Indicates which fields in the provided subscription to update. - // Must be specified and non-empty. - google.protobuf.FieldMask update_mask = 2; -} - -// Request for the `ListSubscriptions` method. -message ListSubscriptionsRequest { - // The name of the project in which to list subscriptions. - // Format is `projects/{project-id}`. - string project = 1; - - // Maximum number of subscriptions to return. - int32 page_size = 2; - - // The value returned by the last `ListSubscriptionsResponse`; indicates that - // this is a continuation of a prior `ListSubscriptions` call, and that the - // system should return the next page of data. - string page_token = 3; -} - -// Response for the `ListSubscriptions` method. -message ListSubscriptionsResponse { - // The subscriptions that match the request. - repeated Subscription subscriptions = 1; - - // If not empty, indicates that there may be more subscriptions that match - // the request; this value should be passed in a new - // `ListSubscriptionsRequest` to get more subscriptions. - string next_page_token = 2; -} - -// Request for the DeleteSubscription method. -message DeleteSubscriptionRequest { - // The subscription to delete. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 1; -} - -// Request for the ModifyPushConfig method. -message ModifyPushConfigRequest { - // The name of the subscription. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 1; - - // The push configuration for future deliveries. - // - // An empty `pushConfig` indicates that the Pub/Sub system should - // stop pushing messages from the given subscription and allow - // messages to be pulled and acknowledged - effectively pausing - // the subscription if `Pull` or `StreamingPull` is not called. - PushConfig push_config = 2; -} - -// Request for the `Pull` method. -message PullRequest { - // The subscription from which messages should be pulled. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 1; - - // If this field set to true, the system will respond immediately even if - // it there are no messages available to return in the `Pull` response. - // Otherwise, the system may wait (for a bounded amount of time) until at - // least one message is available, rather than returning no messages. - bool return_immediately = 2; - - // The maximum number of messages to return for this request. Must be a - // positive integer. The Pub/Sub system may return fewer than the number - // specified. - int32 max_messages = 3; -} - -// Response for the `Pull` method. -message PullResponse { - // Received Pub/Sub messages. The list will be empty if there are no more - // messages available in the backlog. For JSON, the response can be entirely - // empty. The Pub/Sub system may return fewer than the `maxMessages` requested - // even if there are more messages available in the backlog. - repeated ReceivedMessage received_messages = 1; -} - -// Request for the ModifyAckDeadline method. -message ModifyAckDeadlineRequest { - // The name of the subscription. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 1; - - // List of acknowledgment IDs. - repeated string ack_ids = 4; - - // The new ack deadline with respect to the time this request was sent to - // the Pub/Sub system. For example, if the value is 10, the new - // ack deadline will expire 10 seconds after the `ModifyAckDeadline` call - // was made. Specifying zero might immediately make the message available for - // delivery to another subscriber client. This typically results in an - // increase in the rate of message redeliveries (that is, duplicates). - // The minimum deadline you can specify is 0 seconds. - // The maximum deadline you can specify is 600 seconds (10 minutes). - int32 ack_deadline_seconds = 3; -} - -// Request for the Acknowledge method. -message AcknowledgeRequest { - // The subscription whose message is being acknowledged. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 1; - - // The acknowledgment ID for the messages being acknowledged that was returned - // by the Pub/Sub system in the `Pull` response. Must not be empty. - repeated string ack_ids = 2; -} - -// Request for the `StreamingPull` streaming RPC method. This request is used to -// establish the initial stream as well as to stream acknowledgements and ack -// deadline modifications from the client to the server. -message StreamingPullRequest { - // The subscription for which to initialize the new stream. This must be - // provided in the first request on the stream, and must not be set in - // subsequent requests from client to server. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 1; - - // List of acknowledgement IDs for acknowledging previously received messages - // (received on this stream or a different stream). If an ack ID has expired, - // the corresponding message may be redelivered later. Acknowledging a message - // more than once will not result in an error. If the acknowledgement ID is - // malformed, the stream will be aborted with status `INVALID_ARGUMENT`. - repeated string ack_ids = 2; - - // The list of new ack deadlines for the IDs listed in - // `modify_deadline_ack_ids`. The size of this list must be the same as the - // size of `modify_deadline_ack_ids`. If it differs the stream will be aborted - // with `INVALID_ARGUMENT`. Each element in this list is applied to the - // element in the same position in `modify_deadline_ack_ids`. The new ack - // deadline is with respect to the time this request was sent to the Pub/Sub - // system. Must be >= 0. For example, if the value is 10, the new ack deadline - // will expire 10 seconds after this request is received. If the value is 0, - // the message is immediately made available for another streaming or - // non-streaming pull request. If the value is < 0 (an error), the stream will - // be aborted with status `INVALID_ARGUMENT`. - repeated int32 modify_deadline_seconds = 3; - - // List of acknowledgement IDs whose deadline will be modified based on the - // corresponding element in `modify_deadline_seconds`. This field can be used - // to indicate that more time is needed to process a message by the - // subscriber, or to make the message available for redelivery if the - // processing was interrupted. - repeated string modify_deadline_ack_ids = 4; - - // The ack deadline to use for the stream. This must be provided in the - // first request on the stream, but it can also be updated on subsequent - // requests from client to server. The minimum deadline you can specify is 10 - // seconds. The maximum deadline you can specify is 600 seconds (10 minutes). - int32 stream_ack_deadline_seconds = 5; -} - -// Response for the `StreamingPull` method. This response is used to stream -// messages from the server to the client. -message StreamingPullResponse { - // Received Pub/Sub messages. This will not be empty. - repeated ReceivedMessage received_messages = 1; -} - -// Request for the `CreateSnapshot` method. -message CreateSnapshotRequest { - // Optional user-provided name for this snapshot. - // If the name is not provided in the request, the server will assign a random - // name for this snapshot on the same project as the subscription. - // Note that for REST API requests, you must specify a name. See the - // - // resource name rules. - // Format is `projects/{project}/snapshots/{snap}`. - string name = 1; - - // The subscription whose backlog the snapshot retains. - // Specifically, the created snapshot is guaranteed to retain: - // (a) The existing backlog on the subscription. More precisely, this is - // defined as the messages in the subscription's backlog that are - // unacknowledged upon the successful completion of the - // `CreateSnapshot` request; as well as: - // (b) Any messages published to the subscription's topic following the - // successful completion of the CreateSnapshot request. - // Format is `projects/{project}/subscriptions/{sub}`. - string subscription = 2; - - // See Creating and - // managing labels. - map labels = 3; -} - -// Request for the UpdateSnapshot method. -message UpdateSnapshotRequest { - // The updated snapshot object. - Snapshot snapshot = 1; - - // Indicates which fields in the provided snapshot to update. - // Must be specified and non-empty. - google.protobuf.FieldMask update_mask = 2; -} - -// A snapshot resource. Snapshots are used in -// Seek -// operations, which allow -// you to manage message acknowledgments in bulk. That is, you can set the -// acknowledgment state of messages in an existing subscription to the state -// captured by a snapshot. -message Snapshot { - // The name of the snapshot. - string name = 1; - - // The name of the topic from which this snapshot is retaining messages. - string topic = 2; - - // The snapshot is guaranteed to exist up until this time. - // A newly-created snapshot expires no later than 7 days from the time of its - // creation. Its exact lifetime is determined at creation by the existing - // backlog in the source subscription. Specifically, the lifetime of the - // snapshot is `7 days - (age of oldest unacked message in the subscription)`. - // For example, consider a subscription whose oldest unacked message is 3 days - // old. If a snapshot is created from this subscription, the snapshot -- which - // will always capture this 3-day-old backlog as long as the snapshot - // exists -- will expire in 4 days. The service will refuse to create a - // snapshot that would expire in less than 1 hour after creation. - google.protobuf.Timestamp expire_time = 3; - - // See Creating and - // managing labels. - map labels = 4; -} - -// Request for the GetSnapshot method. -message GetSnapshotRequest { - // The name of the snapshot to get. - // Format is `projects/{project}/snapshots/{snap}`. - string snapshot = 1; -} - -// Request for the `ListSnapshots` method. -message ListSnapshotsRequest { - // The name of the project in which to list snapshots. - // Format is `projects/{project-id}`. - string project = 1; - - // Maximum number of snapshots to return. - int32 page_size = 2; - - // The value returned by the last `ListSnapshotsResponse`; indicates that this - // is a continuation of a prior `ListSnapshots` call, and that the system - // should return the next page of data. - string page_token = 3; -} - -// Response for the `ListSnapshots` method. -message ListSnapshotsResponse { - // The resulting snapshots. - repeated Snapshot snapshots = 1; - - // If not empty, indicates that there may be more snapshot that match the - // request; this value should be passed in a new `ListSnapshotsRequest`. - string next_page_token = 2; -} - -// Request for the `DeleteSnapshot` method. -message DeleteSnapshotRequest { - // The name of the snapshot to delete. - // Format is `projects/{project}/snapshots/{snap}`. - string snapshot = 1; -} - -// Request for the `Seek` method. -message SeekRequest { - // The subscription to affect. - string subscription = 1; - - oneof target { - // The time to seek to. - // Messages retained in the subscription that were published before this - // time are marked as acknowledged, and messages retained in the - // subscription that were published after this time are marked as - // unacknowledged. Note that this operation affects only those messages - // retained in the subscription (configured by the combination of - // `message_retention_duration` and `retain_acked_messages`). For example, - // if `time` corresponds to a point before the message retention - // window (or to a point before the system's notion of the subscription - // creation time), only retained messages will be marked as unacknowledged, - // and already-expunged messages will not be restored. - google.protobuf.Timestamp time = 2; - - // The snapshot to seek to. The snapshot's topic must be the same as that of - // the provided subscription. - // Format is `projects/{project}/snapshots/{snap}`. - string snapshot = 3; - } -} - -// Response for the `Seek` method (this response is empty). -message SeekResponse {} diff --git a/pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2.py b/pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2.py deleted file mode 100644 index dd4427f7e9a1..000000000000 --- a/pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2.py +++ /dev/null @@ -1,4694 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/pubsub_v1/proto/pubsub.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 -from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 -from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/pubsub_v1/proto/pubsub.proto", - package="google.pubsub.v1", - syntax="proto3", - serialized_options=_b( - "\n\024com.google.pubsub.v1B\013PubsubProtoP\001Z6google.golang.org/genproto/googleapis/pubsub/v1;pubsub\370\001\001\252\002\026Google.Cloud.PubSub.V1\312\002\026Google\\Cloud\\PubSub\\V1\352\002\031Google::Cloud::PubSub::V1" - ), - serialized_pb=_b( - '\n)google/cloud/pubsub_v1/proto/pubsub.proto\x12\x10google.pubsub.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto";\n\x14MessageStoragePolicy\x12#\n\x1b\x61llowed_persistence_regions\x18\x01 \x03(\t"\xd7\x01\n\x05Topic\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x33\n\x06labels\x18\x02 \x03(\x0b\x32#.google.pubsub.v1.Topic.LabelsEntry\x12\x46\n\x16message_storage_policy\x18\x03 \x01(\x0b\x32&.google.pubsub.v1.MessageStoragePolicy\x12\x14\n\x0ckms_key_name\x18\x05 \x01(\t\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\xf1\x01\n\rPubsubMessage\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x12\x43\n\nattributes\x18\x02 \x03(\x0b\x32/.google.pubsub.v1.PubsubMessage.AttributesEntry\x12\x12\n\nmessage_id\x18\x03 \x01(\t\x12\x30\n\x0cpublish_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0cordering_key\x18\x05 \x01(\t\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01" \n\x0fGetTopicRequest\x12\r\n\x05topic\x18\x01 \x01(\t"m\n\x12UpdateTopicRequest\x12&\n\x05topic\x18\x01 \x01(\x0b\x32\x17.google.pubsub.v1.Topic\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"R\n\x0ePublishRequest\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x31\n\x08messages\x18\x02 \x03(\x0b\x32\x1f.google.pubsub.v1.PubsubMessage"&\n\x0fPublishResponse\x12\x13\n\x0bmessage_ids\x18\x01 \x03(\t"K\n\x11ListTopicsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"V\n\x12ListTopicsResponse\x12\'\n\x06topics\x18\x01 \x03(\x0b\x32\x17.google.pubsub.v1.Topic\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"U\n\x1dListTopicSubscriptionsRequest\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"P\n\x1eListTopicSubscriptionsResponse\x12\x15\n\rsubscriptions\x18\x01 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"Q\n\x19ListTopicSnapshotsRequest\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"H\n\x1aListTopicSnapshotsResponse\x12\x11\n\tsnapshots\x18\x01 \x03(\t\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"#\n\x12\x44\x65leteTopicRequest\x12\r\n\x05topic\x18\x01 \x01(\t"\xe5\x03\n\x0cSubscription\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x31\n\x0bpush_config\x18\x04 \x01(\x0b\x32\x1c.google.pubsub.v1.PushConfig\x12\x1c\n\x14\x61\x63k_deadline_seconds\x18\x05 \x01(\x05\x12\x1d\n\x15retain_acked_messages\x18\x07 \x01(\x08\x12=\n\x1amessage_retention_duration\x18\x08 \x01(\x0b\x32\x19.google.protobuf.Duration\x12:\n\x06labels\x18\t \x03(\x0b\x32*.google.pubsub.v1.Subscription.LabelsEntry\x12\x1f\n\x17\x65nable_message_ordering\x18\n \x01(\x08\x12=\n\x11\x65xpiration_policy\x18\x0b \x01(\x0b\x32".google.pubsub.v1.ExpirationPolicy\x12>\n\x12\x64\x65\x61\x64_letter_policy\x18\r \x01(\x0b\x32".google.pubsub.v1.DeadLetterPolicy\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"L\n\x10\x44\x65\x61\x64LetterPolicy\x12\x19\n\x11\x64\x65\x61\x64_letter_topic\x18\x01 \x01(\t\x12\x1d\n\x15max_delivery_attempts\x18\x02 \x01(\x05":\n\x10\x45xpirationPolicy\x12&\n\x03ttl\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration"\xad\x02\n\nPushConfig\x12\x15\n\rpush_endpoint\x18\x01 \x01(\t\x12@\n\nattributes\x18\x02 \x03(\x0b\x32,.google.pubsub.v1.PushConfig.AttributesEntry\x12<\n\noidc_token\x18\x03 \x01(\x0b\x32&.google.pubsub.v1.PushConfig.OidcTokenH\x00\x1a<\n\tOidcToken\x12\x1d\n\x15service_account_email\x18\x01 \x01(\t\x12\x10\n\x08\x61udience\x18\x02 \x01(\t\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x15\x61uthentication_method"m\n\x0fReceivedMessage\x12\x0e\n\x06\x61\x63k_id\x18\x01 \x01(\t\x12\x30\n\x07message\x18\x02 \x01(\x0b\x32\x1f.google.pubsub.v1.PubsubMessage\x12\x18\n\x10\x64\x65livery_attempt\x18\x03 \x01(\x05".\n\x16GetSubscriptionRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t"\x82\x01\n\x19UpdateSubscriptionRequest\x12\x34\n\x0csubscription\x18\x01 \x01(\x0b\x32\x1e.google.pubsub.v1.Subscription\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"R\n\x18ListSubscriptionsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"k\n\x19ListSubscriptionsResponse\x12\x35\n\rsubscriptions\x18\x01 \x03(\x0b\x32\x1e.google.pubsub.v1.Subscription\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t"1\n\x19\x44\x65leteSubscriptionRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t"b\n\x17ModifyPushConfigRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t\x12\x31\n\x0bpush_config\x18\x02 \x01(\x0b\x32\x1c.google.pubsub.v1.PushConfig"U\n\x0bPullRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t\x12\x1a\n\x12return_immediately\x18\x02 \x01(\x08\x12\x14\n\x0cmax_messages\x18\x03 \x01(\x05"L\n\x0cPullResponse\x12<\n\x11received_messages\x18\x01 \x03(\x0b\x32!.google.pubsub.v1.ReceivedMessage"_\n\x18ModifyAckDeadlineRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t\x12\x0f\n\x07\x61\x63k_ids\x18\x04 \x03(\t\x12\x1c\n\x14\x61\x63k_deadline_seconds\x18\x03 \x01(\x05";\n\x12\x41\x63knowledgeRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t\x12\x0f\n\x07\x61\x63k_ids\x18\x02 \x03(\t"\xa4\x01\n\x14StreamingPullRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t\x12\x0f\n\x07\x61\x63k_ids\x18\x02 \x03(\t\x12\x1f\n\x17modify_deadline_seconds\x18\x03 \x03(\x05\x12\x1f\n\x17modify_deadline_ack_ids\x18\x04 \x03(\t\x12#\n\x1bstream_ack_deadline_seconds\x18\x05 \x01(\x05"U\n\x15StreamingPullResponse\x12<\n\x11received_messages\x18\x01 \x03(\x0b\x32!.google.pubsub.v1.ReceivedMessage"\xaf\x01\n\x15\x43reateSnapshotRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x14\n\x0csubscription\x18\x02 \x01(\t\x12\x43\n\x06labels\x18\x03 \x03(\x0b\x32\x33.google.pubsub.v1.CreateSnapshotRequest.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"v\n\x15UpdateSnapshotRequest\x12,\n\x08snapshot\x18\x01 \x01(\x0b\x32\x1a.google.pubsub.v1.Snapshot\x12/\n\x0bupdate_mask\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask"\xbf\x01\n\x08Snapshot\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12/\n\x0b\x65xpire_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x36\n\x06labels\x18\x04 \x03(\x0b\x32&.google.pubsub.v1.Snapshot.LabelsEntry\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"&\n\x12GetSnapshotRequest\x12\x10\n\x08snapshot\x18\x01 \x01(\t"N\n\x14ListSnapshotsRequest\x12\x0f\n\x07project\x18\x01 \x01(\t\x12\x11\n\tpage_size\x18\x02 \x01(\x05\x12\x12\n\npage_token\x18\x03 \x01(\t"_\n\x15ListSnapshotsResponse\x12-\n\tsnapshots\x18\x01 \x03(\x0b\x32\x1a.google.pubsub.v1.Snapshot\x12\x17\n\x0fnext_page_token\x18\x02 \x01(\t")\n\x15\x44\x65leteSnapshotRequest\x12\x10\n\x08snapshot\x18\x01 \x01(\t"m\n\x0bSeekRequest\x12\x14\n\x0csubscription\x18\x01 \x01(\t\x12*\n\x04time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x12\x12\n\x08snapshot\x18\x03 \x01(\tH\x00\x42\x08\n\x06target"\x0e\n\x0cSeekResponse2\xb1\t\n\tPublisher\x12j\n\x0b\x43reateTopic\x12\x17.google.pubsub.v1.Topic\x1a\x17.google.pubsub.v1.Topic")\x82\xd3\xe4\x93\x02#\x1a\x1e/v1/{name=projects/*/topics/*}:\x01*\x12}\n\x0bUpdateTopic\x12$.google.pubsub.v1.UpdateTopicRequest\x1a\x17.google.pubsub.v1.Topic"/\x82\xd3\xe4\x93\x02)2$/v1/{topic.name=projects/*/topics/*}:\x01*\x12\x82\x01\n\x07Publish\x12 .google.pubsub.v1.PublishRequest\x1a!.google.pubsub.v1.PublishResponse"2\x82\xd3\xe4\x93\x02,"\'/v1/{topic=projects/*/topics/*}:publish:\x01*\x12o\n\x08GetTopic\x12!.google.pubsub.v1.GetTopicRequest\x1a\x17.google.pubsub.v1.Topic"\'\x82\xd3\xe4\x93\x02!\x12\x1f/v1/{topic=projects/*/topics/*}\x12\x80\x01\n\nListTopics\x12#.google.pubsub.v1.ListTopicsRequest\x1a$.google.pubsub.v1.ListTopicsResponse"\'\x82\xd3\xe4\x93\x02!\x12\x1f/v1/{project=projects/*}/topics\x12\xb2\x01\n\x16ListTopicSubscriptions\x12/.google.pubsub.v1.ListTopicSubscriptionsRequest\x1a\x30.google.pubsub.v1.ListTopicSubscriptionsResponse"5\x82\xd3\xe4\x93\x02/\x12-/v1/{topic=projects/*/topics/*}/subscriptions\x12\xa2\x01\n\x12ListTopicSnapshots\x12+.google.pubsub.v1.ListTopicSnapshotsRequest\x1a,.google.pubsub.v1.ListTopicSnapshotsResponse"1\x82\xd3\xe4\x93\x02+\x12)/v1/{topic=projects/*/topics/*}/snapshots\x12t\n\x0b\x44\x65leteTopic\x12$.google.pubsub.v1.DeleteTopicRequest\x1a\x16.google.protobuf.Empty"\'\x82\xd3\xe4\x93\x02!*\x1f/v1/{topic=projects/*/topics/*}\x1ap\xca\x41\x15pubsub.googleapis.com\xd2\x41Uhttps://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/pubsub2\xeb\x12\n\nSubscriber\x12\x86\x01\n\x12\x43reateSubscription\x12\x1e.google.pubsub.v1.Subscription\x1a\x1e.google.pubsub.v1.Subscription"0\x82\xd3\xe4\x93\x02*\x1a%/v1/{name=projects/*/subscriptions/*}:\x01*\x12\x92\x01\n\x0fGetSubscription\x12(.google.pubsub.v1.GetSubscriptionRequest\x1a\x1e.google.pubsub.v1.Subscription"5\x82\xd3\xe4\x93\x02/\x12-/v1/{subscription=projects/*/subscriptions/*}\x12\xa0\x01\n\x12UpdateSubscription\x12+.google.pubsub.v1.UpdateSubscriptionRequest\x1a\x1e.google.pubsub.v1.Subscription"=\x82\xd3\xe4\x93\x02\x37\x32\x32/v1/{subscription.name=projects/*/subscriptions/*}:\x01*\x12\x9c\x01\n\x11ListSubscriptions\x12*.google.pubsub.v1.ListSubscriptionsRequest\x1a+.google.pubsub.v1.ListSubscriptionsResponse".\x82\xd3\xe4\x93\x02(\x12&/v1/{project=projects/*}/subscriptions\x12\x90\x01\n\x12\x44\x65leteSubscription\x12+.google.pubsub.v1.DeleteSubscriptionRequest\x1a\x16.google.protobuf.Empty"5\x82\xd3\xe4\x93\x02/*-/v1/{subscription=projects/*/subscriptions/*}\x12\xa3\x01\n\x11ModifyAckDeadline\x12*.google.pubsub.v1.ModifyAckDeadlineRequest\x1a\x16.google.protobuf.Empty"J\x82\xd3\xe4\x93\x02\x44"?/v1/{subscription=projects/*/subscriptions/*}:modifyAckDeadline:\x01*\x12\x91\x01\n\x0b\x41\x63knowledge\x12$.google.pubsub.v1.AcknowledgeRequest\x1a\x16.google.protobuf.Empty"D\x82\xd3\xe4\x93\x02>"9/v1/{subscription=projects/*/subscriptions/*}:acknowledge:\x01*\x12\x84\x01\n\x04Pull\x12\x1d.google.pubsub.v1.PullRequest\x1a\x1e.google.pubsub.v1.PullResponse"=\x82\xd3\xe4\x93\x02\x37"2/v1/{subscription=projects/*/subscriptions/*}:pull:\x01*\x12\x66\n\rStreamingPull\x12&.google.pubsub.v1.StreamingPullRequest\x1a\'.google.pubsub.v1.StreamingPullResponse"\x00(\x01\x30\x01\x12\xa0\x01\n\x10ModifyPushConfig\x12).google.pubsub.v1.ModifyPushConfigRequest\x1a\x16.google.protobuf.Empty"I\x82\xd3\xe4\x93\x02\x43">/v1/{subscription=projects/*/subscriptions/*}:modifyPushConfig:\x01*\x12~\n\x0bGetSnapshot\x12$.google.pubsub.v1.GetSnapshotRequest\x1a\x1a.google.pubsub.v1.Snapshot"-\x82\xd3\xe4\x93\x02\'\x12%/v1/{snapshot=projects/*/snapshots/*}\x12\x8c\x01\n\rListSnapshots\x12&.google.pubsub.v1.ListSnapshotsRequest\x1a\'.google.pubsub.v1.ListSnapshotsResponse"*\x82\xd3\xe4\x93\x02$\x12"/v1/{project=projects/*}/snapshots\x12\x83\x01\n\x0e\x43reateSnapshot\x12\'.google.pubsub.v1.CreateSnapshotRequest\x1a\x1a.google.pubsub.v1.Snapshot",\x82\xd3\xe4\x93\x02&\x1a!/v1/{name=projects/*/snapshots/*}:\x01*\x12\x8c\x01\n\x0eUpdateSnapshot\x12\'.google.pubsub.v1.UpdateSnapshotRequest\x1a\x1a.google.pubsub.v1.Snapshot"5\x82\xd3\xe4\x93\x02/2*/v1/{snapshot.name=projects/*/snapshots/*}:\x01*\x12\x80\x01\n\x0e\x44\x65leteSnapshot\x12\'.google.pubsub.v1.DeleteSnapshotRequest\x1a\x16.google.protobuf.Empty"-\x82\xd3\xe4\x93\x02\'*%/v1/{snapshot=projects/*/snapshots/*}\x12\x84\x01\n\x04Seek\x12\x1d.google.pubsub.v1.SeekRequest\x1a\x1e.google.pubsub.v1.SeekResponse"=\x82\xd3\xe4\x93\x02\x37"2/v1/{subscription=projects/*/subscriptions/*}:seek:\x01*\x1ap\xca\x41\x15pubsub.googleapis.com\xd2\x41Uhttps://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/pubsubB\xae\x01\n\x14\x63om.google.pubsub.v1B\x0bPubsubProtoP\x01Z6google.golang.org/genproto/googleapis/pubsub/v1;pubsub\xf8\x01\x01\xaa\x02\x16Google.Cloud.PubSub.V1\xca\x02\x16Google\\Cloud\\PubSub\\V1\xea\x02\x19Google::Cloud::PubSub::V1b\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_protobuf_dot_duration__pb2.DESCRIPTOR, - google_dot_protobuf_dot_empty__pb2.DESCRIPTOR, - google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR, - google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, - ], -) - - -_MESSAGESTORAGEPOLICY = _descriptor.Descriptor( - name="MessageStoragePolicy", - full_name="google.pubsub.v1.MessageStoragePolicy", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="allowed_persistence_regions", - full_name="google.pubsub.v1.MessageStoragePolicy.allowed_persistence_regions", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=246, - serialized_end=305, -) - - -_TOPIC_LABELSENTRY = _descriptor.Descriptor( - name="LabelsEntry", - full_name="google.pubsub.v1.Topic.LabelsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.pubsub.v1.Topic.LabelsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.pubsub.v1.Topic.LabelsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=478, - serialized_end=523, -) - -_TOPIC = _descriptor.Descriptor( - name="Topic", - full_name="google.pubsub.v1.Topic", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.pubsub.v1.Topic.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="labels", - full_name="google.pubsub.v1.Topic.labels", - index=1, - number=2, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="message_storage_policy", - full_name="google.pubsub.v1.Topic.message_storage_policy", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="kms_key_name", - full_name="google.pubsub.v1.Topic.kms_key_name", - index=3, - number=5, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_TOPIC_LABELSENTRY], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=308, - serialized_end=523, -) - - -_PUBSUBMESSAGE_ATTRIBUTESENTRY = _descriptor.Descriptor( - name="AttributesEntry", - full_name="google.pubsub.v1.PubsubMessage.AttributesEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.pubsub.v1.PubsubMessage.AttributesEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.pubsub.v1.PubsubMessage.AttributesEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=718, - serialized_end=767, -) - -_PUBSUBMESSAGE = _descriptor.Descriptor( - name="PubsubMessage", - full_name="google.pubsub.v1.PubsubMessage", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="data", - full_name="google.pubsub.v1.PubsubMessage.data", - index=0, - number=1, - type=12, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b(""), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="attributes", - full_name="google.pubsub.v1.PubsubMessage.attributes", - index=1, - number=2, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="message_id", - full_name="google.pubsub.v1.PubsubMessage.message_id", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="publish_time", - full_name="google.pubsub.v1.PubsubMessage.publish_time", - index=3, - number=4, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ordering_key", - full_name="google.pubsub.v1.PubsubMessage.ordering_key", - index=4, - number=5, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_PUBSUBMESSAGE_ATTRIBUTESENTRY], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=526, - serialized_end=767, -) - - -_GETTOPICREQUEST = _descriptor.Descriptor( - name="GetTopicRequest", - full_name="google.pubsub.v1.GetTopicRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.GetTopicRequest.topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=769, - serialized_end=801, -) - - -_UPDATETOPICREQUEST = _descriptor.Descriptor( - name="UpdateTopicRequest", - full_name="google.pubsub.v1.UpdateTopicRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.UpdateTopicRequest.topic", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="update_mask", - full_name="google.pubsub.v1.UpdateTopicRequest.update_mask", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=803, - serialized_end=912, -) - - -_PUBLISHREQUEST = _descriptor.Descriptor( - name="PublishRequest", - full_name="google.pubsub.v1.PublishRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.PublishRequest.topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="messages", - full_name="google.pubsub.v1.PublishRequest.messages", - index=1, - number=2, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=914, - serialized_end=996, -) - - -_PUBLISHRESPONSE = _descriptor.Descriptor( - name="PublishResponse", - full_name="google.pubsub.v1.PublishResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="message_ids", - full_name="google.pubsub.v1.PublishResponse.message_ids", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=998, - serialized_end=1036, -) - - -_LISTTOPICSREQUEST = _descriptor.Descriptor( - name="ListTopicsRequest", - full_name="google.pubsub.v1.ListTopicsRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="project", - full_name="google.pubsub.v1.ListTopicsRequest.project", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_size", - full_name="google.pubsub.v1.ListTopicsRequest.page_size", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_token", - full_name="google.pubsub.v1.ListTopicsRequest.page_token", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1038, - serialized_end=1113, -) - - -_LISTTOPICSRESPONSE = _descriptor.Descriptor( - name="ListTopicsResponse", - full_name="google.pubsub.v1.ListTopicsResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="topics", - full_name="google.pubsub.v1.ListTopicsResponse.topics", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="next_page_token", - full_name="google.pubsub.v1.ListTopicsResponse.next_page_token", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1115, - serialized_end=1201, -) - - -_LISTTOPICSUBSCRIPTIONSREQUEST = _descriptor.Descriptor( - name="ListTopicSubscriptionsRequest", - full_name="google.pubsub.v1.ListTopicSubscriptionsRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.ListTopicSubscriptionsRequest.topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_size", - full_name="google.pubsub.v1.ListTopicSubscriptionsRequest.page_size", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_token", - full_name="google.pubsub.v1.ListTopicSubscriptionsRequest.page_token", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1203, - serialized_end=1288, -) - - -_LISTTOPICSUBSCRIPTIONSRESPONSE = _descriptor.Descriptor( - name="ListTopicSubscriptionsResponse", - full_name="google.pubsub.v1.ListTopicSubscriptionsResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscriptions", - full_name="google.pubsub.v1.ListTopicSubscriptionsResponse.subscriptions", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="next_page_token", - full_name="google.pubsub.v1.ListTopicSubscriptionsResponse.next_page_token", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1290, - serialized_end=1370, -) - - -_LISTTOPICSNAPSHOTSREQUEST = _descriptor.Descriptor( - name="ListTopicSnapshotsRequest", - full_name="google.pubsub.v1.ListTopicSnapshotsRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.ListTopicSnapshotsRequest.topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_size", - full_name="google.pubsub.v1.ListTopicSnapshotsRequest.page_size", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_token", - full_name="google.pubsub.v1.ListTopicSnapshotsRequest.page_token", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1372, - serialized_end=1453, -) - - -_LISTTOPICSNAPSHOTSRESPONSE = _descriptor.Descriptor( - name="ListTopicSnapshotsResponse", - full_name="google.pubsub.v1.ListTopicSnapshotsResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="snapshots", - full_name="google.pubsub.v1.ListTopicSnapshotsResponse.snapshots", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="next_page_token", - full_name="google.pubsub.v1.ListTopicSnapshotsResponse.next_page_token", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1455, - serialized_end=1527, -) - - -_DELETETOPICREQUEST = _descriptor.Descriptor( - name="DeleteTopicRequest", - full_name="google.pubsub.v1.DeleteTopicRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.DeleteTopicRequest.topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1529, - serialized_end=1564, -) - - -_SUBSCRIPTION_LABELSENTRY = _descriptor.Descriptor( - name="LabelsEntry", - full_name="google.pubsub.v1.Subscription.LabelsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.pubsub.v1.Subscription.LabelsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.pubsub.v1.Subscription.LabelsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=478, - serialized_end=523, -) - -_SUBSCRIPTION = _descriptor.Descriptor( - name="Subscription", - full_name="google.pubsub.v1.Subscription", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.pubsub.v1.Subscription.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.Subscription.topic", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="push_config", - full_name="google.pubsub.v1.Subscription.push_config", - index=2, - number=4, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ack_deadline_seconds", - full_name="google.pubsub.v1.Subscription.ack_deadline_seconds", - index=3, - number=5, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="retain_acked_messages", - full_name="google.pubsub.v1.Subscription.retain_acked_messages", - index=4, - number=7, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="message_retention_duration", - full_name="google.pubsub.v1.Subscription.message_retention_duration", - index=5, - number=8, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="labels", - full_name="google.pubsub.v1.Subscription.labels", - index=6, - number=9, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="enable_message_ordering", - full_name="google.pubsub.v1.Subscription.enable_message_ordering", - index=7, - number=10, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="expiration_policy", - full_name="google.pubsub.v1.Subscription.expiration_policy", - index=8, - number=11, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="dead_letter_policy", - full_name="google.pubsub.v1.Subscription.dead_letter_policy", - index=9, - number=13, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_SUBSCRIPTION_LABELSENTRY], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1567, - serialized_end=2052, -) - - -_DEADLETTERPOLICY = _descriptor.Descriptor( - name="DeadLetterPolicy", - full_name="google.pubsub.v1.DeadLetterPolicy", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="dead_letter_topic", - full_name="google.pubsub.v1.DeadLetterPolicy.dead_letter_topic", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="max_delivery_attempts", - full_name="google.pubsub.v1.DeadLetterPolicy.max_delivery_attempts", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2054, - serialized_end=2130, -) - - -_EXPIRATIONPOLICY = _descriptor.Descriptor( - name="ExpirationPolicy", - full_name="google.pubsub.v1.ExpirationPolicy", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="ttl", - full_name="google.pubsub.v1.ExpirationPolicy.ttl", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2132, - serialized_end=2190, -) - - -_PUSHCONFIG_OIDCTOKEN = _descriptor.Descriptor( - name="OidcToken", - full_name="google.pubsub.v1.PushConfig.OidcToken", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="service_account_email", - full_name="google.pubsub.v1.PushConfig.OidcToken.service_account_email", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audience", - full_name="google.pubsub.v1.PushConfig.OidcToken.audience", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2358, - serialized_end=2418, -) - -_PUSHCONFIG_ATTRIBUTESENTRY = _descriptor.Descriptor( - name="AttributesEntry", - full_name="google.pubsub.v1.PushConfig.AttributesEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.pubsub.v1.PushConfig.AttributesEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.pubsub.v1.PushConfig.AttributesEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=718, - serialized_end=767, -) - -_PUSHCONFIG = _descriptor.Descriptor( - name="PushConfig", - full_name="google.pubsub.v1.PushConfig", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="push_endpoint", - full_name="google.pubsub.v1.PushConfig.push_endpoint", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="attributes", - full_name="google.pubsub.v1.PushConfig.attributes", - index=1, - number=2, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="oidc_token", - full_name="google.pubsub.v1.PushConfig.oidc_token", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_PUSHCONFIG_OIDCTOKEN, _PUSHCONFIG_ATTRIBUTESENTRY], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="authentication_method", - full_name="google.pubsub.v1.PushConfig.authentication_method", - index=0, - containing_type=None, - fields=[], - ) - ], - serialized_start=2193, - serialized_end=2494, -) - - -_RECEIVEDMESSAGE = _descriptor.Descriptor( - name="ReceivedMessage", - full_name="google.pubsub.v1.ReceivedMessage", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="ack_id", - full_name="google.pubsub.v1.ReceivedMessage.ack_id", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="message", - full_name="google.pubsub.v1.ReceivedMessage.message", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="delivery_attempt", - full_name="google.pubsub.v1.ReceivedMessage.delivery_attempt", - index=2, - number=3, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2496, - serialized_end=2605, -) - - -_GETSUBSCRIPTIONREQUEST = _descriptor.Descriptor( - name="GetSubscriptionRequest", - full_name="google.pubsub.v1.GetSubscriptionRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.GetSubscriptionRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2607, - serialized_end=2653, -) - - -_UPDATESUBSCRIPTIONREQUEST = _descriptor.Descriptor( - name="UpdateSubscriptionRequest", - full_name="google.pubsub.v1.UpdateSubscriptionRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.UpdateSubscriptionRequest.subscription", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="update_mask", - full_name="google.pubsub.v1.UpdateSubscriptionRequest.update_mask", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2656, - serialized_end=2786, -) - - -_LISTSUBSCRIPTIONSREQUEST = _descriptor.Descriptor( - name="ListSubscriptionsRequest", - full_name="google.pubsub.v1.ListSubscriptionsRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="project", - full_name="google.pubsub.v1.ListSubscriptionsRequest.project", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_size", - full_name="google.pubsub.v1.ListSubscriptionsRequest.page_size", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_token", - full_name="google.pubsub.v1.ListSubscriptionsRequest.page_token", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2788, - serialized_end=2870, -) - - -_LISTSUBSCRIPTIONSRESPONSE = _descriptor.Descriptor( - name="ListSubscriptionsResponse", - full_name="google.pubsub.v1.ListSubscriptionsResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscriptions", - full_name="google.pubsub.v1.ListSubscriptionsResponse.subscriptions", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="next_page_token", - full_name="google.pubsub.v1.ListSubscriptionsResponse.next_page_token", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2872, - serialized_end=2979, -) - - -_DELETESUBSCRIPTIONREQUEST = _descriptor.Descriptor( - name="DeleteSubscriptionRequest", - full_name="google.pubsub.v1.DeleteSubscriptionRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.DeleteSubscriptionRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2981, - serialized_end=3030, -) - - -_MODIFYPUSHCONFIGREQUEST = _descriptor.Descriptor( - name="ModifyPushConfigRequest", - full_name="google.pubsub.v1.ModifyPushConfigRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.ModifyPushConfigRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="push_config", - full_name="google.pubsub.v1.ModifyPushConfigRequest.push_config", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3032, - serialized_end=3130, -) - - -_PULLREQUEST = _descriptor.Descriptor( - name="PullRequest", - full_name="google.pubsub.v1.PullRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.PullRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="return_immediately", - full_name="google.pubsub.v1.PullRequest.return_immediately", - index=1, - number=2, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="max_messages", - full_name="google.pubsub.v1.PullRequest.max_messages", - index=2, - number=3, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3132, - serialized_end=3217, -) - - -_PULLRESPONSE = _descriptor.Descriptor( - name="PullResponse", - full_name="google.pubsub.v1.PullResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="received_messages", - full_name="google.pubsub.v1.PullResponse.received_messages", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3219, - serialized_end=3295, -) - - -_MODIFYACKDEADLINEREQUEST = _descriptor.Descriptor( - name="ModifyAckDeadlineRequest", - full_name="google.pubsub.v1.ModifyAckDeadlineRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.ModifyAckDeadlineRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ack_ids", - full_name="google.pubsub.v1.ModifyAckDeadlineRequest.ack_ids", - index=1, - number=4, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ack_deadline_seconds", - full_name="google.pubsub.v1.ModifyAckDeadlineRequest.ack_deadline_seconds", - index=2, - number=3, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3297, - serialized_end=3392, -) - - -_ACKNOWLEDGEREQUEST = _descriptor.Descriptor( - name="AcknowledgeRequest", - full_name="google.pubsub.v1.AcknowledgeRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.AcknowledgeRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ack_ids", - full_name="google.pubsub.v1.AcknowledgeRequest.ack_ids", - index=1, - number=2, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3394, - serialized_end=3453, -) - - -_STREAMINGPULLREQUEST = _descriptor.Descriptor( - name="StreamingPullRequest", - full_name="google.pubsub.v1.StreamingPullRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.StreamingPullRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="ack_ids", - full_name="google.pubsub.v1.StreamingPullRequest.ack_ids", - index=1, - number=2, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="modify_deadline_seconds", - full_name="google.pubsub.v1.StreamingPullRequest.modify_deadline_seconds", - index=2, - number=3, - type=5, - cpp_type=1, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="modify_deadline_ack_ids", - full_name="google.pubsub.v1.StreamingPullRequest.modify_deadline_ack_ids", - index=3, - number=4, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="stream_ack_deadline_seconds", - full_name="google.pubsub.v1.StreamingPullRequest.stream_ack_deadline_seconds", - index=4, - number=5, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3456, - serialized_end=3620, -) - - -_STREAMINGPULLRESPONSE = _descriptor.Descriptor( - name="StreamingPullResponse", - full_name="google.pubsub.v1.StreamingPullResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="received_messages", - full_name="google.pubsub.v1.StreamingPullResponse.received_messages", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3622, - serialized_end=3707, -) - - -_CREATESNAPSHOTREQUEST_LABELSENTRY = _descriptor.Descriptor( - name="LabelsEntry", - full_name="google.pubsub.v1.CreateSnapshotRequest.LabelsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.pubsub.v1.CreateSnapshotRequest.LabelsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.pubsub.v1.CreateSnapshotRequest.LabelsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=478, - serialized_end=523, -) - -_CREATESNAPSHOTREQUEST = _descriptor.Descriptor( - name="CreateSnapshotRequest", - full_name="google.pubsub.v1.CreateSnapshotRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.pubsub.v1.CreateSnapshotRequest.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.CreateSnapshotRequest.subscription", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="labels", - full_name="google.pubsub.v1.CreateSnapshotRequest.labels", - index=2, - number=3, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_CREATESNAPSHOTREQUEST_LABELSENTRY], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3710, - serialized_end=3885, -) - - -_UPDATESNAPSHOTREQUEST = _descriptor.Descriptor( - name="UpdateSnapshotRequest", - full_name="google.pubsub.v1.UpdateSnapshotRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="snapshot", - full_name="google.pubsub.v1.UpdateSnapshotRequest.snapshot", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="update_mask", - full_name="google.pubsub.v1.UpdateSnapshotRequest.update_mask", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3887, - serialized_end=4005, -) - - -_SNAPSHOT_LABELSENTRY = _descriptor.Descriptor( - name="LabelsEntry", - full_name="google.pubsub.v1.Snapshot.LabelsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.pubsub.v1.Snapshot.LabelsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.pubsub.v1.Snapshot.LabelsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=478, - serialized_end=523, -) - -_SNAPSHOT = _descriptor.Descriptor( - name="Snapshot", - full_name="google.pubsub.v1.Snapshot", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.pubsub.v1.Snapshot.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="topic", - full_name="google.pubsub.v1.Snapshot.topic", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="expire_time", - full_name="google.pubsub.v1.Snapshot.expire_time", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="labels", - full_name="google.pubsub.v1.Snapshot.labels", - index=3, - number=4, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_SNAPSHOT_LABELSENTRY], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4008, - serialized_end=4199, -) - - -_GETSNAPSHOTREQUEST = _descriptor.Descriptor( - name="GetSnapshotRequest", - full_name="google.pubsub.v1.GetSnapshotRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="snapshot", - full_name="google.pubsub.v1.GetSnapshotRequest.snapshot", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4201, - serialized_end=4239, -) - - -_LISTSNAPSHOTSREQUEST = _descriptor.Descriptor( - name="ListSnapshotsRequest", - full_name="google.pubsub.v1.ListSnapshotsRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="project", - full_name="google.pubsub.v1.ListSnapshotsRequest.project", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_size", - full_name="google.pubsub.v1.ListSnapshotsRequest.page_size", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="page_token", - full_name="google.pubsub.v1.ListSnapshotsRequest.page_token", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4241, - serialized_end=4319, -) - - -_LISTSNAPSHOTSRESPONSE = _descriptor.Descriptor( - name="ListSnapshotsResponse", - full_name="google.pubsub.v1.ListSnapshotsResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="snapshots", - full_name="google.pubsub.v1.ListSnapshotsResponse.snapshots", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="next_page_token", - full_name="google.pubsub.v1.ListSnapshotsResponse.next_page_token", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4321, - serialized_end=4416, -) - - -_DELETESNAPSHOTREQUEST = _descriptor.Descriptor( - name="DeleteSnapshotRequest", - full_name="google.pubsub.v1.DeleteSnapshotRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="snapshot", - full_name="google.pubsub.v1.DeleteSnapshotRequest.snapshot", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4418, - serialized_end=4459, -) - - -_SEEKREQUEST = _descriptor.Descriptor( - name="SeekRequest", - full_name="google.pubsub.v1.SeekRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="subscription", - full_name="google.pubsub.v1.SeekRequest.subscription", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="time", - full_name="google.pubsub.v1.SeekRequest.time", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="snapshot", - full_name="google.pubsub.v1.SeekRequest.snapshot", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="target", - full_name="google.pubsub.v1.SeekRequest.target", - index=0, - containing_type=None, - fields=[], - ) - ], - serialized_start=4461, - serialized_end=4570, -) - - -_SEEKRESPONSE = _descriptor.Descriptor( - name="SeekResponse", - full_name="google.pubsub.v1.SeekResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4572, - serialized_end=4586, -) - -_TOPIC_LABELSENTRY.containing_type = _TOPIC -_TOPIC.fields_by_name["labels"].message_type = _TOPIC_LABELSENTRY -_TOPIC.fields_by_name["message_storage_policy"].message_type = _MESSAGESTORAGEPOLICY -_PUBSUBMESSAGE_ATTRIBUTESENTRY.containing_type = _PUBSUBMESSAGE -_PUBSUBMESSAGE.fields_by_name[ - "attributes" -].message_type = _PUBSUBMESSAGE_ATTRIBUTESENTRY -_PUBSUBMESSAGE.fields_by_name[ - "publish_time" -].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP -_UPDATETOPICREQUEST.fields_by_name["topic"].message_type = _TOPIC -_UPDATETOPICREQUEST.fields_by_name[ - "update_mask" -].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK -_PUBLISHREQUEST.fields_by_name["messages"].message_type = _PUBSUBMESSAGE -_LISTTOPICSRESPONSE.fields_by_name["topics"].message_type = _TOPIC -_SUBSCRIPTION_LABELSENTRY.containing_type = _SUBSCRIPTION -_SUBSCRIPTION.fields_by_name["push_config"].message_type = _PUSHCONFIG -_SUBSCRIPTION.fields_by_name[ - "message_retention_duration" -].message_type = google_dot_protobuf_dot_duration__pb2._DURATION -_SUBSCRIPTION.fields_by_name["labels"].message_type = _SUBSCRIPTION_LABELSENTRY -_SUBSCRIPTION.fields_by_name["expiration_policy"].message_type = _EXPIRATIONPOLICY -_SUBSCRIPTION.fields_by_name["dead_letter_policy"].message_type = _DEADLETTERPOLICY -_EXPIRATIONPOLICY.fields_by_name[ - "ttl" -].message_type = google_dot_protobuf_dot_duration__pb2._DURATION -_PUSHCONFIG_OIDCTOKEN.containing_type = _PUSHCONFIG -_PUSHCONFIG_ATTRIBUTESENTRY.containing_type = _PUSHCONFIG -_PUSHCONFIG.fields_by_name["attributes"].message_type = _PUSHCONFIG_ATTRIBUTESENTRY -_PUSHCONFIG.fields_by_name["oidc_token"].message_type = _PUSHCONFIG_OIDCTOKEN -_PUSHCONFIG.oneofs_by_name["authentication_method"].fields.append( - _PUSHCONFIG.fields_by_name["oidc_token"] -) -_PUSHCONFIG.fields_by_name["oidc_token"].containing_oneof = _PUSHCONFIG.oneofs_by_name[ - "authentication_method" -] -_RECEIVEDMESSAGE.fields_by_name["message"].message_type = _PUBSUBMESSAGE -_UPDATESUBSCRIPTIONREQUEST.fields_by_name["subscription"].message_type = _SUBSCRIPTION -_UPDATESUBSCRIPTIONREQUEST.fields_by_name[ - "update_mask" -].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK -_LISTSUBSCRIPTIONSRESPONSE.fields_by_name["subscriptions"].message_type = _SUBSCRIPTION -_MODIFYPUSHCONFIGREQUEST.fields_by_name["push_config"].message_type = _PUSHCONFIG -_PULLRESPONSE.fields_by_name["received_messages"].message_type = _RECEIVEDMESSAGE -_STREAMINGPULLRESPONSE.fields_by_name[ - "received_messages" -].message_type = _RECEIVEDMESSAGE -_CREATESNAPSHOTREQUEST_LABELSENTRY.containing_type = _CREATESNAPSHOTREQUEST -_CREATESNAPSHOTREQUEST.fields_by_name[ - "labels" -].message_type = _CREATESNAPSHOTREQUEST_LABELSENTRY -_UPDATESNAPSHOTREQUEST.fields_by_name["snapshot"].message_type = _SNAPSHOT -_UPDATESNAPSHOTREQUEST.fields_by_name[ - "update_mask" -].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK -_SNAPSHOT_LABELSENTRY.containing_type = _SNAPSHOT -_SNAPSHOT.fields_by_name[ - "expire_time" -].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP -_SNAPSHOT.fields_by_name["labels"].message_type = _SNAPSHOT_LABELSENTRY -_LISTSNAPSHOTSRESPONSE.fields_by_name["snapshots"].message_type = _SNAPSHOT -_SEEKREQUEST.fields_by_name[ - "time" -].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP -_SEEKREQUEST.oneofs_by_name["target"].fields.append(_SEEKREQUEST.fields_by_name["time"]) -_SEEKREQUEST.fields_by_name["time"].containing_oneof = _SEEKREQUEST.oneofs_by_name[ - "target" -] -_SEEKREQUEST.oneofs_by_name["target"].fields.append( - _SEEKREQUEST.fields_by_name["snapshot"] -) -_SEEKREQUEST.fields_by_name["snapshot"].containing_oneof = _SEEKREQUEST.oneofs_by_name[ - "target" -] -DESCRIPTOR.message_types_by_name["MessageStoragePolicy"] = _MESSAGESTORAGEPOLICY -DESCRIPTOR.message_types_by_name["Topic"] = _TOPIC -DESCRIPTOR.message_types_by_name["PubsubMessage"] = _PUBSUBMESSAGE -DESCRIPTOR.message_types_by_name["GetTopicRequest"] = _GETTOPICREQUEST -DESCRIPTOR.message_types_by_name["UpdateTopicRequest"] = _UPDATETOPICREQUEST -DESCRIPTOR.message_types_by_name["PublishRequest"] = _PUBLISHREQUEST -DESCRIPTOR.message_types_by_name["PublishResponse"] = _PUBLISHRESPONSE -DESCRIPTOR.message_types_by_name["ListTopicsRequest"] = _LISTTOPICSREQUEST -DESCRIPTOR.message_types_by_name["ListTopicsResponse"] = _LISTTOPICSRESPONSE -DESCRIPTOR.message_types_by_name[ - "ListTopicSubscriptionsRequest" -] = _LISTTOPICSUBSCRIPTIONSREQUEST -DESCRIPTOR.message_types_by_name[ - "ListTopicSubscriptionsResponse" -] = _LISTTOPICSUBSCRIPTIONSRESPONSE -DESCRIPTOR.message_types_by_name[ - "ListTopicSnapshotsRequest" -] = _LISTTOPICSNAPSHOTSREQUEST -DESCRIPTOR.message_types_by_name[ - "ListTopicSnapshotsResponse" -] = _LISTTOPICSNAPSHOTSRESPONSE -DESCRIPTOR.message_types_by_name["DeleteTopicRequest"] = _DELETETOPICREQUEST -DESCRIPTOR.message_types_by_name["Subscription"] = _SUBSCRIPTION -DESCRIPTOR.message_types_by_name["DeadLetterPolicy"] = _DEADLETTERPOLICY -DESCRIPTOR.message_types_by_name["ExpirationPolicy"] = _EXPIRATIONPOLICY -DESCRIPTOR.message_types_by_name["PushConfig"] = _PUSHCONFIG -DESCRIPTOR.message_types_by_name["ReceivedMessage"] = _RECEIVEDMESSAGE -DESCRIPTOR.message_types_by_name["GetSubscriptionRequest"] = _GETSUBSCRIPTIONREQUEST -DESCRIPTOR.message_types_by_name[ - "UpdateSubscriptionRequest" -] = _UPDATESUBSCRIPTIONREQUEST -DESCRIPTOR.message_types_by_name["ListSubscriptionsRequest"] = _LISTSUBSCRIPTIONSREQUEST -DESCRIPTOR.message_types_by_name[ - "ListSubscriptionsResponse" -] = _LISTSUBSCRIPTIONSRESPONSE -DESCRIPTOR.message_types_by_name[ - "DeleteSubscriptionRequest" -] = _DELETESUBSCRIPTIONREQUEST -DESCRIPTOR.message_types_by_name["ModifyPushConfigRequest"] = _MODIFYPUSHCONFIGREQUEST -DESCRIPTOR.message_types_by_name["PullRequest"] = _PULLREQUEST -DESCRIPTOR.message_types_by_name["PullResponse"] = _PULLRESPONSE -DESCRIPTOR.message_types_by_name["ModifyAckDeadlineRequest"] = _MODIFYACKDEADLINEREQUEST -DESCRIPTOR.message_types_by_name["AcknowledgeRequest"] = _ACKNOWLEDGEREQUEST -DESCRIPTOR.message_types_by_name["StreamingPullRequest"] = _STREAMINGPULLREQUEST -DESCRIPTOR.message_types_by_name["StreamingPullResponse"] = _STREAMINGPULLRESPONSE -DESCRIPTOR.message_types_by_name["CreateSnapshotRequest"] = _CREATESNAPSHOTREQUEST -DESCRIPTOR.message_types_by_name["UpdateSnapshotRequest"] = _UPDATESNAPSHOTREQUEST -DESCRIPTOR.message_types_by_name["Snapshot"] = _SNAPSHOT -DESCRIPTOR.message_types_by_name["GetSnapshotRequest"] = _GETSNAPSHOTREQUEST -DESCRIPTOR.message_types_by_name["ListSnapshotsRequest"] = _LISTSNAPSHOTSREQUEST -DESCRIPTOR.message_types_by_name["ListSnapshotsResponse"] = _LISTSNAPSHOTSRESPONSE -DESCRIPTOR.message_types_by_name["DeleteSnapshotRequest"] = _DELETESNAPSHOTREQUEST -DESCRIPTOR.message_types_by_name["SeekRequest"] = _SEEKREQUEST -DESCRIPTOR.message_types_by_name["SeekResponse"] = _SEEKRESPONSE -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -MessageStoragePolicy = _reflection.GeneratedProtocolMessageType( - "MessageStoragePolicy", - (_message.Message,), - dict( - DESCRIPTOR=_MESSAGESTORAGEPOLICY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""A message storage policy. - - - Attributes: - allowed_persistence_regions: - A list of IDs of GCP regions where messages that are published - to the topic may be persisted in storage. Messages published - by publishers running in non-allowed GCP regions (or running - outside of GCP altogether) will be routed for storage in one - of the allowed regions. An empty list means that no regions - are allowed, and is not a valid configuration. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.MessageStoragePolicy) - ), -) -_sym_db.RegisterMessage(MessageStoragePolicy) - -Topic = _reflection.GeneratedProtocolMessageType( - "Topic", - (_message.Message,), - dict( - LabelsEntry=_reflection.GeneratedProtocolMessageType( - "LabelsEntry", - (_message.Message,), - dict( - DESCRIPTOR=_TOPIC_LABELSENTRY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2" - # @@protoc_insertion_point(class_scope:google.pubsub.v1.Topic.LabelsEntry) - ), - ), - DESCRIPTOR=_TOPIC, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""A topic resource. - - - Attributes: - name: - The name of the topic. It must have the format - ``"projects/{project}/topics/{topic}"``. ``{topic}`` must - start with a letter, and contain only letters (``[A-Za-z]``), - numbers (``[0-9]``), dashes (``-``), underscores (``_``), - periods (``.``), tildes (``~``), plus (``+``) or percent signs - (``%``). It must be between 3 and 255 characters in length, - and it must not start with ``"goog"``. - labels: - See Creating and managing labels. - message_storage_policy: - Policy constraining the set of Google Cloud Platform regions - where messages published to the topic may be stored. If not - present, then no constraints are in effect. - kms_key_name: - The resource name of the Cloud KMS CryptoKey to be used to - protect access to messages published on this topic. The - expected format is - ``projects/*/locations/*/keyRings/*/cryptoKeys/*``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.Topic) - ), -) -_sym_db.RegisterMessage(Topic) -_sym_db.RegisterMessage(Topic.LabelsEntry) - -PubsubMessage = _reflection.GeneratedProtocolMessageType( - "PubsubMessage", - (_message.Message,), - dict( - AttributesEntry=_reflection.GeneratedProtocolMessageType( - "AttributesEntry", - (_message.Message,), - dict( - DESCRIPTOR=_PUBSUBMESSAGE_ATTRIBUTESENTRY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2" - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PubsubMessage.AttributesEntry) - ), - ), - DESCRIPTOR=_PUBSUBMESSAGE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""A message that is published by publishers and consumed by subscribers. - The message must contain either a non-empty data field or at least one - attribute. Note that client libraries represent this object differently - depending on the language. See the corresponding client library - documentation for more information. See Quotas and limits for more - information about message limits. - - - Attributes: - data: - The message data field. If this field is empty, the message - must contain at least one attribute. - attributes: - Optional attributes for this message. - message_id: - ID of this message, assigned by the server when the message is - published. Guaranteed to be unique within the topic. This - value may be read by a subscriber that receives a - ``PubsubMessage`` via a ``Pull`` call or a push delivery. It - must not be populated by the publisher in a ``Publish`` call. - publish_time: - The time at which the message was published, populated by the - server when it receives the ``Publish`` call. It must not be - populated by the publisher in a ``Publish`` call. - ordering_key: - Identifies related messages for which publish order should be - respected. If a ``Subscription`` has - ``enable_message_ordering`` set to ``true``, messages - published with the same ``ordering_key`` value will be - delivered to subscribers in the order in which they are - received by the Pub/Sub system. EXPERIMENTAL: This feature is - part of a closed alpha release. This API might be changed in - backward-incompatible ways and is not recommended for - production use. It is not subject to any SLA or deprecation - policy. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PubsubMessage) - ), -) -_sym_db.RegisterMessage(PubsubMessage) -_sym_db.RegisterMessage(PubsubMessage.AttributesEntry) - -GetTopicRequest = _reflection.GeneratedProtocolMessageType( - "GetTopicRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GETTOPICREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the GetTopic method. - - - Attributes: - topic: - The name of the topic to get. Format is - ``projects/{project}/topics/{topic}``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.GetTopicRequest) - ), -) -_sym_db.RegisterMessage(GetTopicRequest) - -UpdateTopicRequest = _reflection.GeneratedProtocolMessageType( - "UpdateTopicRequest", - (_message.Message,), - dict( - DESCRIPTOR=_UPDATETOPICREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the UpdateTopic method. - - - Attributes: - topic: - The updated topic object. - update_mask: - Indicates which fields in the provided topic to update. Must - be specified and non-empty. Note that if ``update_mask`` - contains "message\_storage\_policy" then the new value will be - determined based on the policy configured at the project or - organization level. The ``message_storage_policy`` must not be - set in the ``topic`` provided above. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.UpdateTopicRequest) - ), -) -_sym_db.RegisterMessage(UpdateTopicRequest) - -PublishRequest = _reflection.GeneratedProtocolMessageType( - "PublishRequest", - (_message.Message,), - dict( - DESCRIPTOR=_PUBLISHREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the Publish method. - - - Attributes: - topic: - The messages in the request will be published on this topic. - Format is ``projects/{project}/topics/{topic}``. - messages: - The messages to publish. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PublishRequest) - ), -) -_sym_db.RegisterMessage(PublishRequest) - -PublishResponse = _reflection.GeneratedProtocolMessageType( - "PublishResponse", - (_message.Message,), - dict( - DESCRIPTOR=_PUBLISHRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``Publish`` method. - - - Attributes: - message_ids: - The server-assigned ID of each published message, in the same - order as the messages in the request. IDs are guaranteed to be - unique within the topic. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PublishResponse) - ), -) -_sym_db.RegisterMessage(PublishResponse) - -ListTopicsRequest = _reflection.GeneratedProtocolMessageType( - "ListTopicsRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTTOPICSREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``ListTopics`` method. - - - Attributes: - project: - The name of the project in which to list topics. Format is - ``projects/{project-id}``. - page_size: - Maximum number of topics to return. - page_token: - The value returned by the last ``ListTopicsResponse``; - indicates that this is a continuation of a prior - ``ListTopics`` call, and that the system should return the - next page of data. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListTopicsRequest) - ), -) -_sym_db.RegisterMessage(ListTopicsRequest) - -ListTopicsResponse = _reflection.GeneratedProtocolMessageType( - "ListTopicsResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTTOPICSRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``ListTopics`` method. - - - Attributes: - topics: - The resulting topics. - next_page_token: - If not empty, indicates that there may be more topics that - match the request; this value should be passed in a new - ``ListTopicsRequest``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListTopicsResponse) - ), -) -_sym_db.RegisterMessage(ListTopicsResponse) - -ListTopicSubscriptionsRequest = _reflection.GeneratedProtocolMessageType( - "ListTopicSubscriptionsRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTTOPICSUBSCRIPTIONSREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``ListTopicSubscriptions`` method. - - - Attributes: - topic: - The name of the topic that subscriptions are attached to. - Format is ``projects/{project}/topics/{topic}``. - page_size: - Maximum number of subscription names to return. - page_token: - The value returned by the last - ``ListTopicSubscriptionsResponse``; indicates that this is a - continuation of a prior ``ListTopicSubscriptions`` call, and - that the system should return the next page of data. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListTopicSubscriptionsRequest) - ), -) -_sym_db.RegisterMessage(ListTopicSubscriptionsRequest) - -ListTopicSubscriptionsResponse = _reflection.GeneratedProtocolMessageType( - "ListTopicSubscriptionsResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTTOPICSUBSCRIPTIONSRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``ListTopicSubscriptions`` method. - - - Attributes: - subscriptions: - The names of the subscriptions that match the request. - next_page_token: - If not empty, indicates that there may be more subscriptions - that match the request; this value should be passed in a new - ``ListTopicSubscriptionsRequest`` to get more subscriptions. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListTopicSubscriptionsResponse) - ), -) -_sym_db.RegisterMessage(ListTopicSubscriptionsResponse) - -ListTopicSnapshotsRequest = _reflection.GeneratedProtocolMessageType( - "ListTopicSnapshotsRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTTOPICSNAPSHOTSREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``ListTopicSnapshots`` method. - - - Attributes: - topic: - The name of the topic that snapshots are attached to. Format - is ``projects/{project}/topics/{topic}``. - page_size: - Maximum number of snapshot names to return. - page_token: - The value returned by the last ``ListTopicSnapshotsResponse``; - indicates that this is a continuation of a prior - ``ListTopicSnapshots`` call, and that the system should return - the next page of data. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListTopicSnapshotsRequest) - ), -) -_sym_db.RegisterMessage(ListTopicSnapshotsRequest) - -ListTopicSnapshotsResponse = _reflection.GeneratedProtocolMessageType( - "ListTopicSnapshotsResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTTOPICSNAPSHOTSRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``ListTopicSnapshots`` method. - - - Attributes: - snapshots: - The names of the snapshots that match the request. - next_page_token: - If not empty, indicates that there may be more snapshots that - match the request; this value should be passed in a new - ``ListTopicSnapshotsRequest`` to get more snapshots. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListTopicSnapshotsResponse) - ), -) -_sym_db.RegisterMessage(ListTopicSnapshotsResponse) - -DeleteTopicRequest = _reflection.GeneratedProtocolMessageType( - "DeleteTopicRequest", - (_message.Message,), - dict( - DESCRIPTOR=_DELETETOPICREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``DeleteTopic`` method. - - - Attributes: - topic: - Name of the topic to delete. Format is - ``projects/{project}/topics/{topic}``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.DeleteTopicRequest) - ), -) -_sym_db.RegisterMessage(DeleteTopicRequest) - -Subscription = _reflection.GeneratedProtocolMessageType( - "Subscription", - (_message.Message,), - dict( - LabelsEntry=_reflection.GeneratedProtocolMessageType( - "LabelsEntry", - (_message.Message,), - dict( - DESCRIPTOR=_SUBSCRIPTION_LABELSENTRY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2" - # @@protoc_insertion_point(class_scope:google.pubsub.v1.Subscription.LabelsEntry) - ), - ), - DESCRIPTOR=_SUBSCRIPTION, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""A subscription resource. - - - Attributes: - name: - The name of the subscription. It must have the format - ``"projects/{project}/subscriptions/{subscription}"``. - ``{subscription}`` must start with a letter, and contain only - letters (``[A-Za-z]``), numbers (``[0-9]``), dashes (``-``), - underscores (``_``), periods (``.``), tildes (``~``), plus - (``+``) or percent signs (``%``). It must be between 3 and 255 - characters in length, and it must not start with ``"goog"``. - topic: - The name of the topic from which this subscription is - receiving messages. Format is - ``projects/{project}/topics/{topic}``. The value of this field - will be ``_deleted-topic_`` if the topic has been deleted. - push_config: - If push delivery is used with this subscription, this field is - used to configure it. An empty ``pushConfig`` signifies that - the subscriber will pull and ack messages using API methods. - ack_deadline_seconds: - The approximate amount of time (on a best-effort basis) - Pub/Sub waits for the subscriber to acknowledge receipt before - resending the message. In the interval after the message is - delivered and before it is acknowledged, it is considered to - be outstanding. During that time period, the message will not - be redelivered (on a best-effort basis). For pull - subscriptions, this value is used as the initial value for the - ack deadline. To override this value for a given message, call - ``ModifyAckDeadline`` with the corresponding ``ack_id`` if - using non-streaming pull or send the ``ack_id`` in a - ``StreamingModifyAckDeadlineRequest`` if using streaming pull. - The minimum custom deadline you can specify is 10 seconds. The - maximum custom deadline you can specify is 600 seconds (10 - minutes). If this parameter is 0, a default value of 10 - seconds is used. For push delivery, this value is also used - to set the request timeout for the call to the push endpoint. - If the subscriber never acknowledges the message, the Pub/Sub - system will eventually redeliver the message. - retain_acked_messages: - Indicates whether to retain acknowledged messages. If true, - then messages are not expunged from the subscription's - backlog, even if they are acknowledged, until they fall out of - the ``message_retention_duration`` window. This must be true - if you would like to Seek to a timestamp. - message_retention_duration: - How long to retain unacknowledged messages in the - subscription's backlog, from the moment a message is - published. If ``retain_acked_messages`` is true, then this - also configures the retention of acknowledged messages, and - thus configures how far back in time a ``Seek`` can be done. - Defaults to 7 days. Cannot be more than 7 days or less than 10 - minutes. - labels: - See Creating and managing labels. - enable_message_ordering: - If true, messages published with the same ``ordering_key`` in - ``PubsubMessage`` will be delivered to the subscribers in the - order in which they are received by the Pub/Sub system. - Otherwise, they may be delivered in any order. EXPERIMENTAL: - This feature is part of a closed alpha release. This API might - be changed in backward-incompatible ways and is not - recommended for production use. It is not subject to any SLA - or deprecation policy. - expiration_policy: - A policy that specifies the conditions for this subscription's - expiration. A subscription is considered active as long as any - connected subscriber is successfully consuming messages from - the subscription or is issuing operations on the subscription. - If ``expiration_policy`` is not set, a *default policy* with - ``ttl`` of 31 days will be used. The minimum allowed value for - ``expiration_policy.ttl`` is 1 day. - dead_letter_policy: - A policy that specifies the conditions for dead lettering - messages in this subscription. If dead\_letter\_policy is not - set, dead lettering is disabled. The Cloud Pub/Sub service - account associated with this subscriptions's parent project - (i.e., service-{project\_number}@gcp-sa- - pubsub.iam.gserviceaccount.com) must have permission to - Acknowledge() messages on this subscription. EXPERIMENTAL: - This feature is part of a closed alpha release. This API might - be changed in backward-incompatible ways and is not - recommended for production use. It is not subject to any SLA - or deprecation policy. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.Subscription) - ), -) -_sym_db.RegisterMessage(Subscription) -_sym_db.RegisterMessage(Subscription.LabelsEntry) - -DeadLetterPolicy = _reflection.GeneratedProtocolMessageType( - "DeadLetterPolicy", - (_message.Message,), - dict( - DESCRIPTOR=_DEADLETTERPOLICY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Dead lettering is done on a best effort basis. The same message might be - dead lettered multiple times. - - If validation on any of the fields fails at subscription - creation/updation, the create/update subscription request will fail. - - - Attributes: - dead_letter_topic: - The name of the topic to which dead letter messages should be - published. Format is ``projects/{project}/topics/{topic}``.The - Cloud Pub/Sub service account associated with the enclosing - subscription's parent project (i.e., - service-{project\_number}@gcp-sa- - pubsub.iam.gserviceaccount.com) must have permission to - Publish() to this topic. The operation will fail if the topic - does not exist. Users should ensure that there is a - subscription attached to this topic since messages published - to a topic with no subscriptions are lost. - max_delivery_attempts: - The maximum number of delivery attempts for any message. The - value must be between 5 and 100. The number of delivery - attempts is defined as 1 + (the sum of number of NACKs and - number of times the acknowledgement deadline has been exceeded - for the message). A NACK is any call to ModifyAckDeadline - with a 0 deadline. Note that client libraries may - automatically extend ack\_deadlines. This field will be - honored on a best effort basis. If this parameter is 0, a - default value of 5 is used. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.DeadLetterPolicy) - ), -) -_sym_db.RegisterMessage(DeadLetterPolicy) - -ExpirationPolicy = _reflection.GeneratedProtocolMessageType( - "ExpirationPolicy", - (_message.Message,), - dict( - DESCRIPTOR=_EXPIRATIONPOLICY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""A policy that specifies the conditions for resource expiration (i.e., - automatic resource deletion). - - - Attributes: - ttl: - Specifies the "time-to-live" duration for an associated - resource. The resource expires if it is not active for a - period of ``ttl``. The definition of "activity" depends on the - type of the associated resource. The minimum and maximum - allowed values for ``ttl`` depend on the type of the - associated resource, as well. If ``ttl`` is not set, the - associated resource never expires. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ExpirationPolicy) - ), -) -_sym_db.RegisterMessage(ExpirationPolicy) - -PushConfig = _reflection.GeneratedProtocolMessageType( - "PushConfig", - (_message.Message,), - dict( - OidcToken=_reflection.GeneratedProtocolMessageType( - "OidcToken", - (_message.Message,), - dict( - DESCRIPTOR=_PUSHCONFIG_OIDCTOKEN, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Contains information needed for generating an `OpenID Connect - token `__. - - - Attributes: - service_account_email: - `Service account email - `__ to be - used for generating the OIDC token. The caller (for - CreateSubscription, UpdateSubscription, and ModifyPushConfig - RPCs) must have the iam.serviceAccounts.actAs permission for - the service account. - audience: - Audience to be used when generating OIDC token. The audience - claim identifies the recipients that the JWT is intended for. - The audience value is a single case-sensitive string. Having - multiple values (array) for the audience field is not - supported. More info about the OIDC JWT token audience here: - https://tools.ietf.org/html/rfc7519#section-4.1.3 Note: if not - specified, the Push endpoint URL will be used. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PushConfig.OidcToken) - ), - ), - AttributesEntry=_reflection.GeneratedProtocolMessageType( - "AttributesEntry", - (_message.Message,), - dict( - DESCRIPTOR=_PUSHCONFIG_ATTRIBUTESENTRY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2" - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PushConfig.AttributesEntry) - ), - ), - DESCRIPTOR=_PUSHCONFIG, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Configuration for a push delivery endpoint. - - - Attributes: - push_endpoint: - A URL locating the endpoint to which messages should be - pushed. For example, a Webhook endpoint might use - "https://example.com/push". - attributes: - Endpoint configuration attributes that can be used to control - different aspects of the message delivery. The only currently - supported attribute is ``x-goog-version``, which you can use - to change the format of the pushed message. This attribute - indicates the version of the data expected by the endpoint. - This controls the shape of the pushed message (i.e., its - fields and metadata). If not present during the - ``CreateSubscription`` call, it will default to the version of - the Pub/Sub API used to make such call. If not present in a - ``ModifyPushConfig`` call, its value will not be changed. - ``GetSubscription`` calls will always return a valid version, - even if the subscription was created without this attribute. - The only supported values for the ``x-goog-version`` attribute - are: - ``v1beta1``: uses the push format defined in the - v1beta1 Pub/Sub API. - ``v1`` or ``v1beta2``: uses the push - format defined in the v1 Pub/Sub API. For example: .. - raw:: html
attributes { "x-goog-version": "v1"
-          } 
- authentication_method: - An authentication method used by push endpoints to verify the - source of push requests. This can be used with push endpoints - that are private by default to allow requests only from the - Cloud Pub/Sub system, for example. This field is optional and - should be set only by users interested in authenticated push. - oidc_token: - If specified, Pub/Sub will generate and attach an OIDC JWT - token as an ``Authorization`` header in the HTTP request for - every pushed message. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PushConfig) - ), -) -_sym_db.RegisterMessage(PushConfig) -_sym_db.RegisterMessage(PushConfig.OidcToken) -_sym_db.RegisterMessage(PushConfig.AttributesEntry) - -ReceivedMessage = _reflection.GeneratedProtocolMessageType( - "ReceivedMessage", - (_message.Message,), - dict( - DESCRIPTOR=_RECEIVEDMESSAGE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""A message and its corresponding acknowledgment ID. - - - Attributes: - ack_id: - This ID can be used to acknowledge the received message. - message: - The message. - delivery_attempt: - Delivery attempt counter is 1 + (the sum of number of NACKs - and number of ack\_deadline exceeds) for this message. A NACK - is any call to ModifyAckDeadline with a 0 deadline. An - ack\_deadline exceeds event is whenever a message is not - acknowledged within ack\_deadline. Note that ack\_deadline is - initially Subscription.ackDeadlineSeconds, but may get - extended automatically by the client library. The first - delivery of a given message will have this value as 1. The - value is calculated at best effort and is approximate. If a - DeadLetterPolicy is not set on the subscription, this will be - 0. EXPERIMENTAL: This feature is part of a closed alpha - release. This API might be changed in backward-incompatible - ways and is not recommended for production use. It is not - subject to any SLA or deprecation policy. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ReceivedMessage) - ), -) -_sym_db.RegisterMessage(ReceivedMessage) - -GetSubscriptionRequest = _reflection.GeneratedProtocolMessageType( - "GetSubscriptionRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GETSUBSCRIPTIONREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the GetSubscription method. - - - Attributes: - subscription: - The name of the subscription to get. Format is - ``projects/{project}/subscriptions/{sub}``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.GetSubscriptionRequest) - ), -) -_sym_db.RegisterMessage(GetSubscriptionRequest) - -UpdateSubscriptionRequest = _reflection.GeneratedProtocolMessageType( - "UpdateSubscriptionRequest", - (_message.Message,), - dict( - DESCRIPTOR=_UPDATESUBSCRIPTIONREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the UpdateSubscription method. - - - Attributes: - subscription: - The updated subscription object. - update_mask: - Indicates which fields in the provided subscription to update. - Must be specified and non-empty. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.UpdateSubscriptionRequest) - ), -) -_sym_db.RegisterMessage(UpdateSubscriptionRequest) - -ListSubscriptionsRequest = _reflection.GeneratedProtocolMessageType( - "ListSubscriptionsRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTSUBSCRIPTIONSREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``ListSubscriptions`` method. - - - Attributes: - project: - The name of the project in which to list subscriptions. Format - is ``projects/{project-id}``. - page_size: - Maximum number of subscriptions to return. - page_token: - The value returned by the last ``ListSubscriptionsResponse``; - indicates that this is a continuation of a prior - ``ListSubscriptions`` call, and that the system should return - the next page of data. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListSubscriptionsRequest) - ), -) -_sym_db.RegisterMessage(ListSubscriptionsRequest) - -ListSubscriptionsResponse = _reflection.GeneratedProtocolMessageType( - "ListSubscriptionsResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTSUBSCRIPTIONSRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``ListSubscriptions`` method. - - - Attributes: - subscriptions: - The subscriptions that match the request. - next_page_token: - If not empty, indicates that there may be more subscriptions - that match the request; this value should be passed in a new - ``ListSubscriptionsRequest`` to get more subscriptions. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListSubscriptionsResponse) - ), -) -_sym_db.RegisterMessage(ListSubscriptionsResponse) - -DeleteSubscriptionRequest = _reflection.GeneratedProtocolMessageType( - "DeleteSubscriptionRequest", - (_message.Message,), - dict( - DESCRIPTOR=_DELETESUBSCRIPTIONREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the DeleteSubscription method. - - - Attributes: - subscription: - The subscription to delete. Format is - ``projects/{project}/subscriptions/{sub}``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.DeleteSubscriptionRequest) - ), -) -_sym_db.RegisterMessage(DeleteSubscriptionRequest) - -ModifyPushConfigRequest = _reflection.GeneratedProtocolMessageType( - "ModifyPushConfigRequest", - (_message.Message,), - dict( - DESCRIPTOR=_MODIFYPUSHCONFIGREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ModifyPushConfig method. - - - Attributes: - subscription: - The name of the subscription. Format is - ``projects/{project}/subscriptions/{sub}``. - push_config: - The push configuration for future deliveries. An empty - ``pushConfig`` indicates that the Pub/Sub system should stop - pushing messages from the given subscription and allow - messages to be pulled and acknowledged - effectively pausing - the subscription if ``Pull`` or ``StreamingPull`` is not - called. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ModifyPushConfigRequest) - ), -) -_sym_db.RegisterMessage(ModifyPushConfigRequest) - -PullRequest = _reflection.GeneratedProtocolMessageType( - "PullRequest", - (_message.Message,), - dict( - DESCRIPTOR=_PULLREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``Pull`` method. - - - Attributes: - subscription: - The subscription from which messages should be pulled. Format - is ``projects/{project}/subscriptions/{sub}``. - return_immediately: - If this field set to true, the system will respond immediately - even if it there are no messages available to return in the - ``Pull`` response. Otherwise, the system may wait (for a - bounded amount of time) until at least one message is - available, rather than returning no messages. - max_messages: - The maximum number of messages to return for this request. - Must be a positive integer. The Pub/Sub system may return - fewer than the number specified. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PullRequest) - ), -) -_sym_db.RegisterMessage(PullRequest) - -PullResponse = _reflection.GeneratedProtocolMessageType( - "PullResponse", - (_message.Message,), - dict( - DESCRIPTOR=_PULLRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``Pull`` method. - - - Attributes: - received_messages: - Received Pub/Sub messages. The list will be empty if there are - no more messages available in the backlog. For JSON, the - response can be entirely empty. The Pub/Sub system may return - fewer than the ``maxMessages`` requested even if there are - more messages available in the backlog. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.PullResponse) - ), -) -_sym_db.RegisterMessage(PullResponse) - -ModifyAckDeadlineRequest = _reflection.GeneratedProtocolMessageType( - "ModifyAckDeadlineRequest", - (_message.Message,), - dict( - DESCRIPTOR=_MODIFYACKDEADLINEREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ModifyAckDeadline method. - - - Attributes: - subscription: - The name of the subscription. Format is - ``projects/{project}/subscriptions/{sub}``. - ack_ids: - List of acknowledgment IDs. - ack_deadline_seconds: - The new ack deadline with respect to the time this request was - sent to the Pub/Sub system. For example, if the value is 10, - the new ack deadline will expire 10 seconds after the - ``ModifyAckDeadline`` call was made. Specifying zero might - immediately make the message available for delivery to another - subscriber client. This typically results in an increase in - the rate of message redeliveries (that is, duplicates). The - minimum deadline you can specify is 0 seconds. The maximum - deadline you can specify is 600 seconds (10 minutes). - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ModifyAckDeadlineRequest) - ), -) -_sym_db.RegisterMessage(ModifyAckDeadlineRequest) - -AcknowledgeRequest = _reflection.GeneratedProtocolMessageType( - "AcknowledgeRequest", - (_message.Message,), - dict( - DESCRIPTOR=_ACKNOWLEDGEREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the Acknowledge method. - - - Attributes: - subscription: - The subscription whose message is being acknowledged. Format - is ``projects/{project}/subscriptions/{sub}``. - ack_ids: - The acknowledgment ID for the messages being acknowledged that - was returned by the Pub/Sub system in the ``Pull`` response. - Must not be empty. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.AcknowledgeRequest) - ), -) -_sym_db.RegisterMessage(AcknowledgeRequest) - -StreamingPullRequest = _reflection.GeneratedProtocolMessageType( - "StreamingPullRequest", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGPULLREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``StreamingPull`` streaming RPC method. This request is - used to establish the initial stream as well as to stream - acknowledgements and ack deadline modifications from the client to the - server. - - - Attributes: - subscription: - The subscription for which to initialize the new stream. This - must be provided in the first request on the stream, and must - not be set in subsequent requests from client to server. - Format is ``projects/{project}/subscriptions/{sub}``. - ack_ids: - List of acknowledgement IDs for acknowledging previously - received messages (received on this stream or a different - stream). If an ack ID has expired, the corresponding message - may be redelivered later. Acknowledging a message more than - once will not result in an error. If the acknowledgement ID is - malformed, the stream will be aborted with status - ``INVALID_ARGUMENT``. - modify_deadline_seconds: - The list of new ack deadlines for the IDs listed in - ``modify_deadline_ack_ids``. The size of this list must be the - same as the size of ``modify_deadline_ack_ids``. If it differs - the stream will be aborted with ``INVALID_ARGUMENT``. Each - element in this list is applied to the element in the same - position in ``modify_deadline_ack_ids``. The new ack deadline - is with respect to the time this request was sent to the - Pub/Sub system. Must be >= 0. For example, if the value is 10, - the new ack deadline will expire 10 seconds after this request - is received. If the value is 0, the message is immediately - made available for another streaming or non-streaming pull - request. If the value is < 0 (an error), the stream will be - aborted with status ``INVALID_ARGUMENT``. - modify_deadline_ack_ids: - List of acknowledgement IDs whose deadline will be modified - based on the corresponding element in - ``modify_deadline_seconds``. This field can be used to - indicate that more time is needed to process a message by the - subscriber, or to make the message available for redelivery if - the processing was interrupted. - stream_ack_deadline_seconds: - The ack deadline to use for the stream. This must be provided - in the first request on the stream, but it can also be updated - on subsequent requests from client to server. The minimum - deadline you can specify is 10 seconds. The maximum deadline - you can specify is 600 seconds (10 minutes). - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.StreamingPullRequest) - ), -) -_sym_db.RegisterMessage(StreamingPullRequest) - -StreamingPullResponse = _reflection.GeneratedProtocolMessageType( - "StreamingPullResponse", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGPULLRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``StreamingPull`` method. This response is used to - stream messages from the server to the client. - - - Attributes: - received_messages: - Received Pub/Sub messages. This will not be empty. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.StreamingPullResponse) - ), -) -_sym_db.RegisterMessage(StreamingPullResponse) - -CreateSnapshotRequest = _reflection.GeneratedProtocolMessageType( - "CreateSnapshotRequest", - (_message.Message,), - dict( - LabelsEntry=_reflection.GeneratedProtocolMessageType( - "LabelsEntry", - (_message.Message,), - dict( - DESCRIPTOR=_CREATESNAPSHOTREQUEST_LABELSENTRY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2" - # @@protoc_insertion_point(class_scope:google.pubsub.v1.CreateSnapshotRequest.LabelsEntry) - ), - ), - DESCRIPTOR=_CREATESNAPSHOTREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``CreateSnapshot`` method. - - - Attributes: - name: - Optional user-provided name for this snapshot. If the name is - not provided in the request, the server will assign a random - name for this snapshot on the same project as the - subscription. Note that for REST API requests, you must - specify a name. See the resource name rules. Format is - ``projects/{project}/snapshots/{snap}``. - subscription: - The subscription whose backlog the snapshot retains. - Specifically, the created snapshot is guaranteed to retain: - (a) The existing backlog on the subscription. More precisely, - this is defined as the messages in the subscription's backlog - that are unacknowledged upon the successful completion of the - ``CreateSnapshot`` request; as well as: (b) Any messages - published to the subscription's topic following the successful - completion of the CreateSnapshot request. Format is - ``projects/{project}/subscriptions/{sub}``. - labels: - See Creating and managing labels. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.CreateSnapshotRequest) - ), -) -_sym_db.RegisterMessage(CreateSnapshotRequest) -_sym_db.RegisterMessage(CreateSnapshotRequest.LabelsEntry) - -UpdateSnapshotRequest = _reflection.GeneratedProtocolMessageType( - "UpdateSnapshotRequest", - (_message.Message,), - dict( - DESCRIPTOR=_UPDATESNAPSHOTREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the UpdateSnapshot method. - - - Attributes: - snapshot: - The updated snapshot object. - update_mask: - Indicates which fields in the provided snapshot to update. - Must be specified and non-empty. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.UpdateSnapshotRequest) - ), -) -_sym_db.RegisterMessage(UpdateSnapshotRequest) - -Snapshot = _reflection.GeneratedProtocolMessageType( - "Snapshot", - (_message.Message,), - dict( - LabelsEntry=_reflection.GeneratedProtocolMessageType( - "LabelsEntry", - (_message.Message,), - dict( - DESCRIPTOR=_SNAPSHOT_LABELSENTRY, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2" - # @@protoc_insertion_point(class_scope:google.pubsub.v1.Snapshot.LabelsEntry) - ), - ), - DESCRIPTOR=_SNAPSHOT, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""A snapshot resource. Snapshots are used in Seek operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the - state captured by a snapshot. - - - Attributes: - name: - The name of the snapshot. - topic: - The name of the topic from which this snapshot is retaining - messages. - expire_time: - The snapshot is guaranteed to exist up until this time. A - newly-created snapshot expires no later than 7 days from the - time of its creation. Its exact lifetime is determined at - creation by the existing backlog in the source subscription. - Specifically, the lifetime of the snapshot is ``7 days - (age - of oldest unacked message in the subscription)``. For example, - consider a subscription whose oldest unacked message is 3 days - old. If a snapshot is created from this subscription, the - snapshot -- which will always capture this 3-day-old backlog - as long as the snapshot exists -- will expire in 4 days. The - service will refuse to create a snapshot that would expire in - less than 1 hour after creation. - labels: - See Creating and managing labels. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.Snapshot) - ), -) -_sym_db.RegisterMessage(Snapshot) -_sym_db.RegisterMessage(Snapshot.LabelsEntry) - -GetSnapshotRequest = _reflection.GeneratedProtocolMessageType( - "GetSnapshotRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GETSNAPSHOTREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the GetSnapshot method. - - - Attributes: - snapshot: - The name of the snapshot to get. Format is - ``projects/{project}/snapshots/{snap}``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.GetSnapshotRequest) - ), -) -_sym_db.RegisterMessage(GetSnapshotRequest) - -ListSnapshotsRequest = _reflection.GeneratedProtocolMessageType( - "ListSnapshotsRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTSNAPSHOTSREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``ListSnapshots`` method. - - - Attributes: - project: - The name of the project in which to list snapshots. Format is - ``projects/{project-id}``. - page_size: - Maximum number of snapshots to return. - page_token: - The value returned by the last ``ListSnapshotsResponse``; - indicates that this is a continuation of a prior - ``ListSnapshots`` call, and that the system should return the - next page of data. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListSnapshotsRequest) - ), -) -_sym_db.RegisterMessage(ListSnapshotsRequest) - -ListSnapshotsResponse = _reflection.GeneratedProtocolMessageType( - "ListSnapshotsResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTSNAPSHOTSRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``ListSnapshots`` method. - - - Attributes: - snapshots: - The resulting snapshots. - next_page_token: - If not empty, indicates that there may be more snapshot that - match the request; this value should be passed in a new - ``ListSnapshotsRequest``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.ListSnapshotsResponse) - ), -) -_sym_db.RegisterMessage(ListSnapshotsResponse) - -DeleteSnapshotRequest = _reflection.GeneratedProtocolMessageType( - "DeleteSnapshotRequest", - (_message.Message,), - dict( - DESCRIPTOR=_DELETESNAPSHOTREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``DeleteSnapshot`` method. - - - Attributes: - snapshot: - The name of the snapshot to delete. Format is - ``projects/{project}/snapshots/{snap}``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.DeleteSnapshotRequest) - ), -) -_sym_db.RegisterMessage(DeleteSnapshotRequest) - -SeekRequest = _reflection.GeneratedProtocolMessageType( - "SeekRequest", - (_message.Message,), - dict( - DESCRIPTOR=_SEEKREQUEST, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Request for the ``Seek`` method. - - - Attributes: - subscription: - The subscription to affect. - time: - The time to seek to. Messages retained in the subscription - that were published before this time are marked as - acknowledged, and messages retained in the subscription that - were published after this time are marked as unacknowledged. - Note that this operation affects only those messages retained - in the subscription (configured by the combination of - ``message_retention_duration`` and ``retain_acked_messages``). - For example, if ``time`` corresponds to a point before the - message retention window (or to a point before the system's - notion of the subscription creation time), only retained - messages will be marked as unacknowledged, and already- - expunged messages will not be restored. - snapshot: - The snapshot to seek to. The snapshot's topic must be the same - as that of the provided subscription. Format is - ``projects/{project}/snapshots/{snap}``. - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.SeekRequest) - ), -) -_sym_db.RegisterMessage(SeekRequest) - -SeekResponse = _reflection.GeneratedProtocolMessageType( - "SeekResponse", - (_message.Message,), - dict( - DESCRIPTOR=_SEEKRESPONSE, - __module__="google.cloud.pubsub_v1.proto.pubsub_pb2", - __doc__="""Response for the ``Seek`` method (this response is empty). - """, - # @@protoc_insertion_point(class_scope:google.pubsub.v1.SeekResponse) - ), -) -_sym_db.RegisterMessage(SeekResponse) - - -DESCRIPTOR._options = None -_TOPIC_LABELSENTRY._options = None -_PUBSUBMESSAGE_ATTRIBUTESENTRY._options = None -_SUBSCRIPTION_LABELSENTRY._options = None -_PUSHCONFIG_ATTRIBUTESENTRY._options = None -_CREATESNAPSHOTREQUEST_LABELSENTRY._options = None -_SNAPSHOT_LABELSENTRY._options = None - -_PUBLISHER = _descriptor.ServiceDescriptor( - name="Publisher", - full_name="google.pubsub.v1.Publisher", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\025pubsub.googleapis.com\322AUhttps://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/pubsub" - ), - serialized_start=4589, - serialized_end=5790, - methods=[ - _descriptor.MethodDescriptor( - name="CreateTopic", - full_name="google.pubsub.v1.Publisher.CreateTopic", - index=0, - containing_service=None, - input_type=_TOPIC, - output_type=_TOPIC, - serialized_options=_b( - "\202\323\344\223\002#\032\036/v1/{name=projects/*/topics/*}:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="UpdateTopic", - full_name="google.pubsub.v1.Publisher.UpdateTopic", - index=1, - containing_service=None, - input_type=_UPDATETOPICREQUEST, - output_type=_TOPIC, - serialized_options=_b( - "\202\323\344\223\002)2$/v1/{topic.name=projects/*/topics/*}:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="Publish", - full_name="google.pubsub.v1.Publisher.Publish", - index=2, - containing_service=None, - input_type=_PUBLISHREQUEST, - output_type=_PUBLISHRESPONSE, - serialized_options=_b( - "\202\323\344\223\002,\"'/v1/{topic=projects/*/topics/*}:publish:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="GetTopic", - full_name="google.pubsub.v1.Publisher.GetTopic", - index=3, - containing_service=None, - input_type=_GETTOPICREQUEST, - output_type=_TOPIC, - serialized_options=_b( - "\202\323\344\223\002!\022\037/v1/{topic=projects/*/topics/*}" - ), - ), - _descriptor.MethodDescriptor( - name="ListTopics", - full_name="google.pubsub.v1.Publisher.ListTopics", - index=4, - containing_service=None, - input_type=_LISTTOPICSREQUEST, - output_type=_LISTTOPICSRESPONSE, - serialized_options=_b( - "\202\323\344\223\002!\022\037/v1/{project=projects/*}/topics" - ), - ), - _descriptor.MethodDescriptor( - name="ListTopicSubscriptions", - full_name="google.pubsub.v1.Publisher.ListTopicSubscriptions", - index=5, - containing_service=None, - input_type=_LISTTOPICSUBSCRIPTIONSREQUEST, - output_type=_LISTTOPICSUBSCRIPTIONSRESPONSE, - serialized_options=_b( - "\202\323\344\223\002/\022-/v1/{topic=projects/*/topics/*}/subscriptions" - ), - ), - _descriptor.MethodDescriptor( - name="ListTopicSnapshots", - full_name="google.pubsub.v1.Publisher.ListTopicSnapshots", - index=6, - containing_service=None, - input_type=_LISTTOPICSNAPSHOTSREQUEST, - output_type=_LISTTOPICSNAPSHOTSRESPONSE, - serialized_options=_b( - "\202\323\344\223\002+\022)/v1/{topic=projects/*/topics/*}/snapshots" - ), - ), - _descriptor.MethodDescriptor( - name="DeleteTopic", - full_name="google.pubsub.v1.Publisher.DeleteTopic", - index=7, - containing_service=None, - input_type=_DELETETOPICREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=_b( - "\202\323\344\223\002!*\037/v1/{topic=projects/*/topics/*}" - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_PUBLISHER) - -DESCRIPTOR.services_by_name["Publisher"] = _PUBLISHER - - -_SUBSCRIBER = _descriptor.ServiceDescriptor( - name="Subscriber", - full_name="google.pubsub.v1.Subscriber", - file=DESCRIPTOR, - index=1, - serialized_options=_b( - "\312A\025pubsub.googleapis.com\322AUhttps://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/pubsub" - ), - serialized_start=5793, - serialized_end=8204, - methods=[ - _descriptor.MethodDescriptor( - name="CreateSubscription", - full_name="google.pubsub.v1.Subscriber.CreateSubscription", - index=0, - containing_service=None, - input_type=_SUBSCRIPTION, - output_type=_SUBSCRIPTION, - serialized_options=_b( - "\202\323\344\223\002*\032%/v1/{name=projects/*/subscriptions/*}:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="GetSubscription", - full_name="google.pubsub.v1.Subscriber.GetSubscription", - index=1, - containing_service=None, - input_type=_GETSUBSCRIPTIONREQUEST, - output_type=_SUBSCRIPTION, - serialized_options=_b( - "\202\323\344\223\002/\022-/v1/{subscription=projects/*/subscriptions/*}" - ), - ), - _descriptor.MethodDescriptor( - name="UpdateSubscription", - full_name="google.pubsub.v1.Subscriber.UpdateSubscription", - index=2, - containing_service=None, - input_type=_UPDATESUBSCRIPTIONREQUEST, - output_type=_SUBSCRIPTION, - serialized_options=_b( - "\202\323\344\223\002722/v1/{subscription.name=projects/*/subscriptions/*}:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="ListSubscriptions", - full_name="google.pubsub.v1.Subscriber.ListSubscriptions", - index=3, - containing_service=None, - input_type=_LISTSUBSCRIPTIONSREQUEST, - output_type=_LISTSUBSCRIPTIONSRESPONSE, - serialized_options=_b( - "\202\323\344\223\002(\022&/v1/{project=projects/*}/subscriptions" - ), - ), - _descriptor.MethodDescriptor( - name="DeleteSubscription", - full_name="google.pubsub.v1.Subscriber.DeleteSubscription", - index=4, - containing_service=None, - input_type=_DELETESUBSCRIPTIONREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=_b( - "\202\323\344\223\002/*-/v1/{subscription=projects/*/subscriptions/*}" - ), - ), - _descriptor.MethodDescriptor( - name="ModifyAckDeadline", - full_name="google.pubsub.v1.Subscriber.ModifyAckDeadline", - index=5, - containing_service=None, - input_type=_MODIFYACKDEADLINEREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=_b( - '\202\323\344\223\002D"?/v1/{subscription=projects/*/subscriptions/*}:modifyAckDeadline:\001*' - ), - ), - _descriptor.MethodDescriptor( - name="Acknowledge", - full_name="google.pubsub.v1.Subscriber.Acknowledge", - index=6, - containing_service=None, - input_type=_ACKNOWLEDGEREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=_b( - '\202\323\344\223\002>"9/v1/{subscription=projects/*/subscriptions/*}:acknowledge:\001*' - ), - ), - _descriptor.MethodDescriptor( - name="Pull", - full_name="google.pubsub.v1.Subscriber.Pull", - index=7, - containing_service=None, - input_type=_PULLREQUEST, - output_type=_PULLRESPONSE, - serialized_options=_b( - '\202\323\344\223\0027"2/v1/{subscription=projects/*/subscriptions/*}:pull:\001*' - ), - ), - _descriptor.MethodDescriptor( - name="StreamingPull", - full_name="google.pubsub.v1.Subscriber.StreamingPull", - index=8, - containing_service=None, - input_type=_STREAMINGPULLREQUEST, - output_type=_STREAMINGPULLRESPONSE, - serialized_options=None, - ), - _descriptor.MethodDescriptor( - name="ModifyPushConfig", - full_name="google.pubsub.v1.Subscriber.ModifyPushConfig", - index=9, - containing_service=None, - input_type=_MODIFYPUSHCONFIGREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=_b( - '\202\323\344\223\002C">/v1/{subscription=projects/*/subscriptions/*}:modifyPushConfig:\001*' - ), - ), - _descriptor.MethodDescriptor( - name="GetSnapshot", - full_name="google.pubsub.v1.Subscriber.GetSnapshot", - index=10, - containing_service=None, - input_type=_GETSNAPSHOTREQUEST, - output_type=_SNAPSHOT, - serialized_options=_b( - "\202\323\344\223\002'\022%/v1/{snapshot=projects/*/snapshots/*}" - ), - ), - _descriptor.MethodDescriptor( - name="ListSnapshots", - full_name="google.pubsub.v1.Subscriber.ListSnapshots", - index=11, - containing_service=None, - input_type=_LISTSNAPSHOTSREQUEST, - output_type=_LISTSNAPSHOTSRESPONSE, - serialized_options=_b( - '\202\323\344\223\002$\022"/v1/{project=projects/*}/snapshots' - ), - ), - _descriptor.MethodDescriptor( - name="CreateSnapshot", - full_name="google.pubsub.v1.Subscriber.CreateSnapshot", - index=12, - containing_service=None, - input_type=_CREATESNAPSHOTREQUEST, - output_type=_SNAPSHOT, - serialized_options=_b( - "\202\323\344\223\002&\032!/v1/{name=projects/*/snapshots/*}:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="UpdateSnapshot", - full_name="google.pubsub.v1.Subscriber.UpdateSnapshot", - index=13, - containing_service=None, - input_type=_UPDATESNAPSHOTREQUEST, - output_type=_SNAPSHOT, - serialized_options=_b( - "\202\323\344\223\002/2*/v1/{snapshot.name=projects/*/snapshots/*}:\001*" - ), - ), - _descriptor.MethodDescriptor( - name="DeleteSnapshot", - full_name="google.pubsub.v1.Subscriber.DeleteSnapshot", - index=14, - containing_service=None, - input_type=_DELETESNAPSHOTREQUEST, - output_type=google_dot_protobuf_dot_empty__pb2._EMPTY, - serialized_options=_b( - "\202\323\344\223\002'*%/v1/{snapshot=projects/*/snapshots/*}" - ), - ), - _descriptor.MethodDescriptor( - name="Seek", - full_name="google.pubsub.v1.Subscriber.Seek", - index=15, - containing_service=None, - input_type=_SEEKREQUEST, - output_type=_SEEKRESPONSE, - serialized_options=_b( - '\202\323\344\223\0027"2/v1/{subscription=projects/*/subscriptions/*}:seek:\001*' - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_SUBSCRIBER) - -DESCRIPTOR.services_by_name["Subscriber"] = _SUBSCRIBER - -# @@protoc_insertion_point(module_scope) diff --git a/pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2_grpc.py b/pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2_grpc.py deleted file mode 100644 index dd1a365877e1..000000000000 --- a/pubsub/google/cloud/pubsub_v1/proto/pubsub_pb2_grpc.py +++ /dev/null @@ -1,573 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.pubsub_v1.proto import ( - pubsub_pb2 as google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2, -) -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 - - -class PublisherStub(object): - """The service that an application uses to manipulate topics, and to send - messages to a topic. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.CreateTopic = channel.unary_unary( - "/google.pubsub.v1.Publisher/CreateTopic", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.FromString, - ) - self.UpdateTopic = channel.unary_unary( - "/google.pubsub.v1.Publisher/UpdateTopic", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.UpdateTopicRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.FromString, - ) - self.Publish = channel.unary_unary( - "/google.pubsub.v1.Publisher/Publish", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PublishRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PublishResponse.FromString, - ) - self.GetTopic = channel.unary_unary( - "/google.pubsub.v1.Publisher/GetTopic", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.GetTopicRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.FromString, - ) - self.ListTopics = channel.unary_unary( - "/google.pubsub.v1.Publisher/ListTopics", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicsRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicsResponse.FromString, - ) - self.ListTopicSubscriptions = channel.unary_unary( - "/google.pubsub.v1.Publisher/ListTopicSubscriptions", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSubscriptionsRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSubscriptionsResponse.FromString, - ) - self.ListTopicSnapshots = channel.unary_unary( - "/google.pubsub.v1.Publisher/ListTopicSnapshots", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSnapshotsRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSnapshotsResponse.FromString, - ) - self.DeleteTopic = channel.unary_unary( - "/google.pubsub.v1.Publisher/DeleteTopic", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.DeleteTopicRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - - -class PublisherServicer(object): - """The service that an application uses to manipulate topics, and to send - messages to a topic. - """ - - def CreateTopic(self, request, context): - """Creates the given topic with the given name. See the - - resource name rules. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def UpdateTopic(self, request, context): - """Updates an existing topic. Note that certain properties of a - topic are not modifiable. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def Publish(self, request, context): - """Adds one or more messages to the topic. Returns `NOT_FOUND` if the topic - does not exist. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetTopic(self, request, context): - """Gets the configuration of a topic. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ListTopics(self, request, context): - """Lists matching topics. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ListTopicSubscriptions(self, request, context): - """Lists the names of the subscriptions on this topic. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ListTopicSnapshots(self, request, context): - """Lists the names of the snapshots on this topic. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def DeleteTopic(self, request, context): - """Deletes the topic with the given name. Returns `NOT_FOUND` if the topic - does not exist. After a topic is deleted, a new topic may be created with - the same name; this is an entirely new topic with none of the old - configuration or subscriptions. Existing subscriptions to this topic are - not deleted, but their `topic` field is set to `_deleted-topic_`. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_PublisherServicer_to_server(servicer, server): - rpc_method_handlers = { - "CreateTopic": grpc.unary_unary_rpc_method_handler( - servicer.CreateTopic, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.SerializeToString, - ), - "UpdateTopic": grpc.unary_unary_rpc_method_handler( - servicer.UpdateTopic, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.UpdateTopicRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.SerializeToString, - ), - "Publish": grpc.unary_unary_rpc_method_handler( - servicer.Publish, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PublishRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PublishResponse.SerializeToString, - ), - "GetTopic": grpc.unary_unary_rpc_method_handler( - servicer.GetTopic, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.GetTopicRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Topic.SerializeToString, - ), - "ListTopics": grpc.unary_unary_rpc_method_handler( - servicer.ListTopics, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicsRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicsResponse.SerializeToString, - ), - "ListTopicSubscriptions": grpc.unary_unary_rpc_method_handler( - servicer.ListTopicSubscriptions, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSubscriptionsRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSubscriptionsResponse.SerializeToString, - ), - "ListTopicSnapshots": grpc.unary_unary_rpc_method_handler( - servicer.ListTopicSnapshots, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSnapshotsRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListTopicSnapshotsResponse.SerializeToString, - ), - "DeleteTopic": grpc.unary_unary_rpc_method_handler( - servicer.DeleteTopic, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.DeleteTopicRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.pubsub.v1.Publisher", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) - - -class SubscriberStub(object): - """The service that an application uses to manipulate subscriptions and to - consume messages from a subscription via the `Pull` method or by - establishing a bi-directional stream using the `StreamingPull` method. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.CreateSubscription = channel.unary_unary( - "/google.pubsub.v1.Subscriber/CreateSubscription", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.FromString, - ) - self.GetSubscription = channel.unary_unary( - "/google.pubsub.v1.Subscriber/GetSubscription", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.GetSubscriptionRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.FromString, - ) - self.UpdateSubscription = channel.unary_unary( - "/google.pubsub.v1.Subscriber/UpdateSubscription", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.UpdateSubscriptionRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.FromString, - ) - self.ListSubscriptions = channel.unary_unary( - "/google.pubsub.v1.Subscriber/ListSubscriptions", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSubscriptionsRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSubscriptionsResponse.FromString, - ) - self.DeleteSubscription = channel.unary_unary( - "/google.pubsub.v1.Subscriber/DeleteSubscription", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.DeleteSubscriptionRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - self.ModifyAckDeadline = channel.unary_unary( - "/google.pubsub.v1.Subscriber/ModifyAckDeadline", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ModifyAckDeadlineRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - self.Acknowledge = channel.unary_unary( - "/google.pubsub.v1.Subscriber/Acknowledge", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.AcknowledgeRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - self.Pull = channel.unary_unary( - "/google.pubsub.v1.Subscriber/Pull", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PullRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PullResponse.FromString, - ) - self.StreamingPull = channel.stream_stream( - "/google.pubsub.v1.Subscriber/StreamingPull", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.StreamingPullRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.StreamingPullResponse.FromString, - ) - self.ModifyPushConfig = channel.unary_unary( - "/google.pubsub.v1.Subscriber/ModifyPushConfig", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ModifyPushConfigRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - self.GetSnapshot = channel.unary_unary( - "/google.pubsub.v1.Subscriber/GetSnapshot", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.GetSnapshotRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Snapshot.FromString, - ) - self.ListSnapshots = channel.unary_unary( - "/google.pubsub.v1.Subscriber/ListSnapshots", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSnapshotsRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSnapshotsResponse.FromString, - ) - self.CreateSnapshot = channel.unary_unary( - "/google.pubsub.v1.Subscriber/CreateSnapshot", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.CreateSnapshotRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Snapshot.FromString, - ) - self.UpdateSnapshot = channel.unary_unary( - "/google.pubsub.v1.Subscriber/UpdateSnapshot", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.UpdateSnapshotRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Snapshot.FromString, - ) - self.DeleteSnapshot = channel.unary_unary( - "/google.pubsub.v1.Subscriber/DeleteSnapshot", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.DeleteSnapshotRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, - ) - self.Seek = channel.unary_unary( - "/google.pubsub.v1.Subscriber/Seek", - request_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.SeekRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.SeekResponse.FromString, - ) - - -class SubscriberServicer(object): - """The service that an application uses to manipulate subscriptions and to - consume messages from a subscription via the `Pull` method or by - establishing a bi-directional stream using the `StreamingPull` method. - """ - - def CreateSubscription(self, request, context): - """Creates a subscription to a given topic. See the - - resource name rules. - If the subscription already exists, returns `ALREADY_EXISTS`. - If the corresponding topic doesn't exist, returns `NOT_FOUND`. - - If the name is not provided in the request, the server will assign a random - name for this subscription on the same project as the topic, conforming - to the - [resource name - format](https://cloud.google.com/pubsub/docs/admin#resource_names). The - generated name is populated in the returned Subscription object. Note that - for REST API requests, you must specify a name in the request. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetSubscription(self, request, context): - """Gets the configuration details of a subscription. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def UpdateSubscription(self, request, context): - """Updates an existing subscription. Note that certain properties of a - subscription, such as its topic, are not modifiable. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ListSubscriptions(self, request, context): - """Lists matching subscriptions. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def DeleteSubscription(self, request, context): - """Deletes an existing subscription. All messages retained in the subscription - are immediately dropped. Calls to `Pull` after deletion will return - `NOT_FOUND`. After a subscription is deleted, a new one may be created with - the same name, but the new one has no association with the old - subscription or its topic unless the same topic is specified. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ModifyAckDeadline(self, request, context): - """Modifies the ack deadline for a specific message. This method is useful - to indicate that more time is needed to process a message by the - subscriber, or to make the message available for redelivery if the - processing was interrupted. Note that this does not modify the - subscription-level `ackDeadlineSeconds` used for subsequent messages. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def Acknowledge(self, request, context): - """Acknowledges the messages associated with the `ack_ids` in the - `AcknowledgeRequest`. The Pub/Sub system can remove the relevant messages - from the subscription. - - Acknowledging a message whose ack deadline has expired may succeed, - but such a message may be redelivered later. Acknowledging a message more - than once will not result in an error. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def Pull(self, request, context): - """Pulls messages from the server. The server may return `UNAVAILABLE` if - there are too many concurrent pull requests pending for the given - subscription. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def StreamingPull(self, request_iterator, context): - """Establishes a stream with the server, which sends messages down to the - client. The client streams acknowledgements and ack deadline modifications - back to the server. The server will close the stream and return the status - on any error. The server may close the stream with status `UNAVAILABLE` to - reassign server-side resources, in which case, the client should - re-establish the stream. Flow control can be achieved by configuring the - underlying RPC channel. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ModifyPushConfig(self, request, context): - """Modifies the `PushConfig` for a specified subscription. - - This may be used to change a push subscription to a pull one (signified by - an empty `PushConfig`) or vice versa, or change the endpoint URL and other - attributes of a push subscription. Messages will accumulate for delivery - continuously through the call regardless of changes to the `PushConfig`. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetSnapshot(self, request, context): - """Gets the configuration details of a snapshot. Snapshots are used in - Seek - operations, which allow you to manage message acknowledgments in bulk. That - is, you can set the acknowledgment state of messages in an existing - subscription to the state captured by a snapshot. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ListSnapshots(self, request, context): - """Lists the existing snapshots. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def CreateSnapshot(self, request, context): - """Creates a snapshot from the requested subscription. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. -

If the snapshot already exists, returns `ALREADY_EXISTS`. - If the requested subscription doesn't exist, returns `NOT_FOUND`. - If the backlog in the subscription is too old -- and the resulting snapshot - would expire in less than 1 hour -- then `FAILED_PRECONDITION` is returned. - See also the `Snapshot.expire_time` field. If the name is not provided in - the request, the server will assign a random - name for this snapshot on the same project as the subscription, conforming - to the - [resource name - format](https://cloud.google.com/pubsub/docs/admin#resource_names). The - generated name is populated in the returned Snapshot object. Note that for - REST API requests, you must specify a name in the request. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def UpdateSnapshot(self, request, context): - """Updates an existing snapshot. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def DeleteSnapshot(self, request, context): - """Removes an existing snapshot. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot.

- When the snapshot is deleted, all messages retained in the snapshot - are immediately dropped. After a snapshot is deleted, a new one may be - created with the same name, but the new one has no association with the old - snapshot or its subscription, unless the same subscription is specified. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def Seek(self, request, context): - """Seeks an existing subscription to a point in time or to a given snapshot, - whichever is provided in the request. Snapshots are used in - Seek - operations, which allow - you to manage message acknowledgments in bulk. That is, you can set the - acknowledgment state of messages in an existing subscription to the state - captured by a snapshot. Note that both the subscription and the snapshot - must be on the same topic. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_SubscriberServicer_to_server(servicer, server): - rpc_method_handlers = { - "CreateSubscription": grpc.unary_unary_rpc_method_handler( - servicer.CreateSubscription, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.SerializeToString, - ), - "GetSubscription": grpc.unary_unary_rpc_method_handler( - servicer.GetSubscription, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.GetSubscriptionRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.SerializeToString, - ), - "UpdateSubscription": grpc.unary_unary_rpc_method_handler( - servicer.UpdateSubscription, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.UpdateSubscriptionRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Subscription.SerializeToString, - ), - "ListSubscriptions": grpc.unary_unary_rpc_method_handler( - servicer.ListSubscriptions, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSubscriptionsRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSubscriptionsResponse.SerializeToString, - ), - "DeleteSubscription": grpc.unary_unary_rpc_method_handler( - servicer.DeleteSubscription, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.DeleteSubscriptionRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - "ModifyAckDeadline": grpc.unary_unary_rpc_method_handler( - servicer.ModifyAckDeadline, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ModifyAckDeadlineRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - "Acknowledge": grpc.unary_unary_rpc_method_handler( - servicer.Acknowledge, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.AcknowledgeRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - "Pull": grpc.unary_unary_rpc_method_handler( - servicer.Pull, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PullRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.PullResponse.SerializeToString, - ), - "StreamingPull": grpc.stream_stream_rpc_method_handler( - servicer.StreamingPull, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.StreamingPullRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.StreamingPullResponse.SerializeToString, - ), - "ModifyPushConfig": grpc.unary_unary_rpc_method_handler( - servicer.ModifyPushConfig, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ModifyPushConfigRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - "GetSnapshot": grpc.unary_unary_rpc_method_handler( - servicer.GetSnapshot, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.GetSnapshotRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Snapshot.SerializeToString, - ), - "ListSnapshots": grpc.unary_unary_rpc_method_handler( - servicer.ListSnapshots, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSnapshotsRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.ListSnapshotsResponse.SerializeToString, - ), - "CreateSnapshot": grpc.unary_unary_rpc_method_handler( - servicer.CreateSnapshot, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.CreateSnapshotRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Snapshot.SerializeToString, - ), - "UpdateSnapshot": grpc.unary_unary_rpc_method_handler( - servicer.UpdateSnapshot, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.UpdateSnapshotRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.Snapshot.SerializeToString, - ), - "DeleteSnapshot": grpc.unary_unary_rpc_method_handler( - servicer.DeleteSnapshot, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.DeleteSnapshotRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, - ), - "Seek": grpc.unary_unary_rpc_method_handler( - servicer.Seek, - request_deserializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.SeekRequest.FromString, - response_serializer=google_dot_cloud_dot_pubsub__v1_dot_proto_dot_pubsub__pb2.SeekResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.pubsub.v1.Subscriber", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/pubsub/google/cloud/pubsub_v1/publisher/__init__.py b/pubsub/google/cloud/pubsub_v1/publisher/__init__.py deleted file mode 100644 index 688ee744b7b4..000000000000 --- a/pubsub/google/cloud/pubsub_v1/publisher/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.cloud.pubsub_v1.publisher.client import Client - - -__all__ = ("Client",) diff --git a/pubsub/google/cloud/pubsub_v1/publisher/_batch/__init__.py b/pubsub/google/cloud/pubsub_v1/publisher/_batch/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/pubsub/google/cloud/pubsub_v1/publisher/_batch/base.py b/pubsub/google/cloud/pubsub_v1/publisher/_batch/base.py deleted file mode 100644 index 75f430b09421..000000000000 --- a/pubsub/google/cloud/pubsub_v1/publisher/_batch/base.py +++ /dev/null @@ -1,169 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import abc - -import six - - -@six.add_metaclass(abc.ABCMeta) -class Batch(object): - """The base batching class for Pub/Sub publishing. - - Although the :class:`~.pubsub_v1.publisher.batch.thread.Batch` class, based - on :class:`threading.Thread`, is fine for most cases, advanced - users may need to implement something based on a different concurrency - model. - - This class defines the interface for the Batch implementation; - subclasses may be passed as the ``batch_class`` argument to - :class:`~.pubsub_v1.client.PublisherClient`. - - The batching behavior works like this: When the - :class:`~.pubsub_v1.publisher.client.Client` is asked to publish a new - message, it requires a batch. The client will see if there is an - already-opened batch for the given topic; if there is, then the message - is sent to that batch. If there is not, then a new batch is created - and the message put there. - - When a new batch is created, it automatically starts a timer counting - down to the maximum latency before the batch should commit. - Essentially, if enough time passes, the batch automatically commits - regardless of how much is in it. However, if either the message count or - size thresholds are encountered first, then the batch will commit early. - """ - - def __len__(self): - """Return the number of messages currently in the batch.""" - return len(self.messages) - - @staticmethod - @abc.abstractmethod - def make_lock(): - """Return a lock in the chosen concurrency model. - - Returns: - ContextManager: A newly created lock. - """ - raise NotImplementedError - - @property - @abc.abstractmethod - def messages(self): - """Return the messages currently in the batch. - - Returns: - Sequence: The messages currently in the batch. - """ - raise NotImplementedError - - @property - @abc.abstractmethod - def size(self): - """Return the total size of all of the messages currently in the batch. - - The size includes any overhead of the actual ``PublishRequest`` that is - sent to the backend. - - Returns: - int: The total size of all of the messages currently - in the batch (including the request overhead), in bytes. - """ - raise NotImplementedError - - @property - @abc.abstractmethod - def settings(self): - """Return the batch settings. - - Returns: - ~.pubsub_v1.types.BatchSettings: The batch settings. These are - considered immutable once the batch has been opened. - """ - raise NotImplementedError - - @property - @abc.abstractmethod - def status(self): - """Return the status of this batch. - - Returns: - str: The status of this batch. All statuses are human-readable, - all-lowercase strings. The ones represented in the - :class:`BaseBatch.Status` enum are special, but other statuses - are permitted. - """ - raise NotImplementedError - - def will_accept(self, message): - """Return True if the batch is able to accept the message. - - In concurrent implementations, the attributes on the current batch - may be modified by other workers. With this in mind, the caller will - likely want to hold a lock that will make sure the state remains - the same after the "will accept?" question is answered. - - Args: - message (~.pubsub_v1.types.PubsubMessage): The Pub/Sub message. - - Returns: - bool: Whether this batch can accept the message. - """ - # If this batch is not accepting messages generally, return False. - if self.status != BatchStatus.ACCEPTING_MESSAGES: - return False - - # If this message will make the batch exceed the ``max_messages`` - # setting, return False. - if len(self.messages) >= self.settings.max_messages: - return False - - # Okay, everything is good. - return True - - @abc.abstractmethod - def publish(self, message): - """Publish a single message. - - Add the given message to this object; this will cause it to be - published once the batch either has enough messages or a sufficient - period of time has elapsed. - - This method is called by :meth:`~.PublisherClient.publish`. - - Args: - message (~.pubsub_v1.types.PubsubMessage): The Pub/Sub message. - - Returns: - ~google.api_core.future.Future: An object conforming to the - :class:`concurrent.futures.Future` interface. - """ - raise NotImplementedError - - -class BatchStatus(object): - """An enum-like class representing valid statuses for a batch. - - It is acceptable for a class to use a status that is not on this - class; this represents the list of statuses where the existing - library hooks in functionality. - """ - - ACCEPTING_MESSAGES = "accepting messages" - STARTING = "starting" - IN_PROGRESS = "in progress" - ERROR = "error" - SUCCESS = "success" diff --git a/pubsub/google/cloud/pubsub_v1/publisher/_batch/thread.py b/pubsub/google/cloud/pubsub_v1/publisher/_batch/thread.py deleted file mode 100644 index 4101bc518b0a..000000000000 --- a/pubsub/google/cloud/pubsub_v1/publisher/_batch/thread.py +++ /dev/null @@ -1,339 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import logging -import threading -import time - -import six - -import google.api_core.exceptions -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.publisher import exceptions -from google.cloud.pubsub_v1.publisher import futures -from google.cloud.pubsub_v1.publisher._batch import base - - -_LOGGER = logging.getLogger(__name__) -_CAN_COMMIT = (base.BatchStatus.ACCEPTING_MESSAGES, base.BatchStatus.STARTING) -_SERVER_PUBLISH_MAX_BYTES = 10 * 1000 * 1000 # max accepted size of PublishRequest - - -class Batch(base.Batch): - """A batch of messages. - - The batch is the internal group of messages which are either awaiting - publication or currently in progress. - - A batch is automatically created by the PublisherClient when the first - message to be published is received; subsequent messages are added to - that batch until the process of actual publishing _starts_. - - Once this occurs, any new messages sent to :meth:`publish` open a new - batch. - - If you are using this library, you most likely do not need to instantiate - batch objects directly; they will be created for you. If you want to - change the actual batching settings, see the ``batching`` argument on - :class:`~.pubsub_v1.PublisherClient`. - - Any properties or methods on this class which are not defined in - :class:`~.pubsub_v1.publisher.batch.BaseBatch` should be considered - implementation details. - - Args: - client (~.pubsub_v1.PublisherClient): The publisher client used to - create this batch. - topic (str): The topic. The format for this is - ``projects/{project}/topics/{topic}``. - settings (~.pubsub_v1.types.BatchSettings): The settings for batch - publishing. These should be considered immutable once the batch - has been opened. - autocommit (bool): Whether to autocommit the batch when the time - has elapsed. Defaults to True unless ``settings.max_latency`` is - inf. - """ - - def __init__(self, client, topic, settings, autocommit=True): - self._client = client - self._topic = topic - self._settings = settings - - self._state_lock = threading.Lock() - # These members are all communicated between threads; ensure that - # any writes to them use the "state lock" to remain atomic. - # _futures list should remain unchanged after batch - # status changed from ACCEPTING_MESSAGES to any other - # in order to avoid race conditions - self._futures = [] - self._messages = [] - self._status = base.BatchStatus.ACCEPTING_MESSAGES - - # The initial size is not zero, we need to account for the size overhead - # of the PublishRequest message itself. - self._base_request_size = types.PublishRequest(topic=topic).ByteSize() - self._size = self._base_request_size - - # If max latency is specified, start a thread to monitor the batch and - # commit when the max latency is reached. - self._thread = None - if autocommit and self.settings.max_latency < float("inf"): - self._thread = threading.Thread( - name="Thread-MonitorBatchPublisher", target=self.monitor - ) - self._thread.start() - - @staticmethod - def make_lock(): - """Return a threading lock. - - Returns: - _thread.Lock: A newly created lock. - """ - return threading.Lock() - - @property - def client(self): - """~.pubsub_v1.client.PublisherClient: A publisher client.""" - return self._client - - @property - def messages(self): - """Sequence: The messages currently in the batch.""" - return self._messages - - @property - def settings(self): - """Return the batch settings. - - Returns: - ~.pubsub_v1.types.BatchSettings: The batch settings. These are - considered immutable once the batch has been opened. - """ - return self._settings - - @property - def size(self): - """Return the total size of all of the messages currently in the batch. - - The size includes any overhead of the actual ``PublishRequest`` that is - sent to the backend. - - Returns: - int: The total size of all of the messages currently - in the batch (including the request overhead), in bytes. - """ - return self._size - - @property - def status(self): - """Return the status of this batch. - - Returns: - str: The status of this batch. All statuses are human-readable, - all-lowercase strings. - """ - return self._status - - def commit(self): - """Actually publish all of the messages on the active batch. - - .. note:: - - This method is non-blocking. It opens a new thread, which calls - :meth:`_commit`, which does block. - - This synchronously sets the batch status to "starting", and then opens - a new thread, which handles actually sending the messages to Pub/Sub. - - If the current batch is **not** accepting messages, this method - does nothing. - """ - # Set the status to "starting" synchronously, to ensure that - # this batch will necessarily not accept new messages. - with self._state_lock: - if self._status == base.BatchStatus.ACCEPTING_MESSAGES: - self._status = base.BatchStatus.STARTING - else: - return - - # Start a new thread to actually handle the commit. - commit_thread = threading.Thread( - name="Thread-CommitBatchPublisher", target=self._commit - ) - commit_thread.start() - - def _commit(self): - """Actually publish all of the messages on the active batch. - - This moves the batch out from being the active batch to an in progress - batch on the publisher, and then the batch is discarded upon - completion. - - .. note:: - - This method blocks. The :meth:`commit` method is the non-blocking - version, which calls this one. - """ - with self._state_lock: - if self._status in _CAN_COMMIT: - self._status = base.BatchStatus.IN_PROGRESS - else: - # If, in the intervening period between when this method was - # called and now, the batch started to be committed, or - # completed a commit, then no-op at this point. - _LOGGER.debug("Batch is already in progress, exiting commit") - return - - # Once in the IN_PROGRESS state, no other thread can publish additional - # messages or initiate a commit (those operations become a no-op), thus - # it is safe to release the state lock here. Releasing the lock avoids - # blocking other threads in case api.publish() below takes a long time - # to complete. - # https://github.com/googleapis/google-cloud-python/issues/8036 - - # Sanity check: If there are no messages, no-op. - if not self._messages: - _LOGGER.debug("No messages to publish, exiting commit") - self._status = base.BatchStatus.SUCCESS - return - - # Begin the request to publish these messages. - # Log how long the underlying request takes. - start = time.time() - - try: - response = self._client.api.publish(self._topic, self._messages) - except google.api_core.exceptions.GoogleAPIError as exc: - # We failed to publish, set the exception on all futures and - # exit. - self._status = base.BatchStatus.ERROR - - for future in self._futures: - future.set_exception(exc) - - _LOGGER.exception("Failed to publish %s messages.", len(self._futures)) - return - - end = time.time() - _LOGGER.debug("gRPC Publish took %s seconds.", end - start) - - if len(response.message_ids) == len(self._futures): - # Iterate over the futures on the queue and return the response - # IDs. We are trusting that there is a 1:1 mapping, and raise - # an exception if not. - self._status = base.BatchStatus.SUCCESS - zip_iter = six.moves.zip(response.message_ids, self._futures) - for message_id, future in zip_iter: - future.set_result(message_id) - else: - # Sanity check: If the number of message IDs is not equal to - # the number of futures I have, then something went wrong. - self._status = base.BatchStatus.ERROR - exception = exceptions.PublishError( - "Some messages were not successfully published." - ) - - for future in self._futures: - future.set_exception(exception) - - _LOGGER.error( - "Only %s of %s messages were published.", - len(response.message_ids), - len(self._futures), - ) - - def monitor(self): - """Commit this batch after sufficient time has elapsed. - - This simply sleeps for ``self.settings.max_latency`` seconds, - and then calls commit unless the batch has already been committed. - """ - # NOTE: This blocks; it is up to the calling code to call it - # in a separate thread. - - # Sleep for however long we should be waiting. - time.sleep(self.settings.max_latency) - - _LOGGER.debug("Monitor is waking up") - return self._commit() - - def publish(self, message): - """Publish a single message. - - Add the given message to this object; this will cause it to be - published once the batch either has enough messages or a sufficient - period of time has elapsed. If the batch is full or the commit is - already in progress, the method does not do anything. - - This method is called by :meth:`~.PublisherClient.publish`. - - Args: - message (~.pubsub_v1.types.PubsubMessage): The Pub/Sub message. - - Returns: - Optional[~google.api_core.future.Future]: An object conforming to - the :class:`~concurrent.futures.Future` interface or :data:`None`. - If :data:`None` is returned, that signals that the batch cannot - accept a message. - - Raises: - pubsub_v1.publisher.exceptions.MessageTooLargeError: If publishing - the ``message`` would exceed the max size limit on the backend. - """ - # Coerce the type, just in case. - if not isinstance(message, types.PubsubMessage): - message = types.PubsubMessage(**message) - - future = None - - with self._state_lock: - if not self.will_accept(message): - return future - - size_increase = types.PublishRequest(messages=[message]).ByteSize() - - if (self._base_request_size + size_increase) > _SERVER_PUBLISH_MAX_BYTES: - err_msg = ( - "The message being published would produce too large a publish " - "request that would exceed the maximum allowed size on the " - "backend ({} bytes).".format(_SERVER_PUBLISH_MAX_BYTES) - ) - raise exceptions.MessageTooLargeError(err_msg) - - new_size = self._size + size_increase - new_count = len(self._messages) + 1 - - size_limit = min(self.settings.max_bytes, _SERVER_PUBLISH_MAX_BYTES) - overflow = new_size > size_limit or new_count >= self.settings.max_messages - - if not self._messages or not overflow: - - # Store the actual message in the batch's message queue. - self._messages.append(message) - self._size = new_size - - # Track the future on this batch (so that the result of the - # future can be set). - future = futures.Future(completed=threading.Event()) - self._futures.append(future) - - # Try to commit, but it must be **without** the lock held, since - # ``commit()`` will try to obtain the lock. - if overflow: - self.commit() - - return future diff --git a/pubsub/google/cloud/pubsub_v1/publisher/client.py b/pubsub/google/cloud/pubsub_v1/publisher/client.py deleted file mode 100644 index 60a03bb652ab..000000000000 --- a/pubsub/google/cloud/pubsub_v1/publisher/client.py +++ /dev/null @@ -1,308 +0,0 @@ -# Copyright 2019, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import copy -import os -import pkg_resources - -import grpc -import six - -from google.api_core import grpc_helpers -from google.oauth2 import service_account - -from google.cloud.pubsub_v1 import _gapic -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.gapic import publisher_client -from google.cloud.pubsub_v1.gapic.transports import publisher_grpc_transport -from google.cloud.pubsub_v1.publisher._batch import thread - - -__version__ = pkg_resources.get_distribution("google-cloud-pubsub").version - -_BLACKLISTED_METHODS = ( - "publish", - "from_service_account_file", - "from_service_account_json", -) - - -@_gapic.add_methods(publisher_client.PublisherClient, blacklist=_BLACKLISTED_METHODS) -class Client(object): - """A publisher client for Google Cloud Pub/Sub. - - This creates an object that is capable of publishing messages. - Generally, you can instantiate this client with no arguments, and you - get sensible defaults. - - Args: - batch_settings (~google.cloud.pubsub_v1.types.BatchSettings): The - settings for batch publishing. - kwargs (dict): Any additional arguments provided are sent as keyword - arguments to the underlying - :class:`~google.cloud.pubsub_v1.gapic.publisher_client.PublisherClient`. - Generally you should not need to set additional keyword - arguments. Optionally, publish retry settings can be set via - ``client_config`` where user-provided retry configurations are - applied to default retry settings. And regional endpoints can be - set via ``client_options`` that takes a single key-value pair that - defines the endpoint. - - Example: - - .. code-block:: python - - from google.cloud import pubsub_v1 - - publisher_client = pubsub_v1.PublisherClient( - # Optional - batch_settings = pubsub_v1.types.BatchSettings( - max_bytes=1024, # One kilobyte - max_latency=1, # One second - ), - - # Optional - client_config = { - "interfaces": { - "google.pubsub.v1.Publisher": { - "retry_params": { - "messaging": { - 'total_timeout_millis': 650000, # default: 600000 - } - } - } - } - }, - - # Optional - client_options = { - "api_endpoint": REGIONAL_ENDPOINT - } - ) - """ - - _batch_class = thread.Batch - - def __init__(self, batch_settings=(), **kwargs): - # Sanity check: Is our goal to use the emulator? - # If so, create a grpc insecure channel with the emulator host - # as the target. - if os.environ.get("PUBSUB_EMULATOR_HOST"): - kwargs["channel"] = grpc.insecure_channel( - target=os.environ.get("PUBSUB_EMULATOR_HOST") - ) - - # Use a custom channel. - # We need this in order to set appropriate default message size and - # keepalive options. - if "transport" not in kwargs: - channel = kwargs.pop("channel", None) - if channel is None: - channel = grpc_helpers.create_channel( - credentials=kwargs.pop("credentials", None), - target=self.target, - scopes=publisher_client.PublisherClient._DEFAULT_SCOPES, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - # cannot pass both 'channel' and 'credentials' - kwargs.pop("credentials", None) - transport = publisher_grpc_transport.PublisherGrpcTransport(channel=channel) - kwargs["transport"] = transport - - # Add the metrics headers, and instantiate the underlying GAPIC - # client. - self.api = publisher_client.PublisherClient(**kwargs) - self.batch_settings = types.BatchSettings(*batch_settings) - - # The batches on the publisher client are responsible for holding - # messages. One batch exists for each topic. - self._batch_lock = self._batch_class.make_lock() - self._batches = {} - self._is_stopped = False - - @classmethod - def from_service_account_file(cls, filename, batch_settings=(), **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - batch_settings (~google.cloud.pubsub_v1.types.BatchSettings): The - settings for batch publishing. - kwargs: Additional arguments to pass to the constructor. - - Returns: - A Publisher :class:`~google.cloud.pubsub_v1.publisher.client.Client` - instance that is the constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(batch_settings, **kwargs) - - from_service_account_json = from_service_account_file - - @property - def target(self): - """Return the target (where the API is). - - Returns: - str: The location of the API. - """ - return publisher_client.PublisherClient.SERVICE_ADDRESS - - def _batch(self, topic, create=False, autocommit=True): - """Return the current batch for the provided topic. - - This will create a new batch if ``create=True`` or if no batch - currently exists. - - Args: - topic (str): A string representing the topic. - create (bool): Whether to create a new batch. Defaults to - :data:`False`. If :data:`True`, this will create a new batch - even if one already exists. - autocommit (bool): Whether to autocommit this batch. This is - primarily useful for debugging and testing, since it allows - the caller to avoid some side effects that batch creation - might have (e.g. spawning a worker to publish a batch). - - Returns: - ~.pubsub_v1._batch.Batch: The batch object. - """ - # If there is no matching batch yet, then potentially create one - # and place it on the batches dictionary. - if not create: - batch = self._batches.get(topic) - if batch is None: - create = True - - if create: - batch = self._batch_class( - autocommit=autocommit, - client=self, - settings=self.batch_settings, - topic=topic, - ) - self._batches[topic] = batch - - return batch - - def publish(self, topic, data, **attrs): - """Publish a single message. - - .. note:: - Messages in Pub/Sub are blobs of bytes. They are *binary* data, - not text. You must send data as a bytestring - (``bytes`` in Python 3; ``str`` in Python 2), and this library - will raise an exception if you send a text string. - - The reason that this is so important (and why we do not try to - coerce for you) is because Pub/Sub is also platform independent - and there is no way to know how to decode messages properly on - the other side; therefore, encoding and decoding is a required - exercise for the developer. - - Add the given message to this object; this will cause it to be - published once the batch either has enough messages or a sufficient - period of time has elapsed. - - Example: - >>> from google.cloud import pubsub_v1 - >>> client = pubsub_v1.PublisherClient() - >>> topic = client.topic_path('[PROJECT]', '[TOPIC]') - >>> data = b'The rain in Wales falls mainly on the snails.' - >>> response = client.publish(topic, data, username='guido') - - Args: - topic (str): The topic to publish messages to. - data (bytes): A bytestring representing the message body. This - must be a bytestring. - attrs (Mapping[str, str]): A dictionary of attributes to be - sent as metadata. (These may be text strings or byte strings.) - - Returns: - A :class:`~google.cloud.pubsub_v1.publisher.futures.Future` - instance that conforms to Python Standard library's - :class:`~concurrent.futures.Future` interface (but not an - instance of that class). - - Raises: - RuntimeError: - If called after publisher has been stopped - by a `stop()` method call. - """ - # Sanity check: Is the data being sent as a bytestring? - # If it is literally anything else, complain loudly about it. - if not isinstance(data, six.binary_type): - raise TypeError( - "Data being published to Pub/Sub must be sent as a bytestring." - ) - - # Coerce all attributes to text strings. - for k, v in copy.copy(attrs).items(): - if isinstance(v, six.text_type): - continue - if isinstance(v, six.binary_type): - attrs[k] = v.decode("utf-8") - continue - raise TypeError( - "All attributes being published to Pub/Sub must " - "be sent as text strings." - ) - - # Create the Pub/Sub message object. - message = types.PubsubMessage(data=data, attributes=attrs) - - # Delegate the publishing to the batch. - with self._batch_lock: - if self._is_stopped: - raise RuntimeError("Cannot publish on a stopped publisher.") - - batch = self._batch(topic) - future = None - while future is None: - future = batch.publish(message) - if future is None: - batch = self._batch(topic, create=True) - - return future - - def stop(self): - """Immediately publish all outstanding messages. - - Asynchronously sends all outstanding messages and - prevents future calls to `publish()`. Method should - be invoked prior to deleting this `Client()` object - in order to ensure that no pending messages are lost. - - .. note:: - - This method is non-blocking. Use `Future()` objects - returned by `publish()` to make sure all publish - requests completed, either in success or error. - """ - with self._batch_lock: - if self._is_stopped: - raise RuntimeError("Cannot stop a publisher already stopped.") - - self._is_stopped = True - - for batch in self._batches.values(): - batch.commit() diff --git a/pubsub/google/cloud/pubsub_v1/publisher/exceptions.py b/pubsub/google/cloud/pubsub_v1/publisher/exceptions.py deleted file mode 100644 index be176bac2dba..000000000000 --- a/pubsub/google/cloud/pubsub_v1/publisher/exceptions.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.api_core.exceptions import GoogleAPICallError -from google.cloud.pubsub_v1.exceptions import TimeoutError - - -class PublishError(GoogleAPICallError): - pass - - -class MessageTooLargeError(ValueError): - """Attempt to publish a message that would exceed the server max size limit.""" - - -__all__ = ("MessageTooLargeError", "PublishError", "TimeoutError") diff --git a/pubsub/google/cloud/pubsub_v1/publisher/futures.py b/pubsub/google/cloud/pubsub_v1/publisher/futures.py deleted file mode 100644 index fa8a79998617..000000000000 --- a/pubsub/google/cloud/pubsub_v1/publisher/futures.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2019, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.cloud.pubsub_v1 import futures - - -class Future(futures.Future): - """This future object is returned from asychronous Pub/Sub publishing - calls. - - Calling :meth:`result` will resolve the future by returning the message - ID, unless an error occurs. - """ - - def result(self, timeout=None): - """Return the message ID or raise an exception. - - This blocks until the message has been published successfully and - returns the message ID unless an exception is raised. - - Args: - timeout (Union[int, float]): The number of seconds before this call - times out and raises TimeoutError. - - Returns: - str: The message ID. - - Raises: - concurrent.futures.TimeoutError: If the request times out. - Exception: For undefined exceptions in the underlying - call execution. - """ - # Attempt to get the exception if there is one. - # If there is not one, then we know everything worked, and we can - # return an appropriate value. - err = self.exception(timeout=timeout) - if err is None: - return self._result - raise err diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/__init__.py b/pubsub/google/cloud/pubsub_v1/subscriber/__init__.py deleted file mode 100644 index a444c3ea7571..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.cloud.pubsub_v1.subscriber.client import Client - - -__all__ = ("Client",) diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/__init__.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/dispatcher.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/dispatcher.py deleted file mode 100644 index b1d8429cba58..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/dispatcher.py +++ /dev/null @@ -1,197 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -from __future__ import division - -import collections -import itertools -import logging -import math -import threading - -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.subscriber._protocol import helper_threads -from google.cloud.pubsub_v1.subscriber._protocol import requests - - -_LOGGER = logging.getLogger(__name__) -_CALLBACK_WORKER_NAME = "Thread-CallbackRequestDispatcher" - - -_MAX_BATCH_SIZE = 100 -"""The maximum number of requests to process and dispatch at a time.""" - -_MAX_BATCH_LATENCY = 0.01 -"""The maximum amount of time in seconds to wait for additional request items -before processing the next batch of requests.""" - -_ACK_IDS_BATCH_SIZE = 2500 -"""The maximum number of ACK IDs to send in a single StreamingPullRequest. - -The backend imposes a maximum request size limit of 524288 bytes (512 KiB) per -acknowledge / modifyAckDeadline request. ACK IDs have a maximum size of 164 -bytes, thus we cannot send more than o 524288/176 ~= 2979 ACK IDs in a single -StreamingPullRequest message. - -Accounting for some overhead, we should thus only send a maximum of 2500 ACK -IDs at a time. -""" - - -class Dispatcher(object): - def __init__(self, manager, queue): - self._manager = manager - self._queue = queue - self._thread = None - self._operational_lock = threading.Lock() - - def start(self): - """Start a thread to dispatch requests queued up by callbacks. - Spawns a thread to run :meth:`dispatch_callback`. - """ - with self._operational_lock: - if self._thread is not None: - raise ValueError("Dispatcher is already running.") - - worker = helper_threads.QueueCallbackWorker( - self._queue, - self.dispatch_callback, - max_items=_MAX_BATCH_SIZE, - max_latency=_MAX_BATCH_LATENCY, - ) - # Create and start the helper thread. - thread = threading.Thread(name=_CALLBACK_WORKER_NAME, target=worker) - thread.daemon = True - thread.start() - _LOGGER.debug("Started helper thread %s", thread.name) - self._thread = thread - - def stop(self): - with self._operational_lock: - if self._thread is not None: - # Signal the worker to stop by queueing a "poison pill" - self._queue.put(helper_threads.STOP) - self._thread.join() - - self._thread = None - - def dispatch_callback(self, items): - """Map the callback request to the appropriate gRPC request. - - Args: - action (str): The method to be invoked. - kwargs (Dict[str, Any]): The keyword arguments for the method - specified by ``action``. - - Raises: - ValueError: If ``action`` isn't one of the expected actions - "ack", "drop", "lease", "modify_ack_deadline" or "nack". - """ - if not self._manager.is_active: - return - - batched_commands = collections.defaultdict(list) - - for item in items: - batched_commands[item.__class__].append(item) - - _LOGGER.debug("Handling %d batched requests", len(items)) - - if batched_commands[requests.LeaseRequest]: - self.lease(batched_commands.pop(requests.LeaseRequest)) - if batched_commands[requests.ModAckRequest]: - self.modify_ack_deadline(batched_commands.pop(requests.ModAckRequest)) - # Note: Drop and ack *must* be after lease. It's possible to get both - # the lease the and ack/drop request in the same batch. - if batched_commands[requests.AckRequest]: - self.ack(batched_commands.pop(requests.AckRequest)) - if batched_commands[requests.NackRequest]: - self.nack(batched_commands.pop(requests.NackRequest)) - if batched_commands[requests.DropRequest]: - self.drop(batched_commands.pop(requests.DropRequest)) - - def ack(self, items): - """Acknowledge the given messages. - - Args: - items(Sequence[AckRequest]): The items to acknowledge. - """ - # If we got timing information, add it to the histogram. - for item in items: - time_to_ack = item.time_to_ack - if time_to_ack is not None: - self._manager.ack_histogram.add(time_to_ack) - - # We must potentially split the request into multiple smaller requests - # to avoid the server-side max request size limit. - ack_ids = (item.ack_id for item in items) - total_chunks = int(math.ceil(len(items) / _ACK_IDS_BATCH_SIZE)) - - for _ in range(total_chunks): - request = types.StreamingPullRequest( - ack_ids=itertools.islice(ack_ids, _ACK_IDS_BATCH_SIZE) - ) - self._manager.send(request) - - # Remove the message from lease management. - self.drop(items) - - def drop(self, items): - """Remove the given messages from lease management. - - Args: - items(Sequence[DropRequest]): The items to drop. - """ - self._manager.leaser.remove(items) - self._manager.maybe_resume_consumer() - - def lease(self, items): - """Add the given messages to lease management. - - Args: - items(Sequence[LeaseRequest]): The items to lease. - """ - self._manager.leaser.add(items) - self._manager.maybe_pause_consumer() - - def modify_ack_deadline(self, items): - """Modify the ack deadline for the given messages. - - Args: - items(Sequence[ModAckRequest]): The items to modify. - """ - # We must potentially split the request into multiple smaller requests - # to avoid the server-side max request size limit. - ack_ids = (item.ack_id for item in items) - seconds = (item.seconds for item in items) - total_chunks = int(math.ceil(len(items) / _ACK_IDS_BATCH_SIZE)) - - for _ in range(total_chunks): - request = types.StreamingPullRequest( - modify_deadline_ack_ids=itertools.islice(ack_ids, _ACK_IDS_BATCH_SIZE), - modify_deadline_seconds=itertools.islice(seconds, _ACK_IDS_BATCH_SIZE), - ) - self._manager.send(request) - - def nack(self, items): - """Explicitly deny receipt of messages. - - Args: - items(Sequence[NackRequest]): The items to deny. - """ - self.modify_ack_deadline( - [requests.ModAckRequest(ack_id=item.ack_id, seconds=0) for item in items] - ) - self.drop([requests.DropRequest(*item) for item in items]) diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/heartbeater.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/heartbeater.py deleted file mode 100644 index 9cd84a1e2397..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/heartbeater.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2018, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import logging -import threading - - -_LOGGER = logging.getLogger(__name__) -_HEARTBEAT_WORKER_NAME = "Thread-Heartbeater" -# How often to send heartbeats in seconds. Determined as half the period of -# time where the Pub/Sub server will close the stream as inactive, which is -# 60 seconds. -_DEFAULT_PERIOD = 30 - - -class Heartbeater(object): - def __init__(self, manager, period=_DEFAULT_PERIOD): - self._thread = None - self._operational_lock = threading.Lock() - self._manager = manager - self._stop_event = threading.Event() - self._period = period - - def heartbeat(self): - """Periodically send heartbeats.""" - while self._manager.is_active and not self._stop_event.is_set(): - self._manager.heartbeat() - _LOGGER.debug("Sent heartbeat.") - self._stop_event.wait(timeout=self._period) - - _LOGGER.info("%s exiting.", _HEARTBEAT_WORKER_NAME) - - def start(self): - with self._operational_lock: - if self._thread is not None: - raise ValueError("Heartbeater is already running.") - - # Create and start the helper thread. - self._stop_event.clear() - thread = threading.Thread( - name=_HEARTBEAT_WORKER_NAME, target=self.heartbeat - ) - thread.daemon = True - thread.start() - _LOGGER.debug("Started helper thread %s", thread.name) - self._thread = thread - - def stop(self): - with self._operational_lock: - self._stop_event.set() - - if self._thread is not None: - # The thread should automatically exit when the consumer is - # inactive. - self._thread.join() - - self._thread = None diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/helper_threads.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/helper_threads.py deleted file mode 100644 index 80ad58738cd1..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/helper_threads.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import time -import uuid - -from six.moves import queue - - -__all__ = ("QueueCallbackWorker", "STOP") - -_LOGGER = logging.getLogger(__name__) - - -# Helper thread stop indicator. This could be a sentinel object or None, -# but the sentinel object's ID can change if the process is forked, and -# None has the possibility of a user accidentally killing the helper -# thread. -STOP = uuid.uuid4() - - -def _get_many(queue_, max_items=None, max_latency=0): - """Get multiple items from a Queue. - - Gets at least one (blocking) and at most ``max_items`` items - (non-blocking) from a given Queue. Does not mark the items as done. - - Args: - queue_ (~queue.Queue`): The Queue to get items from. - max_items (int): The maximum number of items to get. If ``None``, then - all available items in the queue are returned. - max_latency (float): The maximum number of seconds to wait for more - than one item from a queue. This number includes the time required - to retrieve the first item. - - Returns: - Sequence[Any]: A sequence of items retrieved from the queue. - """ - start = time.time() - # Always return at least one item. - items = [queue_.get()] - while max_items is None or len(items) < max_items: - try: - elapsed = time.time() - start - timeout = max(0, max_latency - elapsed) - items.append(queue_.get(timeout=timeout)) - except queue.Empty: - break - return items - - -class QueueCallbackWorker(object): - """A helper that executes a callback for items sent in a queue. - - Calls a blocking ``get()`` on the ``queue`` until it encounters - :attr:`STOP`. - - Args: - queue (~queue.Queue): A Queue instance, appropriate for crossing the - concurrency boundary implemented by ``executor``. Items will - be popped off (with a blocking ``get()``) until :attr:`STOP` - is encountered. - callback (Callable[Sequence[Any], Any]): A callback that can process - items pulled off of the queue. Multiple items will be passed to - the callback in batches. - max_items (int): The maximum amount of items that will be passed to the - callback at a time. - max_latency (float): The maximum amount of time in seconds to wait for - additional items before executing the callback. - """ - - def __init__(self, queue, callback, max_items=100, max_latency=0): - self.queue = queue - self._callback = callback - self.max_items = max_items - self.max_latency = max_latency - - def __call__(self): - continue_ = True - while continue_: - items = _get_many( - self.queue, max_items=self.max_items, max_latency=self.max_latency - ) - - # If stop is in the items, process all items up to STOP and then - # exit. - try: - items = items[: items.index(STOP)] - continue_ = False - except ValueError: - pass - - # Run the callback. If any exceptions occur, log them and - # continue. - try: - self._callback(items) - except Exception as exc: - _LOGGER.exception("Error in queue callback worker: %s", exc) - - _LOGGER.debug("Exiting the QueueCallbackWorker.") diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/histogram.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/histogram.py deleted file mode 100644 index 29ee6fc61685..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/histogram.py +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import, division - - -class Histogram(object): - """Representation of a single histogram. - - The purpose of this class is to store actual ack timing information - in order to predict how long to renew leases. - - The default implementation uses the 99th percentile of previous ack - times to implicitly lease messages; however, custom - :class:`~.pubsub_v1.subscriber._consumer.Consumer` subclasses - are free to use a different formula. - - The precision of data stored is to the nearest integer. Additionally, - values outside the range of ``10 <= x <= 600`` are stored as ``10`` or - ``600``, since these are the boundaries of leases in the actual API. - """ - - def __init__(self, data=None): - """Instantiate the histogram. - - Args: - data (Mapping[str, int]): The data strucure to be used to store - the underlying data. The default is an empty dictionary. - This can be set to a dictionary-like object if required - (for example, if a special object is needed for - concurrency reasons). - """ - # The data is stored as a dictionary, with the keys being the - # value being added and the values being the number of times that - # value was added to the dictionary. - # - # This is depending on the Python interpreter's implicit ordering - # of dictionaries, which is a bitwise sort by the key's ``hash()`` - # value. Because ``hash(int i) -> i`` and all of our keys are - # positive integers (negatives would be a problem because the sort - # is bitwise), we can rely on this. - if data is None: - data = {} - self._data = data - self._len = 0 - - def __len__(self): - """Return the total number of data points in this histogram. - - This is cached on a separate counter (rather than computing it using - ``sum([v for v in self._data.values()])``) to optimize lookup. - - Returns: - int: The total number of data points in this histogram. - """ - return self._len - - def __contains__(self, needle): - """Return True if needle is present in the histogram, False otherwise. - - Returns: - bool: True or False - """ - return needle in self._data - - def __repr__(self): - return "".format( - len=len(self), max=self.max, min=self.min - ) - - @property - def max(self): - """Return the maximum value in this histogram. - - If there are no values in the histogram at all, return 600. - - Returns: - int: The maximum value in the histogram. - """ - if len(self._data) == 0: - return 600 - return next(iter(reversed(sorted(self._data.keys())))) - - @property - def min(self): - """Return the minimum value in this histogram. - - If there are no values in the histogram at all, return 10. - - Returns: - int: The minimum value in the histogram. - """ - if len(self._data) == 0: - return 10 - return next(iter(sorted(self._data.keys()))) - - def add(self, value): - """Add the value to this histogram. - - Args: - value (int): The value. Values outside of ``10 <= x <= 600`` - will be raised to ``10`` or reduced to ``600``. - """ - # If the value is out of bounds, bring it in bounds. - value = int(value) - if value < 10: - value = 10 - if value > 600: - value = 600 - - # Add the value to the histogram's data dictionary. - self._data.setdefault(value, 0) - self._data[value] += 1 - self._len += 1 - - def percentile(self, percent): - """Return the value that is the Nth precentile in the histogram. - - Args: - percent (Union[int, float]): The precentile being sought. The - default consumer implementations use consistently use ``99``. - - Returns: - int: The value corresponding to the requested percentile. - """ - # Sanity check: Any value over 100 should become 100. - if percent >= 100: - percent = 100 - - # Determine the actual target number. - target = len(self) - len(self) * (percent / 100) - - # Iterate over the values in reverse, dropping the target by the - # number of times each value has been seen. When the target passes - # 0, return the value we are currently viewing. - for k in reversed(sorted(self._data.keys())): - target -= self._data[k] - if target < 0: - return k - - # The only way to get here is if there was no data. - # In this case, just return 10 seconds. - return 10 diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/leaser.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/leaser.py deleted file mode 100644 index 8a683e4e772d..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/leaser.py +++ /dev/null @@ -1,193 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import collections -import copy -import logging -import random -import threading -import time - -import six - -from google.cloud.pubsub_v1.subscriber._protocol import requests - - -_LOGGER = logging.getLogger(__name__) -_LEASE_WORKER_NAME = "Thread-LeaseMaintainer" - - -_LeasedMessage = collections.namedtuple("_LeasedMessage", ["added_time", "size"]) - - -class Leaser(object): - def __init__(self, manager): - self._thread = None - self._manager = manager - - # a lock used for start/stop operations, protecting the _thread attribute - self._operational_lock = threading.Lock() - - # A lock ensuring that add/remove operations are atomic and cannot be - # intertwined. Protects the _leased_messages and _bytes attributes. - self._add_remove_lock = threading.Lock() - - self._leased_messages = {} - """dict[str, float]: A mapping of ack IDs to the local time when the - ack ID was initially leased in seconds since the epoch.""" - self._bytes = 0 - """int: The total number of bytes consumed by leased messages.""" - - self._stop_event = threading.Event() - - @property - def message_count(self): - """int: The number of leased messages.""" - return len(self._leased_messages) - - @property - def ack_ids(self): - """Sequence[str]: The ack IDs of all leased messages.""" - return self._leased_messages.keys() - - @property - def bytes(self): - """int: The total size, in bytes, of all leased messages.""" - return self._bytes - - def add(self, items): - """Add messages to be managed by the leaser.""" - with self._add_remove_lock: - for item in items: - # Add the ack ID to the set of managed ack IDs, and increment - # the size counter. - if item.ack_id not in self._leased_messages: - self._leased_messages[item.ack_id] = _LeasedMessage( - added_time=time.time(), size=item.byte_size - ) - self._bytes += item.byte_size - else: - _LOGGER.debug("Message %s is already lease managed", item.ack_id) - - def remove(self, items): - """Remove messages from lease management.""" - with self._add_remove_lock: - # Remove the ack ID from lease management, and decrement the - # byte counter. - for item in items: - if self._leased_messages.pop(item.ack_id, None) is not None: - self._bytes -= item.byte_size - else: - _LOGGER.debug("Item %s was not managed.", item.ack_id) - - if self._bytes < 0: - _LOGGER.debug("Bytes was unexpectedly negative: %d", self._bytes) - self._bytes = 0 - - def maintain_leases(self): - """Maintain all of the leases being managed. - - This method modifies the ack deadline for all of the managed - ack IDs, then waits for most of that time (but with jitter), and - repeats. - """ - while self._manager.is_active and not self._stop_event.is_set(): - # Determine the appropriate duration for the lease. This is - # based off of how long previous messages have taken to ack, with - # a sensible default and within the ranges allowed by Pub/Sub. - p99 = self._manager.ack_histogram.percentile(99) - _LOGGER.debug("The current p99 value is %d seconds.", p99) - - # Make a copy of the leased messages. This is needed because it's - # possible for another thread to modify the dictionary while - # we're iterating over it. - leased_messages = copy.copy(self._leased_messages) - - # Drop any leases that are well beyond max lease time. This - # ensures that in the event of a badly behaving actor, we can - # drop messages and allow Pub/Sub to resend them. - cutoff = time.time() - self._manager.flow_control.max_lease_duration - to_drop = [ - requests.DropRequest(ack_id, item.size) - for ack_id, item in six.iteritems(leased_messages) - if item.added_time < cutoff - ] - - if to_drop: - _LOGGER.warning( - "Dropping %s items because they were leased too long.", len(to_drop) - ) - self._manager.dispatcher.drop(to_drop) - - # Remove dropped items from our copy of the leased messages (they - # have already been removed from the real one by - # self._manager.drop(), which calls self.remove()). - for item in to_drop: - leased_messages.pop(item.ack_id) - - # Create a streaming pull request. - # We do not actually call `modify_ack_deadline` over and over - # because it is more efficient to make a single request. - ack_ids = leased_messages.keys() - if ack_ids: - _LOGGER.debug("Renewing lease for %d ack IDs.", len(ack_ids)) - - # NOTE: This may not work as expected if ``consumer.active`` - # has changed since we checked it. An implementation - # without any sort of race condition would require a - # way for ``send_request`` to fail when the consumer - # is inactive. - self._manager.dispatcher.modify_ack_deadline( - [requests.ModAckRequest(ack_id, p99) for ack_id in ack_ids] - ) - - # Now wait an appropriate period of time and do this again. - # - # We determine the appropriate period of time based on a random - # period between 0 seconds and 90% of the lease. This use of - # jitter (http://bit.ly/2s2ekL7) helps decrease contention in cases - # where there are many clients. - snooze = random.uniform(0.0, p99 * 0.9) - _LOGGER.debug("Snoozing lease management for %f seconds.", snooze) - self._stop_event.wait(timeout=snooze) - - _LOGGER.info("%s exiting.", _LEASE_WORKER_NAME) - - def start(self): - with self._operational_lock: - if self._thread is not None: - raise ValueError("Leaser is already running.") - - # Create and start the helper thread. - self._stop_event.clear() - thread = threading.Thread( - name=_LEASE_WORKER_NAME, target=self.maintain_leases - ) - thread.daemon = True - thread.start() - _LOGGER.debug("Started helper thread %s", thread.name) - self._thread = thread - - def stop(self): - with self._operational_lock: - self._stop_event.set() - - if self._thread is not None: - # The thread should automatically exit when the consumer is - # inactive. - self._thread.join() - - self._thread = None diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/requests.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/requests.py deleted file mode 100644 index ac1df0af8eff..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/requests.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Base class for concurrency policy.""" - -from __future__ import absolute_import, division - -import collections - -# Namedtuples for management requests. Used by the Message class to communicate -# items of work back to the policy. -AckRequest = collections.namedtuple( - "AckRequest", ["ack_id", "byte_size", "time_to_ack"] -) - -DropRequest = collections.namedtuple("DropRequest", ["ack_id", "byte_size"]) - -LeaseRequest = collections.namedtuple("LeaseRequest", ["ack_id", "byte_size"]) - -ModAckRequest = collections.namedtuple("ModAckRequest", ["ack_id", "seconds"]) - -NackRequest = collections.namedtuple("NackRequest", ["ack_id", "byte_size"]) diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py b/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py deleted file mode 100644 index 26764b1a9101..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/_protocol/streaming_pull_manager.py +++ /dev/null @@ -1,659 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import division - -import collections -import functools -import logging -import threading - -import grpc -import six -from six.moves import queue - -from google.api_core import bidi -from google.api_core import exceptions -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.subscriber._protocol import dispatcher -from google.cloud.pubsub_v1.subscriber._protocol import heartbeater -from google.cloud.pubsub_v1.subscriber._protocol import histogram -from google.cloud.pubsub_v1.subscriber._protocol import leaser -from google.cloud.pubsub_v1.subscriber._protocol import requests -import google.cloud.pubsub_v1.subscriber.message -import google.cloud.pubsub_v1.subscriber.scheduler - -_LOGGER = logging.getLogger(__name__) -_RPC_ERROR_THREAD_NAME = "Thread-OnRpcTerminated" -_RETRYABLE_STREAM_ERRORS = ( - exceptions.DeadlineExceeded, - exceptions.ServiceUnavailable, - exceptions.InternalServerError, - exceptions.Unknown, - exceptions.GatewayTimeout, - exceptions.Aborted, -) -_TERMINATING_STREAM_ERRORS = (exceptions.Cancelled,) -_MAX_LOAD = 1.0 -"""The load threshold above which to pause the incoming message stream.""" - -_RESUME_THRESHOLD = 0.8 -"""The load threshold below which to resume the incoming message stream.""" - - -def _maybe_wrap_exception(exception): - """Wraps a gRPC exception class, if needed.""" - if isinstance(exception, grpc.RpcError): - return exceptions.from_grpc_error(exception) - return exception - - -def _wrap_callback_errors(callback, on_callback_error, message): - """Wraps a user callback so that if an exception occurs the message is - nacked. - - Args: - callback (Callable[None, Message]): The user callback. - message (~Message): The Pub/Sub message. - """ - try: - callback(message) - except Exception as exc: - # Note: the likelihood of this failing is extremely low. This just adds - # a message to a queue, so if this doesn't work the world is in an - # unrecoverable state and this thread should just bail. - _LOGGER.exception( - "Top-level exception occurred in callback while processing a message" - ) - message.nack() - on_callback_error(exc) - - -class StreamingPullManager(object): - """The streaming pull manager coordinates pulling messages from Pub/Sub, - leasing them, and scheduling them to be processed. - - Args: - client (~.pubsub_v1.subscriber.client): The subscriber client used - to create this instance. - subscription (str): The name of the subscription. The canonical - format for this is - ``projects/{project}/subscriptions/{subscription}``. - flow_control (~google.cloud.pubsub_v1.types.FlowControl): The flow - control settings. - scheduler (~google.cloud.pubsub_v1.scheduler.Scheduler): The scheduler - to use to process messages. If not provided, a thread pool-based - scheduler will be used. - """ - - _UNARY_REQUESTS = True - """If set to True, this class will make requests over a separate unary - RPC instead of over the streaming RPC.""" - - def __init__( - self, client, subscription, flow_control=types.FlowControl(), scheduler=None - ): - self._client = client - self._subscription = subscription - self._flow_control = flow_control - self._ack_histogram = histogram.Histogram() - self._last_histogram_size = 0 - self._ack_deadline = 10 - self._rpc = None - self._callback = None - self._closing = threading.Lock() - self._closed = False - self._close_callbacks = [] - - if scheduler is None: - self._scheduler = ( - google.cloud.pubsub_v1.subscriber.scheduler.ThreadScheduler() - ) - else: - self._scheduler = scheduler - - # A FIFO queue for the messages that have been received from the server, - # but not yet added to the lease management (and not sent to user callback), - # because the FlowControl limits have been hit. - self._messages_on_hold = queue.Queue() - - # the total number of bytes consumed by the messages currently on hold - self._on_hold_bytes = 0 - - # A lock ensuring that pausing / resuming the consumer are both atomic - # operations that cannot be executed concurrently. Needed for properly - # syncing these operations with the current leaser load. Additionally, - # the lock is used to protect modifications of internal data that - # affects the load computation, i.e. the count and size of the messages - # currently on hold. - self._pause_resume_lock = threading.Lock() - - # The threads created in ``.open()``. - self._dispatcher = None - self._leaser = None - self._consumer = None - self._heartbeater = None - - @property - def is_active(self): - """bool: True if this manager is actively streaming. - - Note that ``False`` does not indicate this is complete shut down, - just that it stopped getting new messages. - """ - return self._consumer is not None and self._consumer.is_active - - @property - def flow_control(self): - """google.cloud.pubsub_v1.types.FlowControl: The active flow control - settings.""" - return self._flow_control - - @property - def dispatcher(self): - """google.cloud.pubsub_v1.subscriber._protocol.dispatcher.Dispatcher: - The dispatcher helper. - """ - return self._dispatcher - - @property - def leaser(self): - """google.cloud.pubsub_v1.subscriber._protocol.leaser.Leaser: - The leaser helper. - """ - return self._leaser - - @property - def ack_histogram(self): - """google.cloud.pubsub_v1.subscriber._protocol.histogram.Histogram: - The histogram tracking time-to-acknowledge. - """ - return self._ack_histogram - - @property - def ack_deadline(self): - """Return the current ack deadline based on historical time-to-ack. - - This method is "sticky". It will only perform the computations to - check on the right ack deadline if the histogram has gained a - significant amount of new information. - - Returns: - int: The ack deadline. - """ - target = min([self._last_histogram_size * 2, self._last_histogram_size + 100]) - if len(self.ack_histogram) > target: - self._ack_deadline = self.ack_histogram.percentile(percent=99) - return self._ack_deadline - - @property - def load(self): - """Return the current load. - - The load is represented as a float, where 1.0 represents having - hit one of the flow control limits, and values between 0.0 and 1.0 - represent how close we are to them. (0.5 means we have exactly half - of what the flow control setting allows, for example.) - - There are (currently) two flow control settings; this property - computes how close the manager is to each of them, and returns - whichever value is higher. (It does not matter that we have lots of - running room on setting A if setting B is over.) - - Returns: - float: The load value. - """ - if self._leaser is None: - return 0.0 - - # Messages that are temporarily put on hold are not being delivered to - # user's callbacks, thus they should not contribute to the flow control - # load calculation. - # However, since these messages must still be lease-managed to avoid - # unnecessary ACK deadline expirations, their count and total size must - # be subtracted from the leaser's values. - return max( - [ - (self._leaser.message_count - self._messages_on_hold.qsize()) - / self._flow_control.max_messages, - (self._leaser.bytes - self._on_hold_bytes) - / self._flow_control.max_bytes, - ] - ) - - def add_close_callback(self, callback): - """Schedules a callable when the manager closes. - - Args: - callback (Callable): The method to call. - """ - self._close_callbacks.append(callback) - - def maybe_pause_consumer(self): - """Check the current load and pause the consumer if needed.""" - with self._pause_resume_lock: - if self.load >= _MAX_LOAD: - if self._consumer is not None and not self._consumer.is_paused: - _LOGGER.debug( - "Message backlog over load at %.2f, pausing.", self.load - ) - self._consumer.pause() - - def maybe_resume_consumer(self): - """Check the load and held messages and resume the consumer if needed. - - If there are messages held internally, release those messages before - resuming the consumer. That will avoid leaser overload. - """ - with self._pause_resume_lock: - # If we have been paused by flow control, check and see if we are - # back within our limits. - # - # In order to not thrash too much, require us to have passed below - # the resume threshold (80% by default) of each flow control setting - # before restarting. - if self._consumer is None or not self._consumer.is_paused: - return - - _LOGGER.debug("Current load: %.2f", self.load) - - # Before maybe resuming the background consumer, release any messages - # currently on hold, if the current load allows for it. - self._maybe_release_messages() - - if self.load < _RESUME_THRESHOLD: - _LOGGER.debug("Current load is %.2f, resuming consumer.", self.load) - self._consumer.resume() - else: - _LOGGER.debug("Did not resume, current load is %.2f.", self.load) - - def _maybe_release_messages(self): - """Release (some of) the held messages if the current load allows for it. - - The method tries to release as many messages as the current leaser load - would allow. Each released message is added to the lease management, - and the user callback is scheduled for it. - - If there are currently no messages on hold, or if the leaser is - already overloaded, this method is effectively a no-op. - - The method assumes the caller has acquired the ``_pause_resume_lock``. - """ - while True: - if self.load >= _MAX_LOAD: - break # already overloaded - - try: - msg = self._messages_on_hold.get_nowait() - except queue.Empty: - break - - self._on_hold_bytes -= msg.size - - if self._on_hold_bytes < 0: - _LOGGER.warning( - "On hold bytes was unexpectedly negative: %s", self._on_hold_bytes - ) - self._on_hold_bytes = 0 - - _LOGGER.debug( - "Released held message, scheduling callback for it, " - "still on hold %s (bytes %s).", - self._messages_on_hold.qsize(), - self._on_hold_bytes, - ) - self._scheduler.schedule(self._callback, msg) - - def _send_unary_request(self, request): - """Send a request using a separate unary request instead of over the - stream. - - Args: - request (types.StreamingPullRequest): The stream request to be - mapped into unary requests. - """ - if request.ack_ids: - self._client.acknowledge( - subscription=self._subscription, ack_ids=list(request.ack_ids) - ) - - if request.modify_deadline_ack_ids: - # Send ack_ids with the same deadline seconds together. - deadline_to_ack_ids = collections.defaultdict(list) - - for n, ack_id in enumerate(request.modify_deadline_ack_ids): - deadline = request.modify_deadline_seconds[n] - deadline_to_ack_ids[deadline].append(ack_id) - - for deadline, ack_ids in six.iteritems(deadline_to_ack_ids): - self._client.modify_ack_deadline( - subscription=self._subscription, - ack_ids=ack_ids, - ack_deadline_seconds=deadline, - ) - - _LOGGER.debug("Sent request(s) over unary RPC.") - - def send(self, request): - """Queue a request to be sent to the RPC. - - If a RetryError occurs, the manager shutdown is triggered, and the - error is re-raised. - """ - if self._UNARY_REQUESTS: - try: - self._send_unary_request(request) - except exceptions.GoogleAPICallError: - _LOGGER.debug( - "Exception while sending unary RPC. This is typically " - "non-fatal as stream requests are best-effort.", - exc_info=True, - ) - except exceptions.RetryError as exc: - _LOGGER.debug( - "RetryError while sending unary RPC. Waiting on a transient " - "error resolution for too long, will now trigger shutdown.", - exc_info=False, - ) - # The underlying channel has been suffering from a retryable error - # for too long, time to give up and shut the streaming pull down. - self._on_rpc_done(exc) - raise - - else: - self._rpc.send(request) - - def heartbeat(self): - """Sends an empty request over the streaming pull RPC. - - This always sends over the stream, regardless of if - ``self._UNARY_REQUESTS`` is set or not. - """ - if self._rpc is not None and self._rpc.is_active: - self._rpc.send(types.StreamingPullRequest()) - - def open(self, callback, on_callback_error): - """Begin consuming messages. - - Args: - callback (Callable[None, google.cloud.pubsub_v1.message.Message]): - A callback that will be called for each message received on the - stream. - on_callback_error (Callable[Exception]): - A callable that will be called if an exception is raised in - the provided `callback`. - """ - if self.is_active: - raise ValueError("This manager is already open.") - - if self._closed: - raise ValueError("This manager has been closed and can not be re-used.") - - self._callback = functools.partial( - _wrap_callback_errors, callback, on_callback_error - ) - - # Create the RPC - stream_ack_deadline_seconds = self.ack_histogram.percentile(99) - - get_initial_request = functools.partial( - self._get_initial_request, stream_ack_deadline_seconds - ) - self._rpc = bidi.ResumableBidiRpc( - start_rpc=self._client.api.streaming_pull, - initial_request=get_initial_request, - should_recover=self._should_recover, - should_terminate=self._should_terminate, - throttle_reopen=True, - ) - self._rpc.add_done_callback(self._on_rpc_done) - - _LOGGER.debug( - "Creating a stream, default ACK deadline set to {} seconds.".format( - stream_ack_deadline_seconds - ) - ) - - # Create references to threads - self._dispatcher = dispatcher.Dispatcher(self, self._scheduler.queue) - self._consumer = bidi.BackgroundConsumer(self._rpc, self._on_response) - self._leaser = leaser.Leaser(self) - self._heartbeater = heartbeater.Heartbeater(self) - - # Start the thread to pass the requests. - self._dispatcher.start() - - # Start consuming messages. - self._consumer.start() - - # Start the lease maintainer thread. - self._leaser.start() - - # Start the stream heartbeater thread. - self._heartbeater.start() - - def close(self, reason=None): - """Stop consuming messages and shutdown all helper threads. - - This method is idempotent. Additional calls will have no effect. - - Args: - reason (Any): The reason to close this. If None, this is considered - an "intentional" shutdown. This is passed to the callbacks - specified via :meth:`add_close_callback`. - """ - with self._closing: - if self._closed: - return - - # Stop consuming messages. - if self.is_active: - _LOGGER.debug("Stopping consumer.") - self._consumer.stop() - self._consumer = None - - # Shutdown all helper threads - _LOGGER.debug("Stopping scheduler.") - self._scheduler.shutdown() - self._scheduler = None - - # Leaser and dispatcher reference each other through the shared - # StreamingPullManager instance, i.e. "self", thus do not set their - # references to None until both have been shut down. - # - # NOTE: Even if the dispatcher operates on an inactive leaser using - # the latter's add() and remove() methods, these have no impact on - # the stopped leaser (the leaser is never again re-started). Ditto - # for the manager's maybe_resume_consumer() / maybe_pause_consumer(), - # because the consumer gets shut down first. - _LOGGER.debug("Stopping leaser.") - self._leaser.stop() - _LOGGER.debug("Stopping dispatcher.") - self._dispatcher.stop() - self._dispatcher = None - # dispatcher terminated, OK to dispose the leaser reference now - self._leaser = None - _LOGGER.debug("Stopping heartbeater.") - self._heartbeater.stop() - self._heartbeater = None - - self._rpc = None - self._closed = True - _LOGGER.debug("Finished stopping manager.") - - for callback in self._close_callbacks: - callback(self, reason) - - def _get_initial_request(self, stream_ack_deadline_seconds): - """Return the initial request for the RPC. - - This defines the initial request that must always be sent to Pub/Sub - immediately upon opening the subscription. - - Args: - stream_ack_deadline_seconds (int): - The default message acknowledge deadline for the stream. - - Returns: - google.cloud.pubsub_v1.types.StreamingPullRequest: A request - suitable for being the first request on the stream (and not - suitable for any other purpose). - """ - # Any ack IDs that are under lease management need to have their - # deadline extended immediately. - if self._leaser is not None: - # Explicitly copy the list, as it could be modified by another - # thread. - lease_ids = list(self._leaser.ack_ids) - else: - lease_ids = [] - - # Put the request together. - request = types.StreamingPullRequest( - modify_deadline_ack_ids=list(lease_ids), - modify_deadline_seconds=[self.ack_deadline] * len(lease_ids), - stream_ack_deadline_seconds=stream_ack_deadline_seconds, - subscription=self._subscription, - ) - - # Return the initial request. - return request - - def _on_response(self, response): - """Process all received Pub/Sub messages. - - For each message, send a modified acknowledgment request to the - server. This prevents expiration of the message due to buffering by - gRPC or proxy/firewall. This makes the server and client expiration - timer closer to each other thus preventing the message being - redelivered multiple times. - - After the messages have all had their ack deadline updated, execute - the callback for each message using the executor. - """ - if response is None: - _LOGGER.debug( - "Response callback invoked with None, likely due to a " - "transport shutdown." - ) - return - - _LOGGER.debug( - "Processing %s received message(s), currenty on hold %s (bytes %s).", - len(response.received_messages), - self._messages_on_hold.qsize(), - self._on_hold_bytes, - ) - - # Immediately (i.e. without waiting for the auto lease management) - # modack the messages we received, as this tells the server that we've - # received them. - items = [ - requests.ModAckRequest(message.ack_id, self._ack_histogram.percentile(99)) - for message in response.received_messages - ] - self._dispatcher.modify_ack_deadline(items) - - invoke_callbacks_for = [] - - for received_message in response.received_messages: - message = google.cloud.pubsub_v1.subscriber.message.Message( - received_message.message, - received_message.ack_id, - received_message.delivery_attempt, - self._scheduler.queue, - ) - # Making a decision based on the load, and modifying the data that - # affects the load -> needs a lock, as that state can be modified - # by different threads. - with self._pause_resume_lock: - if self.load < _MAX_LOAD: - invoke_callbacks_for.append(message) - else: - self._messages_on_hold.put(message) - self._on_hold_bytes += message.size - - req = requests.LeaseRequest(ack_id=message.ack_id, byte_size=message.size) - self.leaser.add([req]) - self.maybe_pause_consumer() - - _LOGGER.debug( - "Scheduling callbacks for %s new messages, new total on hold %s (bytes %s).", - len(invoke_callbacks_for), - self._messages_on_hold.qsize(), - self._on_hold_bytes, - ) - for msg in invoke_callbacks_for: - self._scheduler.schedule(self._callback, msg) - - def _should_recover(self, exception): - """Determine if an error on the RPC stream should be recovered. - - If the exception is one of the retryable exceptions, this will signal - to the consumer thread that it should "recover" from the failure. - - This will cause the stream to exit when it returns :data:`False`. - - Returns: - bool: Indicates if the caller should recover or shut down. - Will be :data:`True` if the ``exception`` is "acceptable", i.e. - in a list of retryable / idempotent exceptions. - """ - exception = _maybe_wrap_exception(exception) - # If this is in the list of idempotent exceptions, then we want to - # recover. - if isinstance(exception, _RETRYABLE_STREAM_ERRORS): - _LOGGER.info("Observed recoverable stream error %s", exception) - return True - _LOGGER.info("Observed non-recoverable stream error %s", exception) - return False - - def _should_terminate(self, exception): - """Determine if an error on the RPC stream should be terminated. - - If the exception is one of the terminating exceptions, this will signal - to the consumer thread that it should terminate. - - This will cause the stream to exit when it returns :data:`True`. - - Returns: - bool: Indicates if the caller should terminate or attempt recovery. - Will be :data:`True` if the ``exception`` is "acceptable", i.e. - in a list of terminating exceptions. - """ - exception = _maybe_wrap_exception(exception) - if isinstance(exception, _TERMINATING_STREAM_ERRORS): - _LOGGER.info("Observed terminating stream error %s", exception) - return True - _LOGGER.info("Observed non-terminating stream error %s", exception) - return False - - def _on_rpc_done(self, future): - """Triggered whenever the underlying RPC terminates without recovery. - - This is typically triggered from one of two threads: the background - consumer thread (when calling ``recv()`` produces a non-recoverable - error) or the grpc management thread (when cancelling the RPC). - - This method is *non-blocking*. It will start another thread to deal - with shutting everything down. This is to prevent blocking in the - background consumer and preventing it from being ``joined()``. - """ - _LOGGER.info("RPC termination has signaled streaming pull manager shutdown.") - future = _maybe_wrap_exception(future) - thread = threading.Thread( - name=_RPC_ERROR_THREAD_NAME, target=self.close, kwargs={"reason": future} - ) - thread.daemon = True - thread.start() diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/client.py b/pubsub/google/cloud/pubsub_v1/subscriber/client.py deleted file mode 100644 index b255fe4767ca..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/client.py +++ /dev/null @@ -1,230 +0,0 @@ -# Copyright 2019, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import os -import pkg_resources - -import grpc - -from google.api_core import grpc_helpers -from google.oauth2 import service_account - -from google.cloud.pubsub_v1 import _gapic -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.gapic import subscriber_client -from google.cloud.pubsub_v1.gapic.transports import subscriber_grpc_transport -from google.cloud.pubsub_v1.subscriber import futures -from google.cloud.pubsub_v1.subscriber._protocol import streaming_pull_manager - - -__version__ = pkg_resources.get_distribution("google-cloud-pubsub").version - -_BLACKLISTED_METHODS = ( - "publish", - "from_service_account_file", - "from_service_account_json", -) - - -@_gapic.add_methods(subscriber_client.SubscriberClient, blacklist=_BLACKLISTED_METHODS) -class Client(object): - """A subscriber client for Google Cloud Pub/Sub. - - This creates an object that is capable of subscribing to messages. - Generally, you can instantiate this client with no arguments, and you - get sensible defaults. - - Args: - kwargs (dict): Any additional arguments provided are sent as keyword - keyword arguments to the underlying - :class:`~google.cloud.pubsub_v1.gapic.subscriber_client.SubscriberClient`. - Generally you should not need to set additional keyword - arguments. Optionally, regional endpoints can be set via - ``client_options`` that takes a single key-value pair that - defines the endpoint. - - Example: - - .. code-block:: python - - from google.cloud import pubsub_v1 - - subscriber_client = pubsub_v1.SubscriberClient( - # Optional - client_options = { - "api_endpoint": REGIONAL_ENDPOINT - } - ) - """ - - def __init__(self, **kwargs): - # Sanity check: Is our goal to use the emulator? - # If so, create a grpc insecure channel with the emulator host - # as the target. - if os.environ.get("PUBSUB_EMULATOR_HOST"): - kwargs["channel"] = grpc.insecure_channel( - target=os.environ.get("PUBSUB_EMULATOR_HOST") - ) - - # Use a custom channel. - # We need this in order to set appropriate default message size and - # keepalive options. - if "transport" not in kwargs: - channel = kwargs.pop("channel", None) - if channel is None: - channel = grpc_helpers.create_channel( - credentials=kwargs.pop("credentials", None), - target=self.target, - scopes=subscriber_client.SubscriberClient._DEFAULT_SCOPES, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - "grpc.keepalive_time_ms": 30000, - }.items(), - ) - # cannot pass both 'channel' and 'credentials' - kwargs.pop("credentials", None) - transport = subscriber_grpc_transport.SubscriberGrpcTransport( - channel=channel - ) - kwargs["transport"] = transport - - # Add the metrics headers, and instantiate the underlying GAPIC - # client. - self._api = subscriber_client.SubscriberClient(**kwargs) - - @classmethod - def from_service_account_file(cls, filename, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - kwargs: Additional arguments to pass to the constructor. - - Returns: - A Subscriber :class:`~google.cloud.pubsub_v1.subscriber.client.Client` - instance that is the constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(**kwargs) - - from_service_account_json = from_service_account_file - - @property - def target(self): - """Return the target (where the API is). - - Returns: - str: The location of the API. - """ - return subscriber_client.SubscriberClient.SERVICE_ADDRESS - - @property - def api(self): - """The underlying gapic API client.""" - return self._api - - def subscribe(self, subscription, callback, flow_control=(), scheduler=None): - """Asynchronously start receiving messages on a given subscription. - - This method starts a background thread to begin pulling messages from - a Pub/Sub subscription and scheduling them to be processed using the - provided ``callback``. - - The ``callback`` will be called with an individual - :class:`google.cloud.pubsub_v1.subscriber.message.Message`. It is the - responsibility of the callback to either call ``ack()`` or ``nack()`` - on the message when it finished processing. If an exception occurs in - the callback during processing, the exception is logged and the message - is ``nack()`` ed. - - The ``flow_control`` argument can be used to control the rate of at - which messages are pulled. The settings are relatively conservative by - default to prevent "message hoarding" - a situation where the client - pulls a large number of messages but can not process them fast enough - leading it to "starve" other clients of messages. Increasing these - settings may lead to faster throughput for messages that do not take - a long time to process. - - This method starts the receiver in the background and returns a - *Future* representing its execution. Waiting on the future (calling - ``result()``) will block forever or until a non-recoverable error - is encountered (such as loss of network connectivity). Cancelling the - future will signal the process to shutdown gracefully and exit. - - .. note:: This uses Pub/Sub's *streaming pull* feature. This feature - properties that may be surprising. Please take a look at - https://cloud.google.com/pubsub/docs/pull#streamingpull for - more details on how streaming pull behaves compared to the - synchronous pull method. - - Example: - - .. code-block:: python - - from google.cloud import pubsub_v1 - - subscriber_client = pubsub_v1.SubscriberClient() - - # existing subscription - subscription = subscriber_client.subscription_path( - 'my-project-id', 'my-subscription') - - def callback(message): - print(message) - message.ack() - - future = subscriber_client.subscribe( - subscription, callback) - - try: - future.result() - except KeyboardInterrupt: - future.cancel() - - Args: - subscription (str): The name of the subscription. The - subscription should have already been created (for example, - by using :meth:`create_subscription`). - callback (Callable[~google.cloud.pubsub_v1.subscriber.message.Message]): - The callback function. This function receives the message as - its only argument and will be called from a different thread/ - process depending on the scheduling strategy. - flow_control (~google.cloud.pubsub_v1.types.FlowControl): The flow control - settings. Use this to prevent situations where you are - inundated with too many messages at once. - scheduler (~google.cloud.pubsub_v1.subscriber.scheduler.Scheduler): An optional - *scheduler* to use when executing the callback. This controls - how callbacks are executed concurrently. - - Returns: - A :class:`~google.cloud.pubsub_v1.subscriber.futures.StreamingPullFuture` - instance that can be used to manage the background stream. - """ - flow_control = types.FlowControl(*flow_control) - - manager = streaming_pull_manager.StreamingPullManager( - self, subscription, flow_control=flow_control, scheduler=scheduler - ) - - future = futures.StreamingPullFuture(manager) - - manager.open(callback=callback, on_callback_error=future.set_exception) - - return future diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/futures.py b/pubsub/google/cloud/pubsub_v1/subscriber/futures.py deleted file mode 100644 index 12504c18b5df..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/futures.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.cloud.pubsub_v1 import futures - - -class StreamingPullFuture(futures.Future): - """Represents a process that asynchronously performs streaming pull and - schedules messages to be processed. - - This future is resolved when the process is stopped (via :meth:`cancel`) or - if it encounters an unrecoverable error. Calling `.result()` will cause - the calling thread to block indefinitely. - """ - - def __init__(self, manager): - super(StreamingPullFuture, self).__init__() - self._manager = manager - self._manager.add_close_callback(self._on_close_callback) - self._cancelled = False - - def _on_close_callback(self, manager, result): - if result is None: - self.set_result(True) - else: - self.set_exception(result) - - def cancel(self): - """Stops pulling messages and shutdowns the background thread consuming - messages. - """ - self._cancelled = True - return self._manager.close() - - def cancelled(self): - """ - returns: - bool: ``True`` if the subscription has been cancelled. - """ - return self._cancelled diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/message.py b/pubsub/google/cloud/pubsub_v1/subscriber/message.py deleted file mode 100644 index 6dc7bc443b59..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/message.py +++ /dev/null @@ -1,257 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import datetime -import json -import math -import time - -from google.api_core import datetime_helpers -from google.cloud.pubsub_v1.subscriber._protocol import requests - - -_MESSAGE_REPR = """\ -Message {{ - data: {!r} - attributes: {} -}}""" - - -def _indent(lines, prefix=" "): - """Indent some text. - - Note that this is present as ``textwrap.indent``, but not in Python 2. - - Args: - lines (str): The newline delimited string to be indented. - prefix (Optional[str]): The prefix to indent each line with. Default - to two spaces. - - Returns: - str: The newly indented content. - """ - indented = [] - for line in lines.split("\n"): - indented.append(prefix + line) - return "\n".join(indented) - - -class Message(object): - """A representation of a single Pub/Sub message. - - The common way to interact with - :class:`~.pubsub_v1.subscriber.message.Message` objects is to receive - them in callbacks on subscriptions; most users should never have a need - to instantiate them by hand. (The exception to this is if you are - implementing a custom subclass to - :class:`~.pubsub_v1.subscriber._consumer.Consumer`.) - - Attributes: - message_id (str): The message ID. In general, you should not need - to use this directly. - data (bytes): The data in the message. Note that this will be a - :class:`bytes`, not a text string. - attributes (.ScalarMapContainer): The attributes sent along with the - message. See :attr:`attributes` for more information on this type. - publish_time (datetime): The time that this message was originally - published. - """ - - def __init__(self, message, ack_id, delivery_attempt, request_queue): - """Construct the Message. - - .. note:: - - This class should not be constructed directly; it is the - responsibility of :class:`BasePolicy` subclasses to do so. - - Args: - message (~.pubsub_v1.types.PubsubMessage): The message received - from Pub/Sub. - ack_id (str): The ack_id received from Pub/Sub. - delivery_attempt (int): The delivery attempt counter received - from Pub/Sub if a DeadLetterPolicy is set on the subscription, - and zero otherwise. - request_queue (queue.Queue): A queue provided by the policy that - can accept requests; the policy is responsible for handling - those requests. - """ - self._message = message - self._ack_id = ack_id - self._delivery_attempt = delivery_attempt if delivery_attempt > 0 else None - self._request_queue = request_queue - self.message_id = message.message_id - - # The instantiation time is the time that this message - # was received. Tracking this provides us a way to be smart about - # the default lease deadline. - self._received_timestamp = time.time() - - def __repr__(self): - # Get an abbreviated version of the data. - abbv_data = self._message.data - if len(abbv_data) > 50: - abbv_data = abbv_data[:50] + b"..." - - pretty_attrs = json.dumps( - dict(self.attributes), indent=2, separators=(",", ": "), sort_keys=True - ) - pretty_attrs = _indent(pretty_attrs) - # We don't actually want the first line indented. - pretty_attrs = pretty_attrs.lstrip() - return _MESSAGE_REPR.format(abbv_data, pretty_attrs) - - @property - def attributes(self): - """Return the attributes of the underlying Pub/Sub Message. - - .. warning:: - - A ``ScalarMapContainer`` behaves slightly differently than a - ``dict``. For a Pub / Sub message this is a ``string->string`` map. - When trying to access a value via ``map['key']``, if the key is - not in the map, then the default value for the string type will - be returned, which is an empty string. It may be more intuitive - to just cast the map to a ``dict`` or to one use ``map.get``. - - Returns: - .ScalarMapContainer: The message's attributes. This is a - ``dict``-like object provided by ``google.protobuf``. - """ - return self._message.attributes - - @property - def data(self): - """Return the data for the underlying Pub/Sub Message. - - Returns: - bytes: The message data. This is always a bytestring; if you - want a text string, call :meth:`bytes.decode`. - """ - return self._message.data - - @property - def publish_time(self): - """Return the time that the message was originally published. - - Returns: - datetime: The date and time that the message was published. - """ - timestamp = self._message.publish_time - delta = datetime.timedelta( - seconds=timestamp.seconds, microseconds=timestamp.nanos // 1000 - ) - return datetime_helpers._UTC_EPOCH + delta - - @property - def size(self): - """Return the size of the underlying message, in bytes.""" - return self._message.ByteSize() - - @property - def ack_id(self): - """str: the ID used to ack the message.""" - return self._ack_id - - @property - def delivery_attempt(self): - """The delivery attempt counter is 1 + (the sum of number of NACKs - and number of ack_deadline exceeds) for this message. It is set to None - if a DeadLetterPolicy is not set on the subscription. - - A NACK is any call to ModifyAckDeadline with a 0 deadline. An ack_deadline - exceeds event is whenever a message is not acknowledged within - ack_deadline. Note that ack_deadline is initially - Subscription.ackDeadlineSeconds, but may get extended automatically by - the client library. - - The first delivery of a given message will have this value as 1. The value - is calculated at best effort and is approximate. - - EXPERIMENTAL: This feature is part of a closed alpha release. This - API might be changed in backward-incompatible ways and is not recommended - for production use. It is not subject to any SLA or deprecation policy. - - Returns: - Optional[int]: The delivery attempt counter or None. - """ - return self._delivery_attempt - - def ack(self): - """Acknowledge the given message. - - Acknowledging a message in Pub/Sub means that you are done - with it, and it will not be delivered to this subscription again. - You should avoid acknowledging messages until you have - *finished* processing them, so that in the event of a failure, - you receive the message again. - - .. warning:: - Acks in Pub/Sub are best effort. You should always - ensure that your processing code is idempotent, as you may - receive any given message more than once. - """ - time_to_ack = math.ceil(time.time() - self._received_timestamp) - self._request_queue.put( - requests.AckRequest( - ack_id=self._ack_id, byte_size=self.size, time_to_ack=time_to_ack - ) - ) - - def drop(self): - """Release the message from lease management. - - This informs the policy to no longer hold on to the lease for this - message. Pub/Sub will re-deliver the message if it is not acknowledged - before the existing lease expires. - - .. warning:: - For most use cases, the only reason to drop a message from - lease management is on :meth:`ack` or :meth:`nack`; these methods - both call this one. You probably do not want to call this method - directly. - """ - self._request_queue.put( - requests.DropRequest(ack_id=self._ack_id, byte_size=self.size) - ) - - def modify_ack_deadline(self, seconds): - """Resets the deadline for acknowledgement. - - New deadline will be the given value of seconds from now. - - The default implementation handles this for you; you should not need - to manually deal with setting ack deadlines. The exception case is - if you are implementing your own custom subclass of - :class:`~.pubsub_v1.subcriber._consumer.Consumer`. - - Args: - seconds (int): The number of seconds to set the lease deadline - to. This should be between 0 and 600. Due to network latency, - values below 10 are advised against. - """ - self._request_queue.put( - requests.ModAckRequest(ack_id=self._ack_id, seconds=seconds) - ) - - def nack(self): - """Decline to acknowldge the given message. - - This will cause the message to be re-delivered to the subscription. - """ - self._request_queue.put( - requests.NackRequest(ack_id=self._ack_id, byte_size=self.size) - ) diff --git a/pubsub/google/cloud/pubsub_v1/subscriber/scheduler.py b/pubsub/google/cloud/pubsub_v1/subscriber/scheduler.py deleted file mode 100644 index 42674c824c64..000000000000 --- a/pubsub/google/cloud/pubsub_v1/subscriber/scheduler.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright 2018, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Schedulers provide means to *schedule* callbacks asynchronously. - -These are used by the subscriber to call the user-provided callback to process -each message. -""" - -import abc -import concurrent.futures -import sys - -import six -from six.moves import queue - - -@six.add_metaclass(abc.ABCMeta) -class Scheduler(object): - """Abstract base class for schedulers. - - Schedulers are used to schedule callbacks asynchronously. - """ - - @property - @abc.abstractmethod - def queue(self): - """Queue: A concurrency-safe queue specific to the underlying - concurrency implementation. - - This queue is used to send messages *back* to the scheduling actor. - """ - raise NotImplementedError - - @abc.abstractmethod - def schedule(self, callback, *args, **kwargs): - """Schedule the callback to be called asynchronously. - - Args: - callback (Callable): The function to call. - args: Positional arguments passed to the function. - kwargs: Key-word arguments passed to the function. - - Returns: - None - """ - raise NotImplementedError - - @abc.abstractmethod - def shutdown(self): - """Shuts down the scheduler and immediately end all pending callbacks. - """ - raise NotImplementedError - - -def _make_default_thread_pool_executor(): - # Python 2.7 and 3.6+ have the thread_name_prefix argument, which is useful - # for debugging. - executor_kwargs = {} - if sys.version_info[:2] == (2, 7) or sys.version_info >= (3, 6): - executor_kwargs["thread_name_prefix"] = "ThreadPoolExecutor-ThreadScheduler" - return concurrent.futures.ThreadPoolExecutor(max_workers=10, **executor_kwargs) - - -class ThreadScheduler(Scheduler): - """A thread pool-based scheduler. - - This scheduler is useful in typical I/O-bound message processing. - - Args: - executor(concurrent.futures.ThreadPoolExecutor): An optional executor - to use. If not specified, a default one will be created. - """ - - def __init__(self, executor=None): - self._queue = queue.Queue() - if executor is None: - self._executor = _make_default_thread_pool_executor() - else: - self._executor = executor - - @property - def queue(self): - """Queue: A thread-safe queue used for communication between callbacks - and the scheduling thread.""" - return self._queue - - def schedule(self, callback, *args, **kwargs): - """Schedule the callback to be called asynchronously in a thread pool. - - Args: - callback (Callable): The function to call. - args: Positional arguments passed to the function. - kwargs: Key-word arguments passed to the function. - - Returns: - None - """ - self._executor.submit(callback, *args, **kwargs) - - def shutdown(self): - """Shuts down the scheduler and immediately end all pending callbacks. - """ - # Drop all pending item from the executor. Without this, the executor - # will block until all pending items are complete, which is - # undesirable. - try: - while True: - self._executor._work_queue.get(block=False) - except queue.Empty: - pass - self._executor.shutdown() diff --git a/pubsub/google/cloud/pubsub_v1/types.py b/pubsub/google/cloud/pubsub_v1/types.py deleted file mode 100644 index 2d238b42f797..000000000000 --- a/pubsub/google/cloud/pubsub_v1/types.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import -import collections -import sys - -from google.api import http_pb2 -from google.iam.v1 import iam_policy_pb2 -from google.iam.v1 import policy_pb2 -from google.iam.v1.logging import audit_data_pb2 -from google.protobuf import descriptor_pb2 -from google.protobuf import duration_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 -from google.protobuf import timestamp_pb2 - -from google.api_core.protobuf_helpers import get_messages -from google.cloud.pubsub_v1.proto import pubsub_pb2 - - -# Define the default values for batching. -# -# This class is used when creating a publisher or subscriber client, and -# these settings can be altered to tweak Pub/Sub behavior. -# The defaults should be fine for most use cases. -BatchSettings = collections.namedtuple( - "BatchSettings", ["max_bytes", "max_latency", "max_messages"] -) -BatchSettings.__new__.__defaults__ = ( - 1 * 1000 * 1000, # max_bytes: 1 MB - 0.01, # max_latency: 10 ms - 100, # max_messages: 100 -) - -if sys.version_info >= (3, 5): - BatchSettings.__doc__ = "The settings for batch publishing the messages." - BatchSettings.max_bytes.__doc__ = ( - "The maximum total size of the messages to collect before automatically " - "publishing the batch, including any byte size overhead of the publish " - "request itself. The maximum value is bound by the server-side limit of " - "10_000_000 bytes." - ) - BatchSettings.max_latency.__doc__ = ( - "The maximum number of seconds to wait for additional messages before " - "automatically publishing the batch." - ) - BatchSettings.max_messages.__doc__ = ( - "The maximum number of messages to collect before automatically " - "publishing the batch." - ) - - -# Define the type class and default values for flow control settings. -# -# This class is used when creating a publisher or subscriber client, and -# these settings can be altered to tweak Pub/Sub behavior. -# The defaults should be fine for most use cases. -FlowControl = collections.namedtuple( - "FlowControl", ["max_bytes", "max_messages", "max_lease_duration"] -) -FlowControl.__new__.__defaults__ = ( - 100 * 1024 * 1024, # max_bytes: 100mb - 1000, # max_messages: 1000 - 1 * 60 * 60, # max_lease_duration: 1 hour. -) - -if sys.version_info >= (3, 5): - FlowControl.__doc__ = ( - "The settings for controlling the rate at which messages are pulled " - "with an asynchronous subscription." - ) - FlowControl.max_bytes.__doc__ = ( - "The maximum total size of received - but not yet processed - messages " - "before pausing the message stream." - ) - FlowControl.max_messages.__doc__ = ( - "The maximum number of received - but not yet processed - messages before " - "pausing the message stream." - ) - FlowControl.max_lease_duration.__doc__ = ( - "The maximum amount of time in seconds to hold a lease on a message " - "before dropping it from the lease management." - ) - - -_shared_modules = [ - http_pb2, - iam_policy_pb2, - policy_pb2, - audit_data_pb2, - descriptor_pb2, - duration_pb2, - empty_pb2, - field_mask_pb2, - timestamp_pb2, -] - -_local_modules = [pubsub_pb2] - - -names = ["BatchSettings", "FlowControl"] - - -for module in _shared_modules: - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) - -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.pubsub_v1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/pubsub/noxfile.py b/pubsub/noxfile.py deleted file mode 100644 index 7949a4e3925a..000000000000 --- a/pubsub/noxfile.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by synthtool. DO NOT EDIT! - -from __future__ import absolute_import -import os -import shutil - -import nox - - -LOCAL_DEPS = (os.path.join("..", "api_core"), os.path.join("..", "core")) -BLACK_VERSION = "black==19.3b0" -BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] - -if os.path.exists("samples"): - BLACK_PATHS.append("samples") - - -@nox.session(python="3.7") -def lint(session): - """Run linters. - - Returns a failure if the linters find linting errors or sufficiently - serious code quality issues. - """ - session.install("flake8", BLACK_VERSION, *LOCAL_DEPS) - session.run("black", "--check", *BLACK_PATHS) - session.run("flake8", "google", "tests") - - -@nox.session(python="3.6") -def blacken(session): - """Run black. - - Format code to uniform standard. - - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. - That run uses an image that doesn't have 3.6 installed. Before updating this - check the state of the `gcp_ubuntu_config` we use for that Kokoro run. - """ - session.install(BLACK_VERSION) - session.run("black", *BLACK_PATHS) - - -@nox.session(python="3.7") -def lint_setup_py(session): - """Verify that setup.py is valid (including RST check).""" - session.install("docutils", "pygments") - session.run("python", "setup.py", "check", "--restructuredtext", "--strict") - - -def default(session): - # Install all test dependencies, then install this package in-place. - session.install("mock", "pytest", "pytest-cov") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", ".") - - # Run py.test against the unit tests. - session.run( - "py.test", - "--quiet", - "--cov=google.cloud", - "--cov=tests.unit", - "--cov-append", - "--cov-config=.coveragerc", - "--cov-report=", - "--cov-fail-under=0", - os.path.join("tests", "unit"), - *session.posargs, - ) - - -@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"]) -def unit(session): - """Run the unit test suite.""" - default(session) - - -@nox.session(python=["2.7", "3.7"]) -def system(session): - """Run the system test suite.""" - system_test_path = os.path.join("tests", "system.py") - system_test_folder_path = os.path.join("tests", "system") - # Sanity check: Only run tests if the environment variable is set. - if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): - session.skip("Credentials must be set via environment variable") - - system_test_exists = os.path.exists(system_test_path) - system_test_folder_exists = os.path.exists(system_test_folder_path) - # Sanity check: only run tests if found. - if not system_test_exists and not system_test_folder_exists: - session.skip("System tests were not found") - - # Use pre-release gRPC for system tests. - session.install("--pre", "grpcio") - - # Install all test dependencies, then install this package into the - # virtualenv's dist-packages. - session.install("mock", "pytest") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", "../test_utils/") - session.install("-e", ".") - - # Run py.test against the system tests. - if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) - if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) - - -@nox.session(python="3.7") -def cover(session): - """Run the final coverage report. - - This outputs the coverage report aggregating coverage from the unit - test runs (not system test runs), and then erases coverage data. - """ - session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=100") - - session.run("coverage", "erase") - - -@nox.session(python="3.7") -def docs(session): - """Build the docs for this library.""" - - session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark") - - shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) - session.run( - "sphinx-build", - "-W", # warnings as errors - "-T", # show full traceback on exception - "-N", # no colors - "-b", - "html", - "-d", - os.path.join("docs", "_build", "doctrees", ""), - os.path.join("docs", ""), - os.path.join("docs", "_build", "html", ""), - ) diff --git a/pubsub/pylint.config.py b/pubsub/pylint.config.py deleted file mode 100644 index 625e52cc9bbb..000000000000 --- a/pubsub/pylint.config.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This module is used to configure gcp-devrel-py-tools run-pylint.""" - -import copy - -from gcp_devrel.tools import pylint - -# Library configuration - -# library_additions = {} -# Ignore generated code -library_replacements = copy.deepcopy(pylint.DEFAULT_LIBRARY_RC_REPLACEMENTS) -library_replacements['MASTER']['ignore'].append('gapic') -library_replacements['MASTER']['ignore'].append('proto') - -# Test configuration - -# test_additions = copy.deepcopy(library_additions) -# test_replacements = copy.deepcopy(library_replacements) diff --git a/pubsub/setup.cfg b/pubsub/setup.cfg deleted file mode 100644 index 3bd555500e37..000000000000 --- a/pubsub/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[bdist_wheel] -universal = 1 diff --git a/pubsub/setup.py b/pubsub/setup.py deleted file mode 100644 index 69f19b3db72e..000000000000 --- a/pubsub/setup.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import io -import os - -import setuptools - - -# Package metadata. - -name = "google-cloud-pubsub" -description = "Google Cloud Pub/Sub API client library" -version = "1.1.0" -# Should be one of: -# 'Development Status :: 3 - Alpha' -# 'Development Status :: 4 - Beta' -# 'Development Status :: 5 - Production/Stable' -release_status = "Development Status :: 5 - Production/Stable" -dependencies = [ - "google-api-core[grpc] >= 1.14.0, < 2.0.0dev", - "grpc-google-iam-v1 >= 0.12.3, < 0.13dev", - 'enum34; python_version < "3.4"', -] -extras = {} - - -# Setup boilerplate below this line. - -package_root = os.path.abspath(os.path.dirname(__file__)) - -readme_filename = os.path.join(package_root, "README.rst") -with io.open(readme_filename, encoding="utf-8") as readme_file: - readme = readme_file.read() - -# Only include packages under the 'google' namespace. Do not include tests, -# benchmarks, etc. -packages = [ - package for package in setuptools.find_packages() if package.startswith("google") -] - -# Determine which namespaces are needed. -namespaces = ["google"] -if "google.cloud" in packages: - namespaces.append("google.cloud") - - -setuptools.setup( - name=name, - version=version, - description=description, - long_description=readme, - author="Google LLC", - author_email="googleapis-packages@google.com", - license="Apache 2.0", - url="https://github.com/GoogleCloudPlatform/google-cloud-python", - classifiers=[ - release_status, - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Operating System :: OS Independent", - "Topic :: Internet", - ], - platforms="Posix; MacOS X; Windows", - packages=packages, - namespace_packages=namespaces, - install_requires=dependencies, - extras_require=extras, - python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*", - include_package_data=True, - zip_safe=False, -) diff --git a/pubsub/synth.metadata b/pubsub/synth.metadata deleted file mode 100644 index 48f9b92bf006..000000000000 --- a/pubsub/synth.metadata +++ /dev/null @@ -1,39 +0,0 @@ -{ - "updateTime": "2020-01-08T13:27:29.257325Z", - "sources": [ - { - "generator": { - "name": "artman", - "version": "0.43.0", - "dockerImage": "googleapis/artman@sha256:264654a37596a44b0668b8ce6ac41082d713f6ee150b3fc6425fa78cc64e4f20" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "08b488e0660c59842a7dee0e3e2b65d9e3a514a9", - "internalRef": "288625007" - } - }, - { - "template": { - "name": "python_library", - "origin": "synthtool.gcp", - "version": "2019.10.17" - } - } - ], - "destinations": [ - { - "client": { - "source": "googleapis", - "apiName": "pubsub", - "apiVersion": "v1", - "language": "python", - "generator": "gapic", - "config": "google/pubsub/artman_pubsub.yaml" - } - } - ] -} \ No newline at end of file diff --git a/pubsub/synth.py b/pubsub/synth.py deleted file mode 100644 index 88ac4a8d4f7e..000000000000 --- a/pubsub/synth.py +++ /dev/null @@ -1,195 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This script is used to synthesize generated parts of this library.""" - -import re -import textwrap - -import synthtool as s -from synthtool import gcp - -gapic = gcp.GAPICGenerator() -common = gcp.CommonTemplates() -version = "v1" - -# ---------------------------------------------------------------------------- -# Generate pubsub GAPIC layer -# ---------------------------------------------------------------------------- -library = gapic.py_library( - "pubsub", - version, - config_path="/google/pubsub/artman_pubsub.yaml", - include_protos=True, -) -s.move( - library, - excludes=[ - "docs/**/*", - "nox.py", - "README.rst", - "setup.py", - "google/cloud/pubsub_v1/__init__.py", - "google/cloud/pubsub_v1/types.py", - ], -) - -# Adjust tests to import the clients directly. -s.replace( - "tests/unit/gapic/v1/test_publisher_client_v1.py", - "from google.cloud import pubsub_v1", - "from google.cloud.pubsub_v1.gapic import publisher_client", -) - -s.replace( - "tests/unit/gapic/v1/test_publisher_client_v1.py", " pubsub_v1", " publisher_client" -) - -s.replace( - "tests/unit/gapic/v1/test_subscriber_client_v1.py", - "from google.cloud import pubsub_v1", - "from google.cloud.pubsub_v1.gapic import subscriber_client", -) - -s.replace( - "tests/unit/gapic/v1/test_subscriber_client_v1.py", - " pubsub_v1", - " subscriber_client", -) - -# DEFAULT SCOPES are being used. so let's force them in. -s.replace( - "google/cloud/pubsub_v1/gapic/*er_client.py", - "# The name of the interface for this client. This is the key used to", - """# The scopes needed to make gRPC calls to all of the methods defined in - # this service - _DEFAULT_SCOPES = ( - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/pubsub', ) - - \g<0>""", -) - -s.replace( - "google/cloud/pubsub_v1/gapic/publisher_client.py", - "import google.api_core.gapic_v1.method\n", - "\g<0>import google.api_core.path_template\n", -) - -# Doc strings are formatted poorly -s.replace( - "google/cloud/pubsub_v1/proto/pubsub_pb2.py", - 'DESCRIPTOR = _MESSAGESTORAGEPOLICY,\n\s+__module__.*\n\s+,\n\s+__doc__ = """', - "\g<0>A message storage policy.\n\n\n ", -) - -s.replace( - "google/cloud/pubsub_v1/gapic/subscriber_client.py", - "subscription \(str\): The subscription whose backlog .*\n(.*\n)+?" - "\s+Format is .*", - """subscription (str): The subscription whose backlog the snapshot retains. - Specifically, the created snapshot is guaranteed to retain: \\ - (a) The existing backlog on the subscription. More precisely, this is \\ - defined as the messages in the subscription's backlog that are \\ - unacknowledged upon the successful completion of the \\ - `CreateSnapshot` request; as well as: \\ - (b) Any messages published to the subscription's topic following the \\ - successful completion of the CreateSnapshot request. \\ - - Format is ``projects/{project}/subscriptions/{sub}``.""", -) - -s.replace( - "google/cloud/pubsub_v1/gapic/publisher_client.py", - "import functools\n", - "import collections\n" - "from copy import deepcopy\n\g<0>" -) - -s.replace( - "google/cloud/pubsub_v1/gapic/publisher_client.py", - "import pkg_resources\n", - "\g<0>import six\n" -) - -s.replace( - "google/cloud/pubsub_v1/gapic/publisher_client.py", - "class PublisherClient", - """# TODO: remove conditional import after Python 2 support is dropped -if six.PY2: - from collections import Mapping -else: - from collections.abc import Mapping - - -def _merge_dict(d1, d2): - # Modifies d1 in-place to take values from d2 - # if the nested keys from d2 are present in d1. - # https://stackoverflow.com/a/10704003/4488789 - for k, v2 in d2.items(): - v1 = d1.get(k) # returns None if v1 has no such key - if v1 is None: - raise Exception("{} is not recognized by client_config".format(k)) - if isinstance(v1, Mapping) and isinstance(v2, Mapping): - _merge_dict(v1, v2) - else: - d1[k] = v2 - return d1 - \n\n\g<0>""" -) - -s.replace( - "google/cloud/pubsub_v1/gapic/publisher_client.py", - "client_config \(dict\): DEPRECATED.", - "client_config (dict):" -) - -s.replace( - "google/cloud/pubsub_v1/gapic/publisher_client.py", - "# Raise deprecation warnings .*\n.*\n.*\n.*\n.*\n.*\n", - """default_client_config = deepcopy(publisher_client_config.config) - - if client_config is None: - client_config = default_client_config - else: - client_config = _merge_dict(default_client_config, client_config) - """ -) - -s.replace( - "google/cloud/pubsub_v1/gapic/publisher_client.py", - "~google.api_core.page_iterator.PageIterator", - "~google.api_core.page_iterator.GRPCIterator" -) - -s.replace( - "google/cloud/pubsub_v1/gapic/subscriber_client.py", - "~google.api_core.page_iterator.PageIterator", - "~google.api_core.page_iterator.GRPCIterator" -) - -# Temporary fixup for 'grpc-google-iam-vi 0.12.4' (before generation). -s.replace( - "google/cloud/pubsub_v1/gapic/transports/*_grpc_transport.py", - "from google.iam.v1 import iam_policy_pb2", - "from google.iam.v1 import iam_policy_pb2_grpc as iam_policy_pb2", -) - -# ---------------------------------------------------------------------------- -# Add templated files -# ---------------------------------------------------------------------------- -templated_files = gcp.CommonTemplates().py_library(unit_cov_level=97, cov_level=100) -s.move(templated_files) - -s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/pubsub/tests/system.py b/pubsub/tests/system.py deleted file mode 100644 index 65baaf016407..000000000000 --- a/pubsub/tests/system.py +++ /dev/null @@ -1,639 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import datetime -import itertools -import operator as op -import os -import threading -import time - -import mock -import pytest -import six - -import google.auth -from google.cloud import pubsub_v1 -from google.cloud.pubsub_v1 import exceptions -from google.cloud.pubsub_v1 import futures -from google.cloud.pubsub_v1 import types - - -from test_utils.system import unique_resource_id - - -@pytest.fixture(scope=u"module") -def project(): - _, default_project = google.auth.default() - yield default_project - - -@pytest.fixture(scope=u"module") -def publisher(): - yield pubsub_v1.PublisherClient() - - -@pytest.fixture(scope=u"module") -def subscriber(): - yield pubsub_v1.SubscriberClient() - - -@pytest.fixture -def topic_path(project, publisher): - topic_name = "t" + unique_resource_id("-") - yield publisher.topic_path(project, topic_name) - - -@pytest.fixture -def subscription_path(project, subscriber): - sub_name = "s" + unique_resource_id("-") - yield subscriber.subscription_path(project, sub_name) - - -@pytest.fixture -def cleanup(): - registry = [] - yield registry - - # Perform all clean up. - for to_call, argument in registry: - to_call(argument) - - -def test_publish_messages(publisher, topic_path, cleanup): - # Make sure the topic gets deleted. - cleanup.append((publisher.delete_topic, topic_path)) - - publisher.create_topic(topic_path) - - futures = [ - publisher.publish( - topic_path, b"The hail in Wales falls mainly on the snails.", num=str(i) - ) - for i in six.moves.range(500) - ] - - for future in futures: - result = future.result() - assert isinstance(result, six.string_types) - - -def test_publish_large_messages(publisher, topic_path, cleanup): - # Make sure the topic gets deleted. - cleanup.append((publisher.delete_topic, topic_path)) - - # Each message should be smaller than 10**7 bytes (the server side limit for - # PublishRequest), but all messages combined in a PublishRequest should - # slightly exceed that threshold to make sure the publish code handles these - # cases well. - # Mind that the total PublishRequest size must still be smaller than - # 10 * 1024 * 1024 bytes in order to not exceed the max request body size limit. - msg_data = b"x" * (2 * 10 ** 6) - - publisher.batch_settings = types.BatchSettings( - max_bytes=11 * 1000 * 1000, # more than the server limit of 10 ** 7 - max_latency=2.0, # so that autocommit happens after publishing all messages - max_messages=100, - ) - publisher.create_topic(topic_path) - - futures = [publisher.publish(topic_path, msg_data, num=str(i)) for i in range(5)] - - # If the publishing logic correctly split all messages into more than a - # single batch despite a high BatchSettings.max_bytes limit, there should - # be no "InvalidArgument: request_size is too large" error. - for future in futures: - result = future.result(timeout=10) - assert isinstance(result, six.string_types) # the message ID - - -def test_subscribe_to_messages( - publisher, topic_path, subscriber, subscription_path, cleanup -): - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # Create a topic. - publisher.create_topic(topic_path) - - # Subscribe to the topic. This must happen before the messages - # are published. - subscriber.create_subscription(subscription_path, topic_path) - - # Publish some messages. - futures = [ - publisher.publish(topic_path, b"Wooooo! The claaaaaw!", num=str(index)) - for index in six.moves.range(50) - ] - - # Make sure the publish completes. - for future in futures: - future.result() - - # Actually open the subscription and hold it open for a few seconds. - # The callback should process the message numbers to prove - # that we got everything at least once. - callback = AckCallback() - future = subscriber.subscribe(subscription_path, callback) - for second in six.moves.range(10): - time.sleep(1) - - # The callback should have fired at least fifty times, but it - # may take some time. - if callback.calls >= 50: - return - - # Okay, we took too long; fail out. - assert callback.calls >= 50 - - future.cancel() - - -def test_subscribe_to_messages_async_callbacks( - publisher, topic_path, subscriber, subscription_path, cleanup -): - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # Create a topic. - publisher.create_topic(topic_path) - - # Subscribe to the topic. This must happen before the messages - # are published. - subscriber.create_subscription(subscription_path, topic_path) - - # Publish some messages. - futures = [ - publisher.publish(topic_path, b"Wooooo! The claaaaaw!", num=str(index)) - for index in six.moves.range(2) - ] - - # Make sure the publish completes. - for future in futures: - future.result() - - # We want to make sure that the callback was called asynchronously. So - # track when each call happened and make sure below. - callback = TimesCallback(2) - - # Actually open the subscription and hold it open for a few seconds. - future = subscriber.subscribe(subscription_path, callback) - for second in six.moves.range(5): - time.sleep(4) - - # The callback should have fired at least two times, but it may - # take some time. - if callback.calls >= 2: - first, last = sorted(callback.call_times[:2]) - diff = last - first - # "Ensure" the first two callbacks were executed asynchronously - # (sequentially would have resulted in a difference of 2+ - # seconds). - assert diff.days == 0 - assert diff.seconds < callback.sleep_time - - # Okay, we took too long; fail out. - assert callback.calls >= 2 - - future.cancel() - - -def test_creating_subscriptions_with_non_default_settings( - publisher, subscriber, project, topic_path, subscription_path, cleanup -): - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # create a topic and a subscription, customize the latter's policy - publisher.create_topic(topic_path) - - msg_retention_duration = {"seconds": 911} - expiration_policy = {"ttl": {"seconds": 90210}} - new_subscription = subscriber.create_subscription( - subscription_path, - topic_path, - ack_deadline_seconds=30, - retain_acked_messages=True, - message_retention_duration=msg_retention_duration, - expiration_policy=expiration_policy, - ) - - # fetch the subscription and check its settings - project_path = subscriber.project_path(project) - subscriptions = subscriber.list_subscriptions(project_path) - - subscriptions = [sub for sub in subscriptions if sub.topic == topic_path] - assert len(subscriptions) == 1 - subscription = subscriptions[0] - - assert subscription == new_subscription - assert subscription.ack_deadline_seconds == 30 - assert subscription.retain_acked_messages - assert subscription.message_retention_duration.seconds == 911 - assert subscription.expiration_policy.ttl.seconds == 90210 - - -def test_listing_project_topics(publisher, project, cleanup): - topic_paths = [ - publisher.topic_path(project, "topic-{}".format(i) + unique_resource_id(".")) - for i in range(1, 4) - ] - for topic in topic_paths: - cleanup.append((publisher.delete_topic, topic)) - publisher.create_topic(topic) - - project_path = publisher.project_path(project) - project_topics = publisher.list_topics(project_path) - project_topics = set(t.name for t in project_topics) - - # there might be other topics in the project, thus do a "is subset" check - assert set(topic_paths) <= project_topics - - -def test_listing_project_subscriptions(publisher, subscriber, project, cleanup): - # create topics - topic_paths = [ - publisher.topic_path(project, "topic-1" + unique_resource_id(".")), - publisher.topic_path(project, "topic-2" + unique_resource_id(".")), - ] - for topic in topic_paths: - cleanup.append((publisher.delete_topic, topic)) - publisher.create_topic(topic) - - # create subscriptions - subscription_paths = [ - subscriber.subscription_path( - project, "sub-{}".format(i) + unique_resource_id(".") - ) - for i in range(1, 4) - ] - for i, subscription in enumerate(subscription_paths): - topic = topic_paths[i % 2] - cleanup.append((subscriber.delete_subscription, subscription)) - subscriber.create_subscription(subscription, topic) - - # retrieve subscriptions and check that the list matches the expected - project_path = subscriber.project_path(project) - subscriptions = subscriber.list_subscriptions(project_path) - subscriptions = set(s.name for s in subscriptions) - - # there might be other subscriptions in the project, thus do a "is subset" check - assert set(subscription_paths) <= subscriptions - - -def test_listing_topic_subscriptions(publisher, subscriber, project, cleanup): - # create topics - topic_paths = [ - publisher.topic_path(project, "topic-1" + unique_resource_id(".")), - publisher.topic_path(project, "topic-2" + unique_resource_id(".")), - ] - for topic in topic_paths: - cleanup.append((publisher.delete_topic, topic)) - publisher.create_topic(topic) - - # create subscriptions - subscription_paths = [ - subscriber.subscription_path( - project, "sub-{}".format(i) + unique_resource_id(".") - ) - for i in range(1, 4) - ] - for i, subscription in enumerate(subscription_paths): - topic = topic_paths[i % 2] - cleanup.append((subscriber.delete_subscription, subscription)) - subscriber.create_subscription(subscription, topic) - - # retrieve subscriptions and check that the list matches the expected - subscriptions = publisher.list_topic_subscriptions(topic_paths[0]) - subscriptions = set(subscriptions) - - assert subscriptions == {subscription_paths[0], subscription_paths[2]} - - -def test_managing_topic_iam_policy(publisher, topic_path, cleanup): - cleanup.append((publisher.delete_topic, topic_path)) - - # create a topic and customize its policy - publisher.create_topic(topic_path) - topic_policy = publisher.get_iam_policy(topic_path) - - topic_policy.bindings.add(role="roles/pubsub.editor", members=["domain:google.com"]) - topic_policy.bindings.add( - role="roles/pubsub.viewer", members=["group:cloud-logs@google.com"] - ) - new_policy = publisher.set_iam_policy(topic_path, topic_policy) - - # fetch the topic policy again and check its values - topic_policy = publisher.get_iam_policy(topic_path) - assert topic_policy.bindings == new_policy.bindings - assert len(topic_policy.bindings) == 2 - - bindings = sorted(topic_policy.bindings, key=op.attrgetter("role")) - assert bindings[0].role == "roles/pubsub.editor" - assert bindings[0].members == ["domain:google.com"] - - assert bindings[1].role == "roles/pubsub.viewer" - assert bindings[1].members == ["group:cloud-logs@google.com"] - - -def test_managing_subscription_iam_policy( - publisher, subscriber, topic_path, subscription_path, cleanup -): - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # create a topic and a subscription, customize the latter's policy - publisher.create_topic(topic_path) - subscriber.create_subscription(subscription_path, topic_path) - sub_policy = subscriber.get_iam_policy(subscription_path) - - sub_policy.bindings.add(role="roles/pubsub.editor", members=["domain:google.com"]) - sub_policy.bindings.add( - role="roles/pubsub.viewer", members=["group:cloud-logs@google.com"] - ) - new_policy = subscriber.set_iam_policy(subscription_path, sub_policy) - - # fetch the subscription policy again and check its values - sub_policy = subscriber.get_iam_policy(subscription_path) - assert sub_policy.bindings == new_policy.bindings - assert len(sub_policy.bindings) == 2 - - bindings = sorted(sub_policy.bindings, key=op.attrgetter("role")) - assert bindings[0].role == "roles/pubsub.editor" - assert bindings[0].members == ["domain:google.com"] - - assert bindings[1].role == "roles/pubsub.viewer" - assert bindings[1].members == ["group:cloud-logs@google.com"] - - -class TestStreamingPull(object): - def test_streaming_pull_callback_error_propagation( - self, publisher, topic_path, subscriber, subscription_path, cleanup - ): - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # create a topic and subscribe to it - publisher.create_topic(topic_path) - subscriber.create_subscription(subscription_path, topic_path) - - # publish a messages and wait until published - future = publisher.publish(topic_path, b"hello!") - future.result(timeout=30) - - # Now subscribe to the topic and verify that an error in the callback - # is propagated through the streaming pull future. - class CallbackError(Exception): - pass - - callback = mock.Mock(side_effect=CallbackError) - future = subscriber.subscribe(subscription_path, callback) - - with pytest.raises(CallbackError): - future.result(timeout=30) - - def test_streaming_pull_ack_deadline( - self, publisher, subscriber, project, topic_path, subscription_path, cleanup - ): - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # Create a topic and a subscription, then subscribe to the topic. This - # must happen before the messages are published. - publisher.create_topic(topic_path) - - # Subscribe to the topic. This must happen before the messages - # are published. - subscriber.create_subscription( - subscription_path, topic_path, ack_deadline_seconds=45 - ) - - # publish some messages and wait for completion - self._publish_messages(publisher, topic_path, batch_sizes=[2]) - - # subscribe to the topic - callback = StreamingPullCallback( - processing_time=13, # more than the default stream ACK deadline (10s) - resolve_at_msg_count=3, # one more than the published messages count - ) - flow_control = types.FlowControl(max_messages=1) - subscription_future = subscriber.subscribe( - subscription_path, callback, flow_control=flow_control - ) - - # We expect to process the first two messages in 2 * 13 seconds, and - # any duplicate message that is re-sent by the backend in additional - # 13 seconds, totalling 39 seconds (+ overhead) --> if there have been - # no duplicates in 60 seconds, we can reasonably assume that there - # won't be any. - try: - callback.done_future.result(timeout=60) - except exceptions.TimeoutError: - # future timed out, because we received no excessive messages - assert sorted(callback.seen_message_ids) == [1, 2] - else: - pytest.fail( - "Expected to receive 2 messages, but got at least {}.".format( - len(callback.seen_message_ids) - ) - ) - finally: - subscription_future.cancel() - - def test_streaming_pull_max_messages( - self, publisher, topic_path, subscriber, subscription_path, cleanup - ): - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # create a topic and subscribe to it - publisher.create_topic(topic_path) - subscriber.create_subscription(subscription_path, topic_path) - - batch_sizes = (7, 4, 8, 2, 10, 1, 3, 8, 6, 1) # total: 50 - self._publish_messages(publisher, topic_path, batch_sizes=batch_sizes) - - # now subscribe and do the main part, check for max pending messages - total_messages = sum(batch_sizes) - flow_control = types.FlowControl(max_messages=5) - callback = StreamingPullCallback( - processing_time=1, resolve_at_msg_count=total_messages - ) - - subscription_future = subscriber.subscribe( - subscription_path, callback, flow_control=flow_control - ) - - # Expected time to process all messages in ideal case: - # (total_messages / FlowControl.max_messages) * processing_time - # - # With total=50, max messages=5, and processing_time=1 this amounts to - # 10 seconds (+ overhead), thus a full minute should be more than enough - # for the processing to complete. If not, fail the test with a timeout. - try: - callback.done_future.result(timeout=60) - except exceptions.TimeoutError: - pytest.fail( - "Timeout: receiving/processing streamed messages took too long." - ) - - # The callback future gets resolved once total_messages have been processed, - # but we want to wait for just a little bit longer to possibly catch cases - # when the callback gets invoked *more* than total_messages times. - time.sleep(3) - - try: - # All messages should have been processed exactly once, and no more - # than max_messages simultaneously at any time. - assert callback.completed_calls == total_messages - assert sorted(callback.seen_message_ids) == list( - range(1, total_messages + 1) - ) - assert callback.max_pending_ack <= flow_control.max_messages - finally: - subscription_future.cancel() # trigger clean shutdown - - @pytest.mark.skipif( - "KOKORO_GFILE_DIR" not in os.environ, - reason="Requires Kokoro environment with a limited subscriber service account.", - ) - def test_streaming_pull_subscriber_permissions_sufficient( - self, publisher, topic_path, subscriber, subscription_path, cleanup - ): - - # Make sure the topic and subscription get deleted. - cleanup.append((publisher.delete_topic, topic_path)) - cleanup.append((subscriber.delete_subscription, subscription_path)) - - # create a topic and subscribe to it - publisher.create_topic(topic_path) - subscriber.create_subscription(subscription_path, topic_path) - - # A service account granting only the pubsub.subscriber role must be used. - filename = os.path.join( - os.environ["KOKORO_GFILE_DIR"], "pubsub-subscriber-service-account.json" - ) - streaming_pull_subscriber = type(subscriber).from_service_account_file(filename) - - # Subscribe to the topic, publish a message, and verify that subscriber - # successfully pulls and processes it. - callback = StreamingPullCallback(processing_time=0.01, resolve_at_msg_count=1) - future = streaming_pull_subscriber.subscribe(subscription_path, callback) - self._publish_messages(publisher, topic_path, batch_sizes=[1]) - - try: - callback.done_future.result(timeout=10) - except exceptions.TimeoutError: - pytest.fail( - "Timeout: receiving/processing streamed messages took too long." - ) - else: - assert 1 in callback.seen_message_ids - finally: - future.cancel() - - def _publish_messages(self, publisher, topic_path, batch_sizes): - """Publish ``count`` messages in batches and wait until completion.""" - publish_futures = [] - msg_counter = itertools.count(start=1) - - for batch_size in batch_sizes: - msg_batch = self._make_messages(count=batch_size) - for msg in msg_batch: - future = publisher.publish( - topic_path, msg, seq_num=str(next(msg_counter)) - ) - publish_futures.append(future) - time.sleep(0.1) - - # wait untill all messages have been successfully published - for future in publish_futures: - future.result(timeout=30) - - def _make_messages(self, count): - messages = [ - u"message {}/{}".format(i, count).encode("utf-8") - for i in range(1, count + 1) - ] - return messages - - -class AckCallback(object): - def __init__(self): - self.calls = 0 - self.lock = threading.Lock() - - def __call__(self, message): - message.ack() - # Only increment the number of calls **after** finishing. - with self.lock: - self.calls += 1 - - -class TimesCallback(object): - def __init__(self, sleep_time): - self.sleep_time = sleep_time - self.calls = 0 - self.call_times = [] - self.lock = threading.Lock() - - def __call__(self, message): - now = datetime.datetime.now() - time.sleep(self.sleep_time) - message.ack() - # Only increment the number of calls **after** finishing. - with self.lock: - # list.append() is thread-safe, but we still wait until - # ``calls`` is incremented to do it. - self.call_times.append(now) - self.calls += 1 - - -class StreamingPullCallback(object): - def __init__(self, processing_time, resolve_at_msg_count): - self._lock = threading.Lock() - self._processing_time = processing_time - self._pending_ack = 0 - self.max_pending_ack = 0 - self.completed_calls = 0 - self.seen_message_ids = [] - - self._resolve_at_msg_count = resolve_at_msg_count - self.done_future = futures.Future() - - def __call__(self, message): - with self._lock: - self._pending_ack += 1 - self.max_pending_ack = max(self.max_pending_ack, self._pending_ack) - self.seen_message_ids.append(int(message.attributes["seq_num"])) - - time.sleep(self._processing_time) - - with self._lock: - self._pending_ack -= 1 - message.ack() - self.completed_calls += 1 - - if self.completed_calls >= self._resolve_at_msg_count: - if not self.done_future.done(): - self.done_future.set_result(None) diff --git a/pubsub/tests/system/gapic/v1/test_system_publisher_v1.py b/pubsub/tests/system/gapic/v1/test_system_publisher_v1.py deleted file mode 100644 index 9c0d2b33ad11..000000000000 --- a/pubsub/tests/system/gapic/v1/test_system_publisher_v1.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import time - -from google.cloud import pubsub_v1 -from google.cloud.pubsub_v1.proto import pubsub_pb2 - - -class TestSystemPublisher(object): - def test_list_topics(self): - project_id = os.environ["PROJECT_ID"] - - client = pubsub_v1.PublisherClient() - project = client.project_path(project_id) - response = client.list_topics(project) diff --git a/pubsub/tests/unit/__init__.py b/pubsub/tests/unit/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/pubsub/tests/unit/gapic/v1/test_publisher_client_v1.py b/pubsub/tests/unit/gapic/v1/test_publisher_client_v1.py deleted file mode 100644 index 6c64cf5a9ba2..000000000000 --- a/pubsub/tests/unit/gapic/v1/test_publisher_client_v1.py +++ /dev/null @@ -1,478 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit tests.""" - -import mock -import pytest - -from google.cloud.pubsub_v1.gapic import publisher_client -from google.cloud.pubsub_v1.proto import pubsub_pb2 -from google.iam.v1 import iam_policy_pb2 -from google.iam.v1 import policy_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestPublisherClient(object): - def test_create_topic(self): - # Setup Expected Response - name_2 = "name2-1052831874" - kms_key_name = "kmsKeyName2094986649" - expected_response = {"name": name_2, "kms_key_name": kms_key_name} - expected_response = pubsub_pb2.Topic(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - name = client.topic_path("[PROJECT]", "[TOPIC]") - - response = client.create_topic(name) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.Topic(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_create_topic_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - name = client.topic_path("[PROJECT]", "[TOPIC]") - - with pytest.raises(CustomException): - client.create_topic(name) - - def test_update_topic(self): - # Setup Expected Response - name = "name3373707" - kms_key_name = "kmsKeyName2094986649" - expected_response = {"name": name, "kms_key_name": kms_key_name} - expected_response = pubsub_pb2.Topic(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - topic = {} - update_mask = {} - - response = client.update_topic(topic, update_mask) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.UpdateTopicRequest( - topic=topic, update_mask=update_mask - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_update_topic_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - topic = {} - update_mask = {} - - with pytest.raises(CustomException): - client.update_topic(topic, update_mask) - - def test_publish(self): - # Setup Expected Response - message_ids_element = "messageIdsElement-744837059" - message_ids = [message_ids_element] - expected_response = {"message_ids": message_ids} - expected_response = pubsub_pb2.PublishResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - data = b"-86" - messages_element = {"data": data} - messages = [messages_element] - - response = client.publish(topic, messages) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.PublishRequest(topic=topic, messages=messages) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_publish_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - data = b"-86" - messages_element = {"data": data} - messages = [messages_element] - - with pytest.raises(CustomException): - client.publish(topic, messages) - - def test_get_topic(self): - # Setup Expected Response - name = "name3373707" - kms_key_name = "kmsKeyName2094986649" - expected_response = {"name": name, "kms_key_name": kms_key_name} - expected_response = pubsub_pb2.Topic(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - response = client.get_topic(topic) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.GetTopicRequest(topic=topic) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_topic_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - with pytest.raises(CustomException): - client.get_topic(topic) - - def test_list_topics(self): - # Setup Expected Response - next_page_token = "" - topics_element = {} - topics = [topics_element] - expected_response = {"next_page_token": next_page_token, "topics": topics} - expected_response = pubsub_pb2.ListTopicsResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - project = client.project_path("[PROJECT]") - - paged_list_response = client.list_topics(project) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.topics[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.ListTopicsRequest(project=project) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_topics_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - project = client.project_path("[PROJECT]") - - paged_list_response = client.list_topics(project) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_list_topic_subscriptions(self): - # Setup Expected Response - next_page_token = "" - subscriptions_element = "subscriptionsElement1698708147" - subscriptions = [subscriptions_element] - expected_response = { - "next_page_token": next_page_token, - "subscriptions": subscriptions, - } - expected_response = pubsub_pb2.ListTopicSubscriptionsResponse( - **expected_response - ) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - paged_list_response = client.list_topic_subscriptions(topic) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.subscriptions[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.ListTopicSubscriptionsRequest(topic=topic) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_topic_subscriptions_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - paged_list_response = client.list_topic_subscriptions(topic) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_delete_topic(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - client.delete_topic(topic) - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.DeleteTopicRequest(topic=topic) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_delete_topic_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - with pytest.raises(CustomException): - client.delete_topic(topic) - - def test_set_iam_policy(self): - # Setup Expected Response - version = 351608024 - etag = b"21" - expected_response = {"version": version, "etag": etag} - expected_response = policy_pb2.Policy(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - resource = client.topic_path("[PROJECT]", "[TOPIC]") - policy = {} - - response = client.set_iam_policy(resource, policy) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.SetIamPolicyRequest( - resource=resource, policy=policy - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_set_iam_policy_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - resource = client.topic_path("[PROJECT]", "[TOPIC]") - policy = {} - - with pytest.raises(CustomException): - client.set_iam_policy(resource, policy) - - def test_get_iam_policy(self): - # Setup Expected Response - version = 351608024 - etag = b"21" - expected_response = {"version": version, "etag": etag} - expected_response = policy_pb2.Policy(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - resource = client.topic_path("[PROJECT]", "[TOPIC]") - - response = client.get_iam_policy(resource) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.GetIamPolicyRequest(resource=resource) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_iam_policy_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - resource = client.topic_path("[PROJECT]", "[TOPIC]") - - with pytest.raises(CustomException): - client.get_iam_policy(resource) - - def test_test_iam_permissions(self): - # Setup Expected Response - expected_response = {} - expected_response = iam_policy_pb2.TestIamPermissionsResponse( - **expected_response - ) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup Request - resource = client.topic_path("[PROJECT]", "[TOPIC]") - permissions = [] - - response = client.test_iam_permissions(resource, permissions) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, permissions=permissions - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_test_iam_permissions_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = publisher_client.PublisherClient() - - # Setup request - resource = client.topic_path("[PROJECT]", "[TOPIC]") - permissions = [] - - with pytest.raises(CustomException): - client.test_iam_permissions(resource, permissions) diff --git a/pubsub/tests/unit/gapic/v1/test_subscriber_client_v1.py b/pubsub/tests/unit/gapic/v1/test_subscriber_client_v1.py deleted file mode 100644 index b1d7f52fad5f..000000000000 --- a/pubsub/tests/unit/gapic/v1/test_subscriber_client_v1.py +++ /dev/null @@ -1,843 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit tests.""" - -import mock -import pytest - -from google.cloud.pubsub_v1.gapic import subscriber_client -from google.cloud.pubsub_v1.proto import pubsub_pb2 -from google.iam.v1 import iam_policy_pb2 -from google.iam.v1 import policy_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 -from google.protobuf import timestamp_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - def stream_stream( - self, method, request_serializer=None, response_deserializer=None - ): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestSubscriberClient(object): - def test_create_subscription(self): - # Setup Expected Response - name_2 = "name2-1052831874" - topic_2 = "topic2-1139259102" - ack_deadline_seconds = 2135351438 - retain_acked_messages = False - enable_message_ordering = True - expected_response = { - "name": name_2, - "topic": topic_2, - "ack_deadline_seconds": ack_deadline_seconds, - "retain_acked_messages": retain_acked_messages, - "enable_message_ordering": enable_message_ordering, - } - expected_response = pubsub_pb2.Subscription(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - name = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - response = client.create_subscription(name, topic) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.Subscription(name=name, topic=topic) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_create_subscription_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - name = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - topic = client.topic_path("[PROJECT]", "[TOPIC]") - - with pytest.raises(CustomException): - client.create_subscription(name, topic) - - def test_get_subscription(self): - # Setup Expected Response - name = "name3373707" - topic = "topic110546223" - ack_deadline_seconds = 2135351438 - retain_acked_messages = False - enable_message_ordering = True - expected_response = { - "name": name, - "topic": topic, - "ack_deadline_seconds": ack_deadline_seconds, - "retain_acked_messages": retain_acked_messages, - "enable_message_ordering": enable_message_ordering, - } - expected_response = pubsub_pb2.Subscription(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - response = client.get_subscription(subscription) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.GetSubscriptionRequest(subscription=subscription) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_subscription_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - with pytest.raises(CustomException): - client.get_subscription(subscription) - - def test_update_subscription(self): - # Setup Expected Response - name = "name3373707" - topic = "topic110546223" - ack_deadline_seconds_2 = 921632575 - retain_acked_messages = False - enable_message_ordering = True - expected_response = { - "name": name, - "topic": topic, - "ack_deadline_seconds": ack_deadline_seconds_2, - "retain_acked_messages": retain_acked_messages, - "enable_message_ordering": enable_message_ordering, - } - expected_response = pubsub_pb2.Subscription(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - ack_deadline_seconds = 42 - subscription = {"ack_deadline_seconds": ack_deadline_seconds} - paths_element = "ack_deadline_seconds" - paths = [paths_element] - update_mask = {"paths": paths} - - response = client.update_subscription(subscription, update_mask) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.UpdateSubscriptionRequest( - subscription=subscription, update_mask=update_mask - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_update_subscription_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - ack_deadline_seconds = 42 - subscription = {"ack_deadline_seconds": ack_deadline_seconds} - paths_element = "ack_deadline_seconds" - paths = [paths_element] - update_mask = {"paths": paths} - - with pytest.raises(CustomException): - client.update_subscription(subscription, update_mask) - - def test_list_subscriptions(self): - # Setup Expected Response - next_page_token = "" - subscriptions_element = {} - subscriptions = [subscriptions_element] - expected_response = { - "next_page_token": next_page_token, - "subscriptions": subscriptions, - } - expected_response = pubsub_pb2.ListSubscriptionsResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - project = client.project_path("[PROJECT]") - - paged_list_response = client.list_subscriptions(project) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.subscriptions[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.ListSubscriptionsRequest(project=project) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_subscriptions_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - project = client.project_path("[PROJECT]") - - paged_list_response = client.list_subscriptions(project) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_delete_subscription(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - client.delete_subscription(subscription) - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.DeleteSubscriptionRequest( - subscription=subscription - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_delete_subscription_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - with pytest.raises(CustomException): - client.delete_subscription(subscription) - - def test_modify_ack_deadline(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - ack_ids = [] - ack_deadline_seconds = 2135351438 - - client.modify_ack_deadline(subscription, ack_ids, ack_deadline_seconds) - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.ModifyAckDeadlineRequest( - subscription=subscription, - ack_ids=ack_ids, - ack_deadline_seconds=ack_deadline_seconds, - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_modify_ack_deadline_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - ack_ids = [] - ack_deadline_seconds = 2135351438 - - with pytest.raises(CustomException): - client.modify_ack_deadline(subscription, ack_ids, ack_deadline_seconds) - - def test_acknowledge(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - ack_ids = [] - - client.acknowledge(subscription, ack_ids) - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.AcknowledgeRequest( - subscription=subscription, ack_ids=ack_ids - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_acknowledge_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - ack_ids = [] - - with pytest.raises(CustomException): - client.acknowledge(subscription, ack_ids) - - def test_pull(self): - # Setup Expected Response - expected_response = {} - expected_response = pubsub_pb2.PullResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - max_messages = 496131527 - - response = client.pull(subscription, max_messages) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.PullRequest( - subscription=subscription, max_messages=max_messages - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_pull_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - max_messages = 496131527 - - with pytest.raises(CustomException): - client.pull(subscription, max_messages) - - def test_streaming_pull(self): - # Setup Expected Response - received_messages_element = {} - received_messages = [received_messages_element] - expected_response = {"received_messages": received_messages} - expected_response = pubsub_pb2.StreamingPullResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[iter([expected_response])]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - stream_ack_deadline_seconds = 1875467245 - request = { - "subscription": subscription, - "stream_ack_deadline_seconds": stream_ack_deadline_seconds, - } - request = pubsub_pb2.StreamingPullRequest(**request) - requests = [request] - - response = client.streaming_pull(requests) - resources = list(response) - assert len(resources) == 1 - assert expected_response == resources[0] - - assert len(channel.requests) == 1 - actual_requests = channel.requests[0][1] - assert len(actual_requests) == 1 - actual_request = list(actual_requests)[0] - assert request == actual_request - - def test_streaming_pull_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - stream_ack_deadline_seconds = 1875467245 - request = { - "subscription": subscription, - "stream_ack_deadline_seconds": stream_ack_deadline_seconds, - } - - request = pubsub_pb2.StreamingPullRequest(**request) - requests = [request] - - with pytest.raises(CustomException): - client.streaming_pull(requests) - - def test_modify_push_config(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - push_config = {} - - client.modify_push_config(subscription, push_config) - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.ModifyPushConfigRequest( - subscription=subscription, push_config=push_config - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_modify_push_config_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - push_config = {} - - with pytest.raises(CustomException): - client.modify_push_config(subscription, push_config) - - def test_list_snapshots(self): - # Setup Expected Response - next_page_token = "" - snapshots_element = {} - snapshots = [snapshots_element] - expected_response = {"next_page_token": next_page_token, "snapshots": snapshots} - expected_response = pubsub_pb2.ListSnapshotsResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - project = client.project_path("[PROJECT]") - - paged_list_response = client.list_snapshots(project) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.snapshots[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.ListSnapshotsRequest(project=project) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_snapshots_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - project = client.project_path("[PROJECT]") - - paged_list_response = client.list_snapshots(project) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_create_snapshot(self): - # Setup Expected Response - name_2 = "name2-1052831874" - topic = "topic110546223" - expected_response = {"name": name_2, "topic": topic} - expected_response = pubsub_pb2.Snapshot(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - name = client.snapshot_path("[PROJECT]", "[SNAPSHOT]") - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - response = client.create_snapshot(name, subscription) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.CreateSnapshotRequest( - name=name, subscription=subscription - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_create_snapshot_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - name = client.snapshot_path("[PROJECT]", "[SNAPSHOT]") - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - with pytest.raises(CustomException): - client.create_snapshot(name, subscription) - - def test_update_snapshot(self): - # Setup Expected Response - name = "name3373707" - topic = "topic110546223" - expected_response = {"name": name, "topic": topic} - expected_response = pubsub_pb2.Snapshot(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - seconds = 123456 - expire_time = {"seconds": seconds} - snapshot = {"expire_time": expire_time} - paths_element = "expire_time" - paths = [paths_element] - update_mask = {"paths": paths} - - response = client.update_snapshot(snapshot, update_mask) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.UpdateSnapshotRequest( - snapshot=snapshot, update_mask=update_mask - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_update_snapshot_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - seconds = 123456 - expire_time = {"seconds": seconds} - snapshot = {"expire_time": expire_time} - paths_element = "expire_time" - paths = [paths_element] - update_mask = {"paths": paths} - - with pytest.raises(CustomException): - client.update_snapshot(snapshot, update_mask) - - def test_delete_snapshot(self): - channel = ChannelStub() - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - snapshot = client.snapshot_path("[PROJECT]", "[SNAPSHOT]") - - client.delete_snapshot(snapshot) - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.DeleteSnapshotRequest(snapshot=snapshot) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_delete_snapshot_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - snapshot = client.snapshot_path("[PROJECT]", "[SNAPSHOT]") - - with pytest.raises(CustomException): - client.delete_snapshot(snapshot) - - def test_seek(self): - # Setup Expected Response - expected_response = {} - expected_response = pubsub_pb2.SeekResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - response = client.seek(subscription) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = pubsub_pb2.SeekRequest(subscription=subscription) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_seek_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - subscription = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - with pytest.raises(CustomException): - client.seek(subscription) - - def test_set_iam_policy(self): - # Setup Expected Response - version = 351608024 - etag = b"21" - expected_response = {"version": version, "etag": etag} - expected_response = policy_pb2.Policy(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - resource = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - policy = {} - - response = client.set_iam_policy(resource, policy) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.SetIamPolicyRequest( - resource=resource, policy=policy - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_set_iam_policy_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - resource = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - policy = {} - - with pytest.raises(CustomException): - client.set_iam_policy(resource, policy) - - def test_get_iam_policy(self): - # Setup Expected Response - version = 351608024 - etag = b"21" - expected_response = {"version": version, "etag": etag} - expected_response = policy_pb2.Policy(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - resource = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - response = client.get_iam_policy(resource) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.GetIamPolicyRequest(resource=resource) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_iam_policy_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - resource = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - - with pytest.raises(CustomException): - client.get_iam_policy(resource) - - def test_test_iam_permissions(self): - # Setup Expected Response - expected_response = {} - expected_response = iam_policy_pb2.TestIamPermissionsResponse( - **expected_response - ) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup Request - resource = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - permissions = [] - - response = client.test_iam_permissions(resource, permissions) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = iam_policy_pb2.TestIamPermissionsRequest( - resource=resource, permissions=permissions - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_test_iam_permissions_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = subscriber_client.SubscriberClient() - - # Setup request - resource = client.subscription_path("[PROJECT]", "[SUBSCRIPTION]") - permissions = [] - - with pytest.raises(CustomException): - client.test_iam_permissions(resource, permissions) diff --git a/pubsub/tests/unit/pubsub_v1/publisher/batch/test_base.py b/pubsub/tests/unit/pubsub_v1/publisher/batch/test_base.py deleted file mode 100644 index b19a5a1f1504..000000000000 --- a/pubsub/tests/unit/pubsub_v1/publisher/batch/test_base.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import mock - -from google.auth import credentials -from google.cloud.pubsub_v1 import publisher -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.publisher._batch.base import BatchStatus -from google.cloud.pubsub_v1.publisher._batch.thread import Batch - - -def create_batch(status=None, settings=types.BatchSettings()): - """Create a batch object, which does not commit. - - Args: - status (str): If provided, the batch's internal status will be set - to the provided status. - - Returns: - ~.pubsub_v1.publisher.batch.thread.Batch: The batch object - """ - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - batch = Batch(client, "topic_name", settings, autocommit=False) - if status: - batch._status = status - return batch - - -def test_len(): - batch = create_batch(status=BatchStatus.ACCEPTING_MESSAGES) - assert len(batch) == 0 - batch.publish(types.PubsubMessage(data=b"foo")) - assert len(batch) == 1 - - -def test_will_accept(): - batch = create_batch(status=BatchStatus.ACCEPTING_MESSAGES) - message = types.PubsubMessage() - assert batch.will_accept(message) is True - - -def test_will_accept_oversize(): - batch = create_batch( - settings=types.BatchSettings(max_bytes=10), - status=BatchStatus.ACCEPTING_MESSAGES, - ) - message = types.PubsubMessage(data=b"abcdefghijklmnopqrstuvwxyz") - assert batch.will_accept(message) is True - - -def test_will_not_accept_status(): - batch = create_batch(status="talk to the hand") - message = types.PubsubMessage() - assert batch.will_accept(message) is False - - -def test_will_not_accept_number(): - batch = create_batch( - settings=types.BatchSettings(max_messages=-1), - status=BatchStatus.ACCEPTING_MESSAGES, - ) - message = types.PubsubMessage(data=b"abc") - assert batch.will_accept(message) is False diff --git a/pubsub/tests/unit/pubsub_v1/publisher/batch/test_thread.py b/pubsub/tests/unit/pubsub_v1/publisher/batch/test_thread.py deleted file mode 100644 index f51b314af6df..000000000000 --- a/pubsub/tests/unit/pubsub_v1/publisher/batch/test_thread.py +++ /dev/null @@ -1,421 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import datetime -import threading -import time - -import mock -import pytest - -import google.api_core.exceptions -from google.auth import credentials -from google.cloud.pubsub_v1 import publisher -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.publisher import exceptions -from google.cloud.pubsub_v1.publisher._batch.base import BatchStatus -from google.cloud.pubsub_v1.publisher._batch import thread -from google.cloud.pubsub_v1.publisher._batch.thread import Batch - - -def create_client(): - creds = mock.Mock(spec=credentials.Credentials) - return publisher.Client(credentials=creds) - - -def create_batch(autocommit=False, topic="topic_name", **batch_settings): - """Return a batch object suitable for testing. - - Args: - autocommit (bool): Whether the batch should commit after - ``max_latency`` seconds. By default, this is ``False`` - for unit testing. - topic (str): The name of the topic the batch should publish - the messages to. - batch_settings (dict): Arguments passed on to the - :class:``~.pubsub_v1.types.BatchSettings`` constructor. - - Returns: - ~.pubsub_v1.publisher.batch.thread.Batch: A batch object. - """ - client = create_client() - settings = types.BatchSettings(**batch_settings) - return Batch(client, topic, settings, autocommit=autocommit) - - -def test_init(): - """Establish that a monitor thread is usually created on init.""" - client = create_client() - - # Do not actually create a thread, but do verify that one was created; - # it should be running the batch's "monitor" method (which commits the - # batch once time elapses). - with mock.patch.object(threading, "Thread", autospec=True) as Thread: - batch = Batch(client, "topic_name", types.BatchSettings()) - Thread.assert_called_once_with( - name="Thread-MonitorBatchPublisher", target=batch.monitor - ) - - # New batches start able to accept messages by default. - assert batch.status == BatchStatus.ACCEPTING_MESSAGES - - -def test_init_infinite_latency(): - batch = create_batch(max_latency=float("inf")) - assert batch._thread is None - - -@mock.patch.object(threading, "Lock") -def test_make_lock(Lock): - lock = Batch.make_lock() - assert lock is Lock.return_value - Lock.assert_called_once_with() - - -def test_client(): - client = create_client() - settings = types.BatchSettings() - batch = Batch(client, "topic_name", settings, autocommit=False) - assert batch.client is client - - -def test_commit(): - batch = create_batch() - with mock.patch.object(threading, "Thread", autospec=True) as Thread: - batch.commit() - - # A thread should have been created to do the actual commit. - Thread.assert_called_once_with( - name="Thread-CommitBatchPublisher", target=batch._commit - ) - Thread.return_value.start.assert_called_once_with() - - # The batch's status needs to be something other than "accepting messages", - # since the commit started. - assert batch.status != BatchStatus.ACCEPTING_MESSAGES - assert batch.status == BatchStatus.STARTING - - -def test_commit_no_op(): - batch = create_batch() - batch._status = BatchStatus.IN_PROGRESS - with mock.patch.object(threading, "Thread", autospec=True) as Thread: - batch.commit() - - # Make sure a thread was not created. - Thread.assert_not_called() - - # Check that batch status is unchanged. - assert batch.status == BatchStatus.IN_PROGRESS - - -def test_blocking__commit(): - batch = create_batch() - futures = ( - batch.publish({"data": b"This is my message."}), - batch.publish({"data": b"This is another message."}), - ) - - # Set up the underlying API publish method to return a PublishResponse. - publish_response = types.PublishResponse(message_ids=["a", "b"]) - patch = mock.patch.object( - type(batch.client.api), "publish", return_value=publish_response - ) - with patch as publish: - batch._commit() - - # Establish that the underlying API call was made with expected - # arguments. - publish.assert_called_once_with( - "topic_name", - [ - types.PubsubMessage(data=b"This is my message."), - types.PubsubMessage(data=b"This is another message."), - ], - ) - - # Establish that all of the futures are done, and that they have the - # expected values. - assert futures[0].done() - assert futures[0].result() == "a" - assert futures[1].done() - assert futures[1].result() == "b" - - -def test_client_api_publish_not_blocking_additional_publish_calls(): - batch = create_batch(max_messages=1) - api_publish_called = threading.Event() - - def api_publish_delay(_, messages): - api_publish_called.set() - time.sleep(1.0) - message_ids = [str(i) for i in range(len(messages))] - return types.PublishResponse(message_ids=message_ids) - - api_publish_patch = mock.patch.object( - type(batch.client.api), "publish", side_effect=api_publish_delay - ) - - with api_publish_patch: - batch.publish({"data": b"first message"}) - - start = datetime.datetime.now() - event_set = api_publish_called.wait(timeout=1.0) - if not event_set: - pytest.fail("API publish was not called in time") - batch.publish({"data": b"second message"}) - end = datetime.datetime.now() - - # While a batch commit in progress, waiting for the API publish call to - # complete should not unnecessariliy delay other calls to batch.publish(). - assert (end - start).total_seconds() < 1.0 - - -@mock.patch.object(thread, "_LOGGER") -def test_blocking__commit_starting(_LOGGER): - batch = create_batch() - batch._status = BatchStatus.STARTING - - batch._commit() - assert batch._status == BatchStatus.SUCCESS - - _LOGGER.debug.assert_called_once_with("No messages to publish, exiting commit") - - -@mock.patch.object(thread, "_LOGGER") -def test_blocking__commit_already_started(_LOGGER): - batch = create_batch() - batch._status = BatchStatus.IN_PROGRESS - - batch._commit() - assert batch._status == BatchStatus.IN_PROGRESS - - _LOGGER.debug.assert_called_once_with( - "Batch is already in progress, exiting commit" - ) - - -def test_blocking__commit_no_messages(): - batch = create_batch() - with mock.patch.object(type(batch.client.api), "publish") as publish: - batch._commit() - - assert publish.call_count == 0 - - -def test_blocking__commit_wrong_messageid_length(): - batch = create_batch() - futures = ( - batch.publish({"data": b"blah blah blah"}), - batch.publish({"data": b"blah blah blah blah"}), - ) - - # Set up a PublishResponse that only returns one message ID. - publish_response = types.PublishResponse(message_ids=["a"]) - patch = mock.patch.object( - type(batch.client.api), "publish", return_value=publish_response - ) - - with patch: - batch._commit() - - for future in futures: - assert future.done() - assert isinstance(future.exception(), exceptions.PublishError) - - -def test_block__commmit_api_error(): - batch = create_batch() - futures = ( - batch.publish({"data": b"blah blah blah"}), - batch.publish({"data": b"blah blah blah blah"}), - ) - - # Make the API throw an error when publishing. - error = google.api_core.exceptions.InternalServerError("uh oh") - patch = mock.patch.object(type(batch.client.api), "publish", side_effect=error) - - with patch: - batch._commit() - - for future in futures: - assert future.done() - assert future.exception() == error - - -def test_block__commmit_retry_error(): - batch = create_batch() - futures = ( - batch.publish({"data": b"blah blah blah"}), - batch.publish({"data": b"blah blah blah blah"}), - ) - - # Make the API throw an error when publishing. - error = google.api_core.exceptions.RetryError("uh oh", None) - patch = mock.patch.object(type(batch.client.api), "publish", side_effect=error) - - with patch: - batch._commit() - - for future in futures: - assert future.done() - assert future.exception() == error - - -def test_monitor(): - batch = create_batch(max_latency=5.0) - with mock.patch.object(time, "sleep") as sleep: - with mock.patch.object(type(batch), "_commit") as _commit: - batch.monitor() - - # The monitor should have waited the given latency. - sleep.assert_called_once_with(5.0) - - # Since `monitor` runs in its own thread, it should call - # the blocking commit implementation. - _commit.assert_called_once_with() - - -def test_monitor_already_committed(): - batch = create_batch(max_latency=5.0) - status = "something else" - batch._status = status - with mock.patch.object(time, "sleep") as sleep: - batch.monitor() - - # The monitor should have waited the given latency. - sleep.assert_called_once_with(5.0) - - # The status should not have changed. - assert batch._status == status - - -def test_publish_updating_batch_size(): - batch = create_batch(topic="topic_foo") - messages = ( - types.PubsubMessage(data=b"foobarbaz"), - types.PubsubMessage(data=b"spameggs"), - types.PubsubMessage(data=b"1335020400"), - ) - - # Publish each of the messages, which should save them to the batch. - futures = [batch.publish(message) for message in messages] - - # There should be three messages on the batch, and three futures. - assert len(batch.messages) == 3 - assert batch._futures == futures - - # The size should have been incremented by the sum of the size - # contributions of each message to the PublishRequest. - base_request_size = types.PublishRequest(topic="topic_foo").ByteSize() - expected_request_size = base_request_size + sum( - types.PublishRequest(messages=[msg]).ByteSize() for msg in messages - ) - - assert batch.size == expected_request_size - assert batch.size > 0 # I do not always trust protobuf. - - -def test_publish_not_will_accept(): - batch = create_batch(topic="topic_foo", max_messages=0) - base_request_size = types.PublishRequest(topic="topic_foo").ByteSize() - - # Publish the message. - message = types.PubsubMessage(data=b"foobarbaz") - future = batch.publish(message) - - assert future is None - assert batch.size == base_request_size - assert batch.messages == [] - assert batch._futures == [] - - -def test_publish_exceed_max_messages(): - max_messages = 4 - batch = create_batch(max_messages=max_messages) - messages = ( - types.PubsubMessage(data=b"foobarbaz"), - types.PubsubMessage(data=b"spameggs"), - types.PubsubMessage(data=b"1335020400"), - ) - - # Publish each of the messages, which should save them to the batch. - with mock.patch.object(batch, "commit") as commit: - futures = [batch.publish(message) for message in messages] - assert batch._futures == futures - assert len(futures) == max_messages - 1 - - # Commit should not yet have been called. - assert commit.call_count == 0 - - # When a fourth message is published, commit should be called. - # No future will be returned in this case. - future = batch.publish(types.PubsubMessage(data=b"last one")) - commit.assert_called_once_with() - - assert future is None - assert batch._futures == futures - - -@mock.patch.object(thread, "_SERVER_PUBLISH_MAX_BYTES", 1000) -def test_publish_single_message_size_exceeds_server_size_limit(): - batch = create_batch( - topic="topic_foo", - max_messages=1000, - max_bytes=1000 * 1000, # way larger than (mocked) server side limit - ) - - big_message = types.PubsubMessage(data=b"x" * 984) - - request_size = types.PublishRequest( - topic="topic_foo", messages=[big_message] - ).ByteSize() - assert request_size == 1001 # sanity check, just above the (mocked) server limit - - with pytest.raises(exceptions.MessageTooLargeError): - batch.publish(big_message) - - -@mock.patch.object(thread, "_SERVER_PUBLISH_MAX_BYTES", 1000) -def test_publish_total_messages_size_exceeds_server_size_limit(): - batch = create_batch(topic="topic_foo", max_messages=10, max_bytes=1500) - - messages = ( - types.PubsubMessage(data=b"x" * 500), - types.PubsubMessage(data=b"x" * 600), - ) - - # Sanity check - request size is still below BatchSettings.max_bytes, - # but it exceeds the server-side size limit. - request_size = types.PublishRequest(topic="topic_foo", messages=messages).ByteSize() - assert 1000 < request_size < 1500 - - with mock.patch.object(batch, "commit") as fake_commit: - batch.publish(messages[0]) - batch.publish(messages[1]) - - # The server side limit should kick in and cause a commit. - fake_commit.assert_called_once() - - -def test_publish_dict(): - batch = create_batch() - future = batch.publish({"data": b"foobarbaz", "attributes": {"spam": "eggs"}}) - - # There should be one message on the batch. - expected_message = types.PubsubMessage( - data=b"foobarbaz", attributes={"spam": "eggs"} - ) - assert batch.messages == [expected_message] - assert batch._futures == [future] diff --git a/pubsub/tests/unit/pubsub_v1/publisher/test_futures_publisher.py b/pubsub/tests/unit/pubsub_v1/publisher/test_futures_publisher.py deleted file mode 100644 index eb32d05185b6..000000000000 --- a/pubsub/tests/unit/pubsub_v1/publisher/test_futures_publisher.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2019, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import pytest - -from google.cloud.pubsub_v1.publisher import futures - - -class TestFuture(object): - def test_result_on_success(self): - future = futures.Future() - future.set_result("570307942214048") - assert future.result() == "570307942214048" - - def test_result_on_failure(self): - future = futures.Future() - future.set_exception(RuntimeError("Something bad happened.")) - with pytest.raises(RuntimeError): - future.result() diff --git a/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py b/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py deleted file mode 100644 index a06d2d0cf697..000000000000 --- a/pubsub/tests/unit/pubsub_v1/publisher/test_publisher_client.py +++ /dev/null @@ -1,267 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.auth import credentials - -import mock -import pytest - -from google.cloud.pubsub_v1.gapic import publisher_client -from google.cloud.pubsub_v1 import publisher -from google.cloud.pubsub_v1 import types - - -def test_init(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - # A plain client should have an `api` (the underlying GAPIC) and a - # batch settings object, which should have the defaults. - assert isinstance(client.api, publisher_client.PublisherClient) - assert client.batch_settings.max_bytes == 1 * 1000 * 1000 - assert client.batch_settings.max_latency == 0.01 - assert client.batch_settings.max_messages == 100 - - -def test_init_w_custom_transport(): - transport = object() - client = publisher.Client(transport=transport) - - # A plain client should have an `api` (the underlying GAPIC) and a - # batch settings object, which should have the defaults. - assert isinstance(client.api, publisher_client.PublisherClient) - assert client.api.transport is transport - assert client.batch_settings.max_bytes == 1 * 1000 * 1000 - assert client.batch_settings.max_latency == 0.01 - assert client.batch_settings.max_messages == 100 - - -def test_init_emulator(monkeypatch): - monkeypatch.setenv("PUBSUB_EMULATOR_HOST", "/foo/bar/") - # NOTE: When the emulator host is set, a custom channel will be used, so - # no credentials (mock ot otherwise) can be passed in. - client = publisher.Client() - - # Establish that a gRPC request would attempt to hit the emulator host. - # - # Sadly, there seems to be no good way to do this without poking at - # the private API of gRPC. - channel = client.api.transport.publish._channel - assert channel.target().decode("utf8") == "/foo/bar/" - - -def test_batch_create(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - assert len(client._batches) == 0 - topic = "topic/path" - batch = client._batch(topic, autocommit=False) - assert client._batches == {topic: batch} - - -def test_batch_exists(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - topic = "topic/path" - client._batches[topic] = mock.sentinel.batch - - # A subsequent request should return the same batch. - batch = client._batch(topic, autocommit=False) - assert batch is mock.sentinel.batch - assert client._batches == {topic: batch} - - -def test_batch_create_and_exists(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - topic = "topic/path" - client._batches[topic] = mock.sentinel.batch - - # A subsequent request should return the same batch. - batch = client._batch(topic, create=True, autocommit=False) - assert batch is not mock.sentinel.batch - assert client._batches == {topic: batch} - - -def test_publish(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - # Use a mock in lieu of the actual batch class. - batch = mock.Mock(spec=client._batch_class) - # Set the mock up to claim indiscriminately that it accepts all messages. - batch.will_accept.return_value = True - batch.publish.side_effect = (mock.sentinel.future1, mock.sentinel.future2) - - topic = "topic/path" - client._batches[topic] = batch - - # Begin publishing. - future1 = client.publish(topic, b"spam") - future2 = client.publish(topic, b"foo", bar="baz") - - assert future1 is mock.sentinel.future1 - assert future2 is mock.sentinel.future2 - - # Check mock. - batch.publish.assert_has_calls( - [ - mock.call(types.PubsubMessage(data=b"spam")), - mock.call(types.PubsubMessage(data=b"foo", attributes={"bar": "baz"})), - ] - ) - - -def test_publish_data_not_bytestring_error(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - topic = "topic/path" - with pytest.raises(TypeError): - client.publish(topic, u"This is a text string.") - with pytest.raises(TypeError): - client.publish(topic, 42) - - -def test_publish_attrs_bytestring(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - # Use a mock in lieu of the actual batch class. - batch = mock.Mock(spec=client._batch_class) - # Set the mock up to claim indiscriminately that it accepts all messages. - batch.will_accept.return_value = True - - topic = "topic/path" - client._batches[topic] = batch - - # Begin publishing. - future = client.publish(topic, b"foo", bar=b"baz") - - assert future is batch.publish.return_value - - # The attributes should have been sent as text. - batch.publish.assert_called_once_with( - types.PubsubMessage(data=b"foo", attributes={"bar": u"baz"}) - ) - - -def test_publish_new_batch_needed(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - # Use mocks in lieu of the actual batch class. - batch1 = mock.Mock(spec=client._batch_class) - batch2 = mock.Mock(spec=client._batch_class) - # Set the first mock up to claim indiscriminately that it rejects all - # messages and the second accepts all. - batch1.publish.return_value = None - batch2.publish.return_value = mock.sentinel.future - - topic = "topic/path" - client._batches[topic] = batch1 - - # Actually mock the batch class now. - batch_class = mock.Mock(spec=(), return_value=batch2) - client._batch_class = batch_class - - # Publish a message. - future = client.publish(topic, b"foo", bar=b"baz") - assert future is mock.sentinel.future - - # Check the mocks. - batch_class.assert_called_once_with( - autocommit=True, client=client, settings=client.batch_settings, topic=topic - ) - message_pb = types.PubsubMessage(data=b"foo", attributes={"bar": u"baz"}) - batch1.publish.assert_called_once_with(message_pb) - batch2.publish.assert_called_once_with(message_pb) - - -def test_publish_attrs_type_error(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - topic = "topic/path" - with pytest.raises(TypeError): - client.publish(topic, b"foo", answer=42) - - -def test_stop(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - batch = client._batch("topic1", autocommit=False) - batch2 = client._batch("topic2", autocommit=False) - - pubsub_msg = types.PubsubMessage(data=b"msg") - - patch = mock.patch.object(batch, "commit") - patch2 = mock.patch.object(batch2, "commit") - - with patch as commit_mock, patch2 as commit_mock2: - batch.publish(pubsub_msg) - batch2.publish(pubsub_msg) - - client.stop() - - # check if commit() called - commit_mock.assert_called() - commit_mock2.assert_called() - - # check that closed publisher doesn't accept new messages - with pytest.raises(RuntimeError): - client.publish("topic1", b"msg2") - - with pytest.raises(RuntimeError): - client.stop() - - -def test_gapic_instance_method(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - - ct = mock.Mock() - client.api._inner_api_calls["create_topic"] = ct - - client.create_topic("projects/foo/topics/bar") - assert ct.call_count == 1 - _, args, _ = ct.mock_calls[0] - assert args[0] == types.Topic(name="projects/foo/topics/bar") - - -def test_gapic_class_method_on_class(): - answer = publisher.Client.topic_path("foo", "bar") - assert answer == "projects/foo/topics/bar" - - -def test_class_method_factory(): - patch = mock.patch( - "google.oauth2.service_account.Credentials.from_service_account_file" - ) - - with patch: - client = publisher.Client.from_service_account_file("filename.json") - - assert isinstance(client, publisher.Client) - - -def test_gapic_class_method_on_instance(): - creds = mock.Mock(spec=credentials.Credentials) - client = publisher.Client(credentials=creds) - answer = client.topic_path("foo", "bar") - assert answer == "projects/foo/topics/bar" diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_dispatcher.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_dispatcher.py deleted file mode 100644 index 592a03c6422c..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_dispatcher.py +++ /dev/null @@ -1,261 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import collections -import threading - -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.subscriber._protocol import dispatcher -from google.cloud.pubsub_v1.subscriber._protocol import helper_threads -from google.cloud.pubsub_v1.subscriber._protocol import requests -from google.cloud.pubsub_v1.subscriber._protocol import streaming_pull_manager - -import mock -from six.moves import queue -import pytest - - -@pytest.mark.parametrize( - "item,method_name", - [ - (requests.AckRequest(0, 0, 0), "ack"), - (requests.DropRequest(0, 0), "drop"), - (requests.LeaseRequest(0, 0), "lease"), - (requests.ModAckRequest(0, 0), "modify_ack_deadline"), - (requests.NackRequest(0, 0), "nack"), - ], -) -def test_dispatch_callback(item, method_name): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [item] - - with mock.patch.object(dispatcher_, method_name) as method: - dispatcher_.dispatch_callback(items) - - method.assert_called_once_with([item]) - - -def test_dispatch_callback_inactive(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - manager.is_active = False - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - dispatcher_.dispatch_callback([requests.AckRequest(0, 0, 0)]) - - manager.send.assert_not_called() - - -def test_ack(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [requests.AckRequest(ack_id="ack_id_string", byte_size=0, time_to_ack=20)] - dispatcher_.ack(items) - - manager.send.assert_called_once_with( - types.StreamingPullRequest(ack_ids=["ack_id_string"]) - ) - - manager.leaser.remove.assert_called_once_with(items) - manager.maybe_resume_consumer.assert_called_once() - manager.ack_histogram.add.assert_called_once_with(20) - - -def test_ack_no_time(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [requests.AckRequest(ack_id="ack_id_string", byte_size=0, time_to_ack=None)] - dispatcher_.ack(items) - - manager.send.assert_called_once_with( - types.StreamingPullRequest(ack_ids=["ack_id_string"]) - ) - - manager.ack_histogram.add.assert_not_called() - - -def test_ack_splitting_large_payload(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [ - # use realistic lengths for ACK IDs (max 176 bytes) - requests.AckRequest(ack_id=str(i).zfill(176), byte_size=0, time_to_ack=20) - for i in range(5001) - ] - dispatcher_.ack(items) - - calls = manager.send.call_args_list - assert len(calls) == 3 - - all_ack_ids = {item.ack_id for item in items} - sent_ack_ids = collections.Counter() - - for call in calls: - message = call.args[0] - assert message.ByteSize() <= 524288 # server-side limit (2**19) - sent_ack_ids.update(message.ack_ids) - - assert set(sent_ack_ids) == all_ack_ids # all messages should have been ACK-ed - assert sent_ack_ids.most_common(1)[0][1] == 1 # each message ACK-ed exactly once - - -def test_lease(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [requests.LeaseRequest(ack_id="ack_id_string", byte_size=10)] - dispatcher_.lease(items) - - manager.leaser.add.assert_called_once_with(items) - manager.maybe_pause_consumer.assert_called_once() - - -def test_drop(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [requests.DropRequest(ack_id="ack_id_string", byte_size=10)] - dispatcher_.drop(items) - - manager.leaser.remove.assert_called_once_with(items) - manager.maybe_resume_consumer.assert_called_once() - - -def test_nack(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [requests.NackRequest(ack_id="ack_id_string", byte_size=10)] - dispatcher_.nack(items) - - manager.send.assert_called_once_with( - types.StreamingPullRequest( - modify_deadline_ack_ids=["ack_id_string"], modify_deadline_seconds=[0] - ) - ) - - -def test_modify_ack_deadline(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [requests.ModAckRequest(ack_id="ack_id_string", seconds=60)] - dispatcher_.modify_ack_deadline(items) - - manager.send.assert_called_once_with( - types.StreamingPullRequest( - modify_deadline_ack_ids=["ack_id_string"], modify_deadline_seconds=[60] - ) - ) - - -def test_modify_ack_deadline_splitting_large_payload(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - items = [ - # use realistic lengths for ACK IDs (max 176 bytes) - requests.ModAckRequest(ack_id=str(i).zfill(176), seconds=60) - for i in range(5001) - ] - dispatcher_.modify_ack_deadline(items) - - calls = manager.send.call_args_list - assert len(calls) == 3 - - all_ack_ids = {item.ack_id for item in items} - sent_ack_ids = collections.Counter() - - for call in calls: - message = call.args[0] - assert message.ByteSize() <= 524288 # server-side limit (2**19) - sent_ack_ids.update(message.modify_deadline_ack_ids) - - assert set(sent_ack_ids) == all_ack_ids # all messages should have been MODACK-ed - assert sent_ack_ids.most_common(1)[0][1] == 1 # each message MODACK-ed exactly once - - -@mock.patch("threading.Thread", autospec=True) -def test_start(thread): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - - dispatcher_.start() - - thread.assert_called_once_with( - name=dispatcher._CALLBACK_WORKER_NAME, target=mock.ANY - ) - - thread.return_value.start.assert_called_once() - - assert dispatcher_._thread is not None - - -@mock.patch("threading.Thread", autospec=True) -def test_start_already_started(thread): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - dispatcher_ = dispatcher.Dispatcher(manager, mock.sentinel.queue) - dispatcher_._thread = mock.sentinel.thread - - with pytest.raises(ValueError): - dispatcher_.start() - - thread.assert_not_called() - - -def test_stop(): - queue_ = queue.Queue() - dispatcher_ = dispatcher.Dispatcher(mock.sentinel.manager, queue_) - thread = mock.create_autospec(threading.Thread, instance=True) - dispatcher_._thread = thread - - dispatcher_.stop() - - assert queue_.get() is helper_threads.STOP - thread.join.assert_called_once() - assert dispatcher_._thread is None - - -def test_stop_no_join(): - dispatcher_ = dispatcher.Dispatcher(mock.sentinel.manager, mock.sentinel.queue) - - dispatcher_.stop() diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_futures_subscriber.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_futures_subscriber.py deleted file mode 100644 index 2b4566018f7f..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_futures_subscriber.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import mock -import pytest - -from google.cloud.pubsub_v1.subscriber import futures -from google.cloud.pubsub_v1.subscriber._protocol import streaming_pull_manager - - -class TestStreamingPullFuture(object): - def make_future(self): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - future = futures.StreamingPullFuture(manager) - return future - - def test_default_state(self): - future = self.make_future() - - assert future.running() - assert not future.done() - assert not future.cancelled() - future._manager.add_close_callback.assert_called_once_with( - future._on_close_callback - ) - - def test__on_close_callback_success(self): - future = self.make_future() - - future._on_close_callback(mock.sentinel.manager, None) - - assert future.result() is True - assert not future.running() - - def test__on_close_callback_failure(self): - future = self.make_future() - - future._on_close_callback(mock.sentinel.manager, ValueError("meep")) - - with pytest.raises(ValueError): - future.result() - - assert not future.running() - - def test_cancel(self): - future = self.make_future() - - future.cancel() - - future._manager.close.assert_called_once() - assert future.cancelled() diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_heartbeater.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_heartbeater.py deleted file mode 100644 index 8f5049691a9d..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_heartbeater.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2018, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import threading - -from google.cloud.pubsub_v1.subscriber._protocol import heartbeater -from google.cloud.pubsub_v1.subscriber._protocol import streaming_pull_manager - -import mock -import pytest - - -def test_heartbeat_inactive(caplog): - caplog.set_level(logging.INFO) - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - manager.is_active = False - - heartbeater_ = heartbeater.Heartbeater(manager) - - heartbeater_.heartbeat() - - assert "exiting" in caplog.text - - -def test_heartbeat_stopped(caplog): - caplog.set_level(logging.INFO) - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - - heartbeater_ = heartbeater.Heartbeater(manager) - heartbeater_.stop() - - heartbeater_.heartbeat() - - assert "exiting" in caplog.text - - -def make_sleep_mark_manager_as_inactive(heartbeater): - # Make sleep mark the manager as inactive so that heartbeat() - # exits at the end of the first run. - def trigger_inactive(timeout): - assert timeout - heartbeater._manager.is_active = False - - heartbeater._stop_event.wait = trigger_inactive - - -def test_heartbeat_once(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - heartbeater_ = heartbeater.Heartbeater(manager) - make_sleep_mark_manager_as_inactive(heartbeater_) - - heartbeater_.heartbeat() - - manager.heartbeat.assert_called_once() - - -@mock.patch("threading.Thread", autospec=True) -def test_start(thread): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - heartbeater_ = heartbeater.Heartbeater(manager) - - heartbeater_.start() - - thread.assert_called_once_with( - name=heartbeater._HEARTBEAT_WORKER_NAME, target=heartbeater_.heartbeat - ) - - thread.return_value.start.assert_called_once() - - assert heartbeater_._thread is not None - - -@mock.patch("threading.Thread", autospec=True) -def test_start_already_started(thread): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - heartbeater_ = heartbeater.Heartbeater(manager) - heartbeater_._thread = mock.sentinel.thread - - with pytest.raises(ValueError): - heartbeater_.start() - - thread.assert_not_called() - - -def test_stop(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - heartbeater_ = heartbeater.Heartbeater(manager) - thread = mock.create_autospec(threading.Thread, instance=True) - heartbeater_._thread = thread - - heartbeater_.stop() - - assert heartbeater_._stop_event.is_set() - thread.join.assert_called_once() - assert heartbeater_._thread is None - - -def test_stop_no_join(): - heartbeater_ = heartbeater.Heartbeater(mock.sentinel.manager) - - heartbeater_.stop() diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_helper_threads.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_helper_threads.py deleted file mode 100644 index 6e1bcc813c89..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_helper_threads.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import mock -from six.moves import queue - -from google.cloud.pubsub_v1.subscriber._protocol import helper_threads - - -def test_queue_callback_worker(): - queue_ = queue.Queue() - callback = mock.Mock(spec=()) - qct = helper_threads.QueueCallbackWorker(queue_, callback) - - # Set up an appropriate mock for the queue, and call the queue callback - # thread. - with mock.patch.object(queue.Queue, "get") as get: - get.side_effect = (mock.sentinel.A, helper_threads.STOP, queue.Empty()) - qct() - - # Assert that we got the expected calls. - assert get.call_count == 3 - callback.assert_called_once_with([mock.sentinel.A]) - - -def test_queue_callback_worker_stop_with_extra_items(): - queue_ = queue.Queue() - callback = mock.Mock(spec=()) - qct = helper_threads.QueueCallbackWorker(queue_, callback) - - # Set up an appropriate mock for the queue, and call the queue callback - # thread. - with mock.patch.object(queue.Queue, "get") as get: - get.side_effect = ( - mock.sentinel.A, - helper_threads.STOP, - mock.sentinel.B, - queue.Empty(), - ) - qct() - - # Assert that we got the expected calls. - assert get.call_count == 4 - callback.assert_called_once_with([mock.sentinel.A]) - - -def test_queue_callback_worker_get_many(): - queue_ = queue.Queue() - callback = mock.Mock(spec=()) - qct = helper_threads.QueueCallbackWorker(queue_, callback) - - # Set up an appropriate mock for the queue, and call the queue callback - # thread. - with mock.patch.object(queue.Queue, "get") as get: - get.side_effect = ( - mock.sentinel.A, - queue.Empty(), - mock.sentinel.B, - helper_threads.STOP, - queue.Empty(), - ) - qct() - - # Assert that we got the expected calls. - assert get.call_count == 5 - callback.assert_has_calls( - [mock.call([(mock.sentinel.A)]), mock.call([(mock.sentinel.B)])] - ) - - -def test_queue_callback_worker_max_items(): - queue_ = queue.Queue() - callback = mock.Mock(spec=()) - qct = helper_threads.QueueCallbackWorker(queue_, callback, max_items=1) - - # Set up an appropriate mock for the queue, and call the queue callback - # thread. - with mock.patch.object(queue.Queue, "get") as get: - get.side_effect = ( - mock.sentinel.A, - mock.sentinel.B, - helper_threads.STOP, - queue.Empty(), - ) - qct() - - # Assert that we got the expected calls. - assert get.call_count == 3 - callback.assert_has_calls( - [mock.call([(mock.sentinel.A)]), mock.call([(mock.sentinel.B)])] - ) - - -def test_queue_callback_worker_exception(): - queue_ = queue.Queue() - callback = mock.Mock(spec=(), side_effect=(Exception,)) - qct = helper_threads.QueueCallbackWorker(queue_, callback) - - # Set up an appropriate mock for the queue, and call the queue callback - # thread. - with mock.patch.object(queue.Queue, "get") as get: - get.side_effect = (mock.sentinel.A, helper_threads.STOP, queue.Empty()) - qct() - - # Assert that we got the expected calls. - assert get.call_count == 3 - callback.assert_called_once_with([mock.sentinel.A]) diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_histogram.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_histogram.py deleted file mode 100644 index d3c15cdcee9c..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_histogram.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from google.cloud.pubsub_v1.subscriber._protocol import histogram - - -def test_init(): - data = {} - histo = histogram.Histogram(data=data) - assert histo._data is data - assert len(histo) == 0 - - -def test_contains(): - histo = histogram.Histogram() - histo.add(10) - histo.add(20) - assert 10 in histo - assert 20 in histo - assert 30 not in histo - - -def test_max(): - histo = histogram.Histogram() - assert histo.max == 600 - histo.add(120) - assert histo.max == 120 - histo.add(150) - assert histo.max == 150 - histo.add(20) - assert histo.max == 150 - - -def test_min(): - histo = histogram.Histogram() - assert histo.min == 10 - histo.add(60) - assert histo.min == 60 - histo.add(30) - assert histo.min == 30 - histo.add(120) - assert histo.min == 30 - - -def test_add(): - histo = histogram.Histogram() - histo.add(60) - assert histo._data[60] == 1 - histo.add(60) - assert histo._data[60] == 2 - - -def test_add_lower_limit(): - histo = histogram.Histogram() - histo.add(5) - assert 5 not in histo - assert 10 in histo - - -def test_add_upper_limit(): - histo = histogram.Histogram() - histo.add(12000) - assert 12000 not in histo - assert 600 in histo - - -def test_percentile(): - histo = histogram.Histogram() - [histo.add(i) for i in range(101, 201)] - assert histo.percentile(100) == 200 - assert histo.percentile(101) == 200 - assert histo.percentile(99) == 199 - assert histo.percentile(1) == 101 diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_leaser.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_leaser.py deleted file mode 100644 index c8b217473d40..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_leaser.py +++ /dev/null @@ -1,225 +0,0 @@ -# Copyright 2017, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import threading - -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.subscriber._protocol import dispatcher -from google.cloud.pubsub_v1.subscriber._protocol import histogram -from google.cloud.pubsub_v1.subscriber._protocol import leaser -from google.cloud.pubsub_v1.subscriber._protocol import requests -from google.cloud.pubsub_v1.subscriber._protocol import streaming_pull_manager - -import mock -import pytest - - -def test_add_and_remove(): - leaser_ = leaser.Leaser(mock.sentinel.manager) - - leaser_.add([requests.LeaseRequest(ack_id="ack1", byte_size=50)]) - leaser_.add([requests.LeaseRequest(ack_id="ack2", byte_size=25)]) - - assert leaser_.message_count == 2 - assert set(leaser_.ack_ids) == set(["ack1", "ack2"]) - assert leaser_.bytes == 75 - - leaser_.remove([requests.DropRequest(ack_id="ack1", byte_size=50)]) - - assert leaser_.message_count == 1 - assert set(leaser_.ack_ids) == set(["ack2"]) - assert leaser_.bytes == 25 - - -def test_add_already_managed(caplog): - caplog.set_level(logging.DEBUG) - - leaser_ = leaser.Leaser(mock.sentinel.manager) - - leaser_.add([requests.LeaseRequest(ack_id="ack1", byte_size=50)]) - leaser_.add([requests.LeaseRequest(ack_id="ack1", byte_size=50)]) - - assert "already lease managed" in caplog.text - - -def test_remove_not_managed(caplog): - caplog.set_level(logging.DEBUG) - - leaser_ = leaser.Leaser(mock.sentinel.manager) - - leaser_.remove([requests.DropRequest(ack_id="ack1", byte_size=50)]) - - assert "not managed" in caplog.text - - -def test_remove_negative_bytes(caplog): - caplog.set_level(logging.DEBUG) - - leaser_ = leaser.Leaser(mock.sentinel.manager) - - leaser_.add([requests.LeaseRequest(ack_id="ack1", byte_size=50)]) - leaser_.remove([requests.DropRequest(ack_id="ack1", byte_size=75)]) - - assert leaser_.bytes == 0 - assert "unexpectedly negative" in caplog.text - - -def create_manager(flow_control=types.FlowControl()): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - manager.dispatcher = mock.create_autospec(dispatcher.Dispatcher, instance=True) - manager.is_active = True - manager.flow_control = flow_control - manager.ack_histogram = histogram.Histogram() - return manager - - -def test_maintain_leases_inactive(caplog): - caplog.set_level(logging.INFO) - manager = create_manager() - manager.is_active = False - - leaser_ = leaser.Leaser(manager) - - leaser_.maintain_leases() - - assert "exiting" in caplog.text - - -def test_maintain_leases_stopped(caplog): - caplog.set_level(logging.INFO) - manager = create_manager() - - leaser_ = leaser.Leaser(manager) - leaser_.stop() - - leaser_.maintain_leases() - - assert "exiting" in caplog.text - - -def make_sleep_mark_manager_as_inactive(leaser): - # Make sleep mark the manager as inactive so that maintain_leases - # exits at the end of the first run. - def trigger_inactive(timeout): - assert 0 < timeout < 10 - leaser._manager.is_active = False - - leaser._stop_event.wait = trigger_inactive - - -def test_maintain_leases_ack_ids(): - manager = create_manager() - leaser_ = leaser.Leaser(manager) - make_sleep_mark_manager_as_inactive(leaser_) - leaser_.add([requests.LeaseRequest(ack_id="my ack id", byte_size=50)]) - - leaser_.maintain_leases() - - manager.dispatcher.modify_ack_deadline.assert_called_once_with( - [requests.ModAckRequest(ack_id="my ack id", seconds=10)] - ) - - -def test_maintain_leases_no_ack_ids(): - manager = create_manager() - leaser_ = leaser.Leaser(manager) - make_sleep_mark_manager_as_inactive(leaser_) - - leaser_.maintain_leases() - - manager.dispatcher.modify_ack_deadline.assert_not_called() - - -@mock.patch("time.time", autospec=True) -def test_maintain_leases_outdated_items(time): - manager = create_manager() - leaser_ = leaser.Leaser(manager) - make_sleep_mark_manager_as_inactive(leaser_) - - # Add these items at the beginning of the timeline - time.return_value = 0 - leaser_.add([requests.LeaseRequest(ack_id="ack1", byte_size=50)]) - - # Add another item at towards end of the timeline - time.return_value = manager.flow_control.max_lease_duration - 1 - leaser_.add([requests.LeaseRequest(ack_id="ack2", byte_size=50)]) - - # Now make sure time reports that we are at the end of our timeline. - time.return_value = manager.flow_control.max_lease_duration + 1 - - leaser_.maintain_leases() - - # Only ack2 should be renewed. ack1 should've been dropped - manager.dispatcher.modify_ack_deadline.assert_called_once_with( - [requests.ModAckRequest(ack_id="ack2", seconds=10)] - ) - manager.dispatcher.drop.assert_called_once_with( - [requests.DropRequest(ack_id="ack1", byte_size=50)] - ) - - -@mock.patch("threading.Thread", autospec=True) -def test_start(thread): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - leaser_ = leaser.Leaser(manager) - - leaser_.start() - - thread.assert_called_once_with( - name=leaser._LEASE_WORKER_NAME, target=leaser_.maintain_leases - ) - - thread.return_value.start.assert_called_once() - - assert leaser_._thread is not None - - -@mock.patch("threading.Thread", autospec=True) -def test_start_already_started(thread): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - leaser_ = leaser.Leaser(manager) - leaser_._thread = mock.sentinel.thread - - with pytest.raises(ValueError): - leaser_.start() - - thread.assert_not_called() - - -def test_stop(): - manager = mock.create_autospec( - streaming_pull_manager.StreamingPullManager, instance=True - ) - leaser_ = leaser.Leaser(manager) - thread = mock.create_autospec(threading.Thread, instance=True) - leaser_._thread = thread - - leaser_.stop() - - assert leaser_._stop_event.is_set() - thread.join.assert_called_once() - assert leaser_._thread is None - - -def test_stop_no_join(): - leaser_ = leaser.Leaser(mock.sentinel.manager) - - leaser_.stop() diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_message.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_message.py deleted file mode 100644 index fd23deef06c9..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_message.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import datetime -import time - -import mock -import pytz -from six.moves import queue -from google.protobuf import timestamp_pb2 - -from google.api_core import datetime_helpers -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.subscriber import message -from google.cloud.pubsub_v1.subscriber._protocol import requests - - -RECEIVED = datetime.datetime(2012, 4, 21, 15, 0, tzinfo=pytz.utc) -RECEIVED_SECONDS = datetime_helpers.to_milliseconds(RECEIVED) // 1000 -PUBLISHED_MICROS = 123456 -PUBLISHED = RECEIVED + datetime.timedelta(days=1, microseconds=PUBLISHED_MICROS) -PUBLISHED_SECONDS = datetime_helpers.to_milliseconds(PUBLISHED) // 1000 - - -def create_message(data, ack_id="ACKID", delivery_attempt=0, **attrs): - with mock.patch.object(time, "time") as time_: - time_.return_value = RECEIVED_SECONDS - msg = message.Message( - message=types.PubsubMessage( - attributes=attrs, - data=data, - message_id="message_id", - publish_time=timestamp_pb2.Timestamp( - seconds=PUBLISHED_SECONDS, nanos=PUBLISHED_MICROS * 1000 - ), - ), - ack_id=ack_id, - delivery_attempt=delivery_attempt, - request_queue=queue.Queue(), - ) - return msg - - -def test_attributes(): - msg = create_message(b"foo", baz="bacon", spam="eggs") - assert msg.attributes == {"baz": "bacon", "spam": "eggs"} - - -def test_data(): - msg = create_message(b"foo") - assert msg.data == b"foo" - - -def test_size(): - msg = create_message(b"foo") - assert msg.size == 30 # payload + protobuf overhead - - -def test_ack_id(): - ack_id = "MY-ACK-ID" - msg = create_message(b"foo", ack_id=ack_id) - assert msg.ack_id == ack_id - - -def test_delivery_attempt(): - delivery_attempt = 10 - msg = create_message(b"foo", delivery_attempt=delivery_attempt) - assert msg.delivery_attempt == delivery_attempt - - -def test_delivery_attempt_is_none(): - msg = create_message(b"foo", delivery_attempt=0) - assert msg.delivery_attempt is None - - -def test_publish_time(): - msg = create_message(b"foo") - assert msg.publish_time == PUBLISHED - - -def check_call_types(mock, *args, **kwargs): - """Checks a mock's call types. - - Args: - mock: The mock to check. - args: The types of the positional arguments. - kwargs: The names of the keyword args to check and their respective - types. - - Raises: - AssertionError: if any of the types don't match, or if the number of - arguments does not match. - """ - for call in mock.mock_calls: - _, call_args, call_kwargs = call - assert len(call_args) == len(args) - for n, argtype in enumerate(args): - assert isinstance(call_args[n], argtype) - for argname, argtype in kwargs: - assert argname in call_kwargs - assert isinstance(call_kwargs[argname], argtype) - - -def test_ack(): - msg = create_message(b"foo", ack_id="bogus_ack_id") - with mock.patch.object(msg._request_queue, "put") as put: - msg.ack() - put.assert_called_once_with( - requests.AckRequest( - ack_id="bogus_ack_id", byte_size=30, time_to_ack=mock.ANY - ) - ) - check_call_types(put, requests.AckRequest) - - -def test_drop(): - msg = create_message(b"foo", ack_id="bogus_ack_id") - with mock.patch.object(msg._request_queue, "put") as put: - msg.drop() - put.assert_called_once_with( - requests.DropRequest(ack_id="bogus_ack_id", byte_size=30) - ) - check_call_types(put, requests.DropRequest) - - -def test_modify_ack_deadline(): - msg = create_message(b"foo", ack_id="bogus_ack_id") - with mock.patch.object(msg._request_queue, "put") as put: - msg.modify_ack_deadline(60) - put.assert_called_once_with( - requests.ModAckRequest(ack_id="bogus_ack_id", seconds=60) - ) - check_call_types(put, requests.ModAckRequest) - - -def test_nack(): - msg = create_message(b"foo", ack_id="bogus_ack_id") - with mock.patch.object(msg._request_queue, "put") as put: - msg.nack() - put.assert_called_once_with( - requests.NackRequest(ack_id="bogus_ack_id", byte_size=30) - ) - check_call_types(put, requests.NackRequest) - - -def test_repr(): - data = b"foo" - msg = create_message(data, snow="cones", orange="juice") - data_line = " data: {!r}".format(data) - expected_repr = "\n".join( - ( - "Message {", - data_line, - " attributes: {", - ' "orange": "juice",', - ' "snow": "cones"', - " }", - "}", - ) - ) - assert repr(msg) == expected_repr diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_scheduler.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_scheduler.py deleted file mode 100644 index 774d0d63e2a2..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_scheduler.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2018, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import concurrent.futures -import threading - -import mock -from six.moves import queue - -from google.cloud.pubsub_v1.subscriber import scheduler - - -def test_subclasses_base_abc(): - assert issubclass(scheduler.ThreadScheduler, scheduler.Scheduler) - - -def test_constructor_defaults(): - scheduler_ = scheduler.ThreadScheduler() - - assert isinstance(scheduler_.queue, queue.Queue) - assert isinstance(scheduler_._executor, concurrent.futures.Executor) - - -def test_constructor_options(): - scheduler_ = scheduler.ThreadScheduler(executor=mock.sentinel.executor) - - assert scheduler_._executor == mock.sentinel.executor - - -def test_schedule(): - called_with = [] - called = threading.Event() - - def callback(*args, **kwargs): - called_with.append((args, kwargs)) - called.set() - - scheduler_ = scheduler.ThreadScheduler() - - scheduler_.schedule(callback, "arg1", kwarg1="meep") - - called.wait() - scheduler_.shutdown() - - assert called_with == [(("arg1",), {"kwarg1": "meep"})] diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_streaming_pull_manager.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_streaming_pull_manager.py deleted file mode 100644 index 6f8a04ac9935..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_streaming_pull_manager.py +++ /dev/null @@ -1,826 +0,0 @@ -# Copyright 2018, Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import threading -import time -import types as stdlib_types - -import mock -import pytest -from six.moves import queue - -from google.api_core import bidi -from google.api_core import exceptions -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.gapic import subscriber_client_config -from google.cloud.pubsub_v1.subscriber import client -from google.cloud.pubsub_v1.subscriber import message -from google.cloud.pubsub_v1.subscriber import scheduler -from google.cloud.pubsub_v1.subscriber._protocol import dispatcher -from google.cloud.pubsub_v1.subscriber._protocol import heartbeater -from google.cloud.pubsub_v1.subscriber._protocol import leaser -from google.cloud.pubsub_v1.subscriber._protocol import requests -from google.cloud.pubsub_v1.subscriber._protocol import streaming_pull_manager -import grpc - - -@pytest.mark.parametrize( - "exception,expected_cls", - [ - (ValueError("meep"), ValueError), - ( - mock.create_autospec(grpc.RpcError, instance=True), - exceptions.GoogleAPICallError, - ), - ], -) -def test__maybe_wrap_exception(exception, expected_cls): - assert isinstance( - streaming_pull_manager._maybe_wrap_exception(exception), expected_cls - ) - - -def test__wrap_callback_errors_no_error(): - msg = mock.create_autospec(message.Message, instance=True) - callback = mock.Mock() - on_callback_error = mock.Mock() - - streaming_pull_manager._wrap_callback_errors(callback, on_callback_error, msg) - - callback.assert_called_once_with(msg) - msg.nack.assert_not_called() - on_callback_error.assert_not_called() - - -def test__wrap_callback_errors_error(): - callback_error = ValueError("meep") - - msg = mock.create_autospec(message.Message, instance=True) - callback = mock.Mock(side_effect=callback_error) - on_callback_error = mock.Mock() - - streaming_pull_manager._wrap_callback_errors(callback, on_callback_error, msg) - - msg.nack.assert_called_once() - on_callback_error.assert_called_once_with(callback_error) - - -def test_constructor_and_default_state(): - manager = streaming_pull_manager.StreamingPullManager( - mock.sentinel.client, mock.sentinel.subscription - ) - - # Public state - assert manager.is_active is False - assert manager.flow_control == types.FlowControl() - assert manager.dispatcher is None - assert manager.leaser is None - assert manager.ack_histogram is not None - assert manager.ack_deadline == 10 - assert manager.load == 0 - - # Private state - assert manager._client == mock.sentinel.client - assert manager._subscription == mock.sentinel.subscription - assert manager._scheduler is not None - - -def test_constructor_with_options(): - manager = streaming_pull_manager.StreamingPullManager( - mock.sentinel.client, - mock.sentinel.subscription, - flow_control=mock.sentinel.flow_control, - scheduler=mock.sentinel.scheduler, - ) - - assert manager.flow_control == mock.sentinel.flow_control - assert manager._scheduler == mock.sentinel.scheduler - - -def make_manager(**kwargs): - client_ = mock.create_autospec(client.Client, instance=True) - scheduler_ = mock.create_autospec(scheduler.Scheduler, instance=True) - return streaming_pull_manager.StreamingPullManager( - client_, "subscription-name", scheduler=scheduler_, **kwargs - ) - - -def fake_leaser_add(leaser, init_msg_count=0, assumed_msg_size=10): - """Add a simplified fake add() method to a leaser instance. - - The fake add() method actually increases the leaser's internal message count - by one for each message, and the total bytes by ``assumed_msg_size`` for - each message (regardless of the actual message size). - """ - - def fake_add(self, items): - self.message_count += len(items) - self.bytes += len(items) * assumed_msg_size - - leaser.message_count = init_msg_count - leaser.bytes = init_msg_count * assumed_msg_size - leaser.add = stdlib_types.MethodType(fake_add, leaser) - - -def test_ack_deadline(): - manager = make_manager() - assert manager.ack_deadline == 10 - manager.ack_histogram.add(20) - assert manager.ack_deadline == 20 - manager.ack_histogram.add(10) - assert manager.ack_deadline == 20 - - -def test_maybe_pause_consumer_wo_consumer_set(): - manager = make_manager( - flow_control=types.FlowControl(max_messages=10, max_bytes=1000) - ) - manager.maybe_pause_consumer() # no raise - # Ensure load > 1 - _leaser = manager._leaser = mock.create_autospec(leaser.Leaser) - _leaser.message_count = 100 - _leaser.bytes = 10000 - manager.maybe_pause_consumer() # no raise - - -def test_lease_load_and_pause(): - manager = make_manager( - flow_control=types.FlowControl(max_messages=10, max_bytes=1000) - ) - manager._leaser = leaser.Leaser(manager) - manager._consumer = mock.create_autospec(bidi.BackgroundConsumer, instance=True) - manager._consumer.is_paused = False - - # This should mean that our messages count is at 10%, and our bytes - # are at 15%; load should return the higher (0.15), and shouldn't cause - # the consumer to pause. - manager.leaser.add([requests.LeaseRequest(ack_id="one", byte_size=150)]) - assert manager.load == 0.15 - manager.maybe_pause_consumer() - manager._consumer.pause.assert_not_called() - - # After this message is added, the messages should be higher at 20% - # (versus 16% for bytes). - manager.leaser.add([requests.LeaseRequest(ack_id="two", byte_size=10)]) - assert manager.load == 0.2 - - # Returning a number above 100% is fine, and it should cause this to pause. - manager.leaser.add([requests.LeaseRequest(ack_id="three", byte_size=1000)]) - assert manager.load == 1.16 - manager.maybe_pause_consumer() - manager._consumer.pause.assert_called_once() - - -def test_drop_and_resume(): - manager = make_manager( - flow_control=types.FlowControl(max_messages=10, max_bytes=1000) - ) - manager._leaser = leaser.Leaser(manager) - manager._consumer = mock.create_autospec(bidi.BackgroundConsumer, instance=True) - manager._consumer.is_paused = True - - # Add several messages until we're over the load threshold. - manager.leaser.add( - [ - requests.LeaseRequest(ack_id="one", byte_size=750), - requests.LeaseRequest(ack_id="two", byte_size=250), - ] - ) - - assert manager.load == 1.0 - - # Trying to resume now should have no effect as we're over the threshold. - manager.maybe_resume_consumer() - manager._consumer.resume.assert_not_called() - - # Drop the 200 byte message, which should put us under the resume - # threshold. - manager.leaser.remove([requests.DropRequest(ack_id="two", byte_size=250)]) - manager.maybe_resume_consumer() - manager._consumer.resume.assert_called_once() - - -def test_resume_not_paused(): - manager = make_manager() - manager._consumer = mock.create_autospec(bidi.BackgroundConsumer, instance=True) - manager._consumer.is_paused = False - - # Resuming should have no effect is the consumer is not actually paused. - manager.maybe_resume_consumer() - manager._consumer.resume.assert_not_called() - - -def test_maybe_resume_consumer_wo_consumer_set(): - manager = make_manager( - flow_control=types.FlowControl(max_messages=10, max_bytes=1000) - ) - manager.maybe_resume_consumer() # no raise - - -def test__maybe_release_messages_on_overload(): - manager = make_manager( - flow_control=types.FlowControl(max_messages=10, max_bytes=1000) - ) - - msg = mock.create_autospec(message.Message, instance=True, ack_id="ack", size=11) - manager._messages_on_hold.put(msg) - manager._on_hold_bytes = msg.size - - # Ensure load is exactly 1.0 (to verify that >= condition is used) - _leaser = manager._leaser = mock.create_autospec(leaser.Leaser) - _leaser.message_count = 10 - _leaser.bytes = 1000 + msg.size - - manager._maybe_release_messages() - - assert manager._messages_on_hold.qsize() == 1 - manager._leaser.add.assert_not_called() - manager._scheduler.schedule.assert_not_called() - - -def test__maybe_release_messages_below_overload(): - manager = make_manager( - flow_control=types.FlowControl(max_messages=10, max_bytes=1000) - ) - manager._callback = mock.sentinel.callback - - # Init leaser message count to 11, so that when subtracting the 3 messages - # that are on hold, there is still room for another 2 messages before the - # max load is hit. - _leaser = manager._leaser = mock.create_autospec(leaser.Leaser) - fake_leaser_add(_leaser, init_msg_count=11, assumed_msg_size=10) - - messages = [ - mock.create_autospec(message.Message, instance=True, ack_id="ack_foo", size=10), - mock.create_autospec(message.Message, instance=True, ack_id="ack_bar", size=10), - mock.create_autospec(message.Message, instance=True, ack_id="ack_baz", size=10), - ] - for msg in messages: - manager._messages_on_hold.put(msg) - manager._on_hold_bytes = 3 * 10 - - # the actual call of MUT - manager._maybe_release_messages() - - assert manager._messages_on_hold.qsize() == 1 - msg = manager._messages_on_hold.get_nowait() - assert msg.ack_id == "ack_baz" - - schedule_calls = manager._scheduler.schedule.mock_calls - assert len(schedule_calls) == 2 - for _, call_args, _ in schedule_calls: - assert call_args[0] == mock.sentinel.callback - assert isinstance(call_args[1], message.Message) - assert call_args[1].ack_id in ("ack_foo", "ack_bar") - - -def test__maybe_release_messages_negative_on_hold_bytes_warning(caplog): - manager = make_manager( - flow_control=types.FlowControl(max_messages=10, max_bytes=1000) - ) - - msg = mock.create_autospec(message.Message, instance=True, ack_id="ack", size=17) - manager._messages_on_hold.put(msg) - manager._on_hold_bytes = 5 # too low for some reason - - _leaser = manager._leaser = mock.create_autospec(leaser.Leaser) - _leaser.message_count = 3 - _leaser.bytes = 150 - - with caplog.at_level(logging.WARNING): - manager._maybe_release_messages() - - expected_warnings = [ - record.message.lower() - for record in caplog.records - if "unexpectedly negative" in record.message - ] - assert len(expected_warnings) == 1 - assert "on hold bytes" in expected_warnings[0] - assert "-12" in expected_warnings[0] - - assert manager._on_hold_bytes == 0 # should be auto-corrected - - -def test_send_unary(): - manager = make_manager() - manager._UNARY_REQUESTS = True - - manager.send( - types.StreamingPullRequest( - ack_ids=["ack_id1", "ack_id2"], - modify_deadline_ack_ids=["ack_id3", "ack_id4", "ack_id5"], - modify_deadline_seconds=[10, 20, 20], - ) - ) - - manager._client.acknowledge.assert_called_once_with( - subscription=manager._subscription, ack_ids=["ack_id1", "ack_id2"] - ) - - manager._client.modify_ack_deadline.assert_has_calls( - [ - mock.call( - subscription=manager._subscription, - ack_ids=["ack_id3"], - ack_deadline_seconds=10, - ), - mock.call( - subscription=manager._subscription, - ack_ids=["ack_id4", "ack_id5"], - ack_deadline_seconds=20, - ), - ], - any_order=True, - ) - - -def test_send_unary_empty(): - manager = make_manager() - manager._UNARY_REQUESTS = True - - manager.send(types.StreamingPullRequest()) - - manager._client.acknowledge.assert_not_called() - manager._client.modify_ack_deadline.assert_not_called() - - -def test_send_unary_api_call_error(caplog): - caplog.set_level(logging.DEBUG) - - manager = make_manager() - manager._UNARY_REQUESTS = True - - error = exceptions.GoogleAPICallError("The front fell off") - manager._client.acknowledge.side_effect = error - - manager.send(types.StreamingPullRequest(ack_ids=["ack_id1", "ack_id2"])) - - assert "The front fell off" in caplog.text - - -def test_send_unary_retry_error(caplog): - caplog.set_level(logging.DEBUG) - - manager, _, _, _, _, _ = make_running_manager() - manager._UNARY_REQUESTS = True - - error = exceptions.RetryError( - "Too long a transient error", cause=Exception("Out of time!") - ) - manager._client.acknowledge.side_effect = error - - with pytest.raises(exceptions.RetryError): - manager.send(types.StreamingPullRequest(ack_ids=["ack_id1", "ack_id2"])) - - assert "RetryError while sending unary RPC" in caplog.text - assert "signaled streaming pull manager shutdown" in caplog.text - - -def test_send_streaming(): - manager = make_manager() - manager._UNARY_REQUESTS = False - manager._rpc = mock.create_autospec(bidi.BidiRpc, instance=True) - - manager.send(mock.sentinel.request) - - manager._rpc.send.assert_called_once_with(mock.sentinel.request) - - -def test_heartbeat(): - manager = make_manager() - manager._rpc = mock.create_autospec(bidi.BidiRpc, instance=True) - manager._rpc.is_active = True - - manager.heartbeat() - - manager._rpc.send.assert_called_once_with(types.StreamingPullRequest()) - - -def test_heartbeat_inactive(): - manager = make_manager() - manager._rpc = mock.create_autospec(bidi.BidiRpc, instance=True) - manager._rpc.is_active = False - - manager.heartbeat() - - manager._rpc.send.assert_not_called() - - -@mock.patch("google.api_core.bidi.ResumableBidiRpc", autospec=True) -@mock.patch("google.api_core.bidi.BackgroundConsumer", autospec=True) -@mock.patch("google.cloud.pubsub_v1.subscriber._protocol.leaser.Leaser", autospec=True) -@mock.patch( - "google.cloud.pubsub_v1.subscriber._protocol.dispatcher.Dispatcher", autospec=True -) -@mock.patch( - "google.cloud.pubsub_v1.subscriber._protocol.heartbeater.Heartbeater", autospec=True -) -def test_open(heartbeater, dispatcher, leaser, background_consumer, resumable_bidi_rpc): - manager = make_manager() - - manager.open(mock.sentinel.callback, mock.sentinel.on_callback_error) - - heartbeater.assert_called_once_with(manager) - heartbeater.return_value.start.assert_called_once() - assert manager._heartbeater == heartbeater.return_value - - dispatcher.assert_called_once_with(manager, manager._scheduler.queue) - dispatcher.return_value.start.assert_called_once() - assert manager._dispatcher == dispatcher.return_value - - leaser.assert_called_once_with(manager) - leaser.return_value.start.assert_called_once() - assert manager.leaser == leaser.return_value - - background_consumer.assert_called_once_with(manager._rpc, manager._on_response) - background_consumer.return_value.start.assert_called_once() - assert manager._consumer == background_consumer.return_value - - resumable_bidi_rpc.assert_called_once_with( - start_rpc=manager._client.api.streaming_pull, - initial_request=mock.ANY, - should_recover=manager._should_recover, - should_terminate=manager._should_terminate, - throttle_reopen=True, - ) - initial_request_arg = resumable_bidi_rpc.call_args.kwargs["initial_request"] - assert initial_request_arg.func == manager._get_initial_request - assert initial_request_arg.args[0] == 10 # the default stream ACK timeout - assert not manager._client.api.get_subscription.called - - resumable_bidi_rpc.return_value.add_done_callback.assert_called_once_with( - manager._on_rpc_done - ) - assert manager._rpc == resumable_bidi_rpc.return_value - - manager._consumer.is_active = True - assert manager.is_active is True - - -def test_open_already_active(): - manager = make_manager() - manager._consumer = mock.create_autospec(bidi.BackgroundConsumer, instance=True) - manager._consumer.is_active = True - - with pytest.raises(ValueError, match="already open"): - manager.open(mock.sentinel.callback, mock.sentinel.on_callback_error) - - -def test_open_has_been_closed(): - manager = make_manager() - manager._closed = True - - with pytest.raises(ValueError, match="closed"): - manager.open(mock.sentinel.callback, mock.sentinel.on_callback_error) - - -def make_running_manager(): - manager = make_manager() - manager._consumer = mock.create_autospec(bidi.BackgroundConsumer, instance=True) - manager._consumer.is_active = True - manager._dispatcher = mock.create_autospec(dispatcher.Dispatcher, instance=True) - manager._leaser = mock.create_autospec(leaser.Leaser, instance=True) - manager._heartbeater = mock.create_autospec(heartbeater.Heartbeater, instance=True) - - return ( - manager, - manager._consumer, - manager._dispatcher, - manager._leaser, - manager._heartbeater, - manager._scheduler, - ) - - -def test_close(): - manager, consumer, dispatcher, leaser, heartbeater, scheduler = ( - make_running_manager() - ) - - manager.close() - - consumer.stop.assert_called_once() - leaser.stop.assert_called_once() - dispatcher.stop.assert_called_once() - heartbeater.stop.assert_called_once() - scheduler.shutdown.assert_called_once() - - assert manager.is_active is False - - -def test_close_inactive_consumer(): - manager, consumer, dispatcher, leaser, heartbeater, scheduler = ( - make_running_manager() - ) - consumer.is_active = False - - manager.close() - - consumer.stop.assert_not_called() - leaser.stop.assert_called_once() - dispatcher.stop.assert_called_once() - heartbeater.stop.assert_called_once() - scheduler.shutdown.assert_called_once() - - -def test_close_idempotent(): - manager, _, _, _, _, scheduler = make_running_manager() - - manager.close() - manager.close() - - assert scheduler.shutdown.call_count == 1 - - -class FakeDispatcher(object): - def __init__(self, manager, error_callback): - self._manager = manager - self._error_callback = error_callback - self._thread = None - self._stop = False - - def start(self): - self._thread = threading.Thread(target=self._do_work) - self._thread.daemon = True - self._thread.start() - - def stop(self): - self._stop = True - self._thread.join() - self._thread = None - - def _do_work(self): - while not self._stop: - try: - self._manager.leaser.add([mock.Mock()]) - except Exception as exc: - self._error_callback(exc) - time.sleep(0.1) - - # also try to interact with the leaser after the stop flag has been set - try: - self._manager.leaser.remove([mock.Mock()]) - except Exception as exc: - self._error_callback(exc) - - -def test_close_no_dispatcher_error(): - manager, _, _, _, _, _ = make_running_manager() - error_callback = mock.Mock(name="error_callback") - dispatcher = FakeDispatcher(manager=manager, error_callback=error_callback) - manager._dispatcher = dispatcher - dispatcher.start() - - manager.close() - - error_callback.assert_not_called() - - -def test_close_callbacks(): - manager, _, _, _, _, _ = make_running_manager() - - callback = mock.Mock() - - manager.add_close_callback(callback) - manager.close(reason="meep") - - callback.assert_called_once_with(manager, "meep") - - -def test__get_initial_request(): - manager = make_manager() - manager._leaser = mock.create_autospec(leaser.Leaser, instance=True) - manager._leaser.ack_ids = ["1", "2"] - - initial_request = manager._get_initial_request(123) - - assert isinstance(initial_request, types.StreamingPullRequest) - assert initial_request.subscription == "subscription-name" - assert initial_request.stream_ack_deadline_seconds == 123 - assert initial_request.modify_deadline_ack_ids == ["1", "2"] - assert initial_request.modify_deadline_seconds == [10, 10] - - -def test__get_initial_request_wo_leaser(): - manager = make_manager() - manager._leaser = None - - initial_request = manager._get_initial_request(123) - - assert isinstance(initial_request, types.StreamingPullRequest) - assert initial_request.subscription == "subscription-name" - assert initial_request.stream_ack_deadline_seconds == 123 - assert initial_request.modify_deadline_ack_ids == [] - assert initial_request.modify_deadline_seconds == [] - - -def test__on_response_delivery_attempt(): - manager, _, dispatcher, leaser, _, scheduler = make_running_manager() - manager._callback = mock.sentinel.callback - - # Set up the messages. - response = types.StreamingPullResponse( - received_messages=[ - types.ReceivedMessage( - ack_id="fack", message=types.PubsubMessage(data=b"foo", message_id="1") - ), - types.ReceivedMessage( - ack_id="back", - message=types.PubsubMessage(data=b"bar", message_id="2"), - delivery_attempt=6, - ), - ] - ) - - # adjust message bookkeeping in leaser - fake_leaser_add(leaser, init_msg_count=0, assumed_msg_size=42) - - manager._on_response(response) - - schedule_calls = scheduler.schedule.mock_calls - assert len(schedule_calls) == 2 - msg1 = schedule_calls[0][1][1] - assert msg1.delivery_attempt is None - msg2 = schedule_calls[1][1][1] - assert msg2.delivery_attempt == 6 - - -def test__on_response_no_leaser_overload(): - manager, _, dispatcher, leaser, _, scheduler = make_running_manager() - manager._callback = mock.sentinel.callback - - # Set up the messages. - response = types.StreamingPullResponse( - received_messages=[ - types.ReceivedMessage( - ack_id="fack", message=types.PubsubMessage(data=b"foo", message_id="1") - ), - types.ReceivedMessage( - ack_id="back", message=types.PubsubMessage(data=b"bar", message_id="2") - ), - ] - ) - - # adjust message bookkeeping in leaser - fake_leaser_add(leaser, init_msg_count=0, assumed_msg_size=42) - - # Actually run the method and prove that modack and schedule - # are called in the expected way. - manager._on_response(response) - - dispatcher.modify_ack_deadline.assert_called_once_with( - [requests.ModAckRequest("fack", 10), requests.ModAckRequest("back", 10)] - ) - - schedule_calls = scheduler.schedule.mock_calls - assert len(schedule_calls) == 2 - for call in schedule_calls: - assert call[1][0] == mock.sentinel.callback - assert isinstance(call[1][1], message.Message) - - # the leaser load limit not hit, no messages had to be put on hold - assert manager._messages_on_hold.qsize() == 0 - - -def test__on_response_with_leaser_overload(): - manager, _, dispatcher, leaser, _, scheduler = make_running_manager() - manager._callback = mock.sentinel.callback - - # Set up the messages. - response = types.StreamingPullResponse( - received_messages=[ - types.ReceivedMessage( - ack_id="fack", message=types.PubsubMessage(data=b"foo", message_id="1") - ), - types.ReceivedMessage( - ack_id="back", message=types.PubsubMessage(data=b"bar", message_id="2") - ), - types.ReceivedMessage( - ack_id="zack", message=types.PubsubMessage(data=b"baz", message_id="3") - ), - ] - ) - - # Adjust message bookkeeping in leaser. Pick 999 messages, which is just below - # the default FlowControl.max_messages limit. - fake_leaser_add(leaser, init_msg_count=999, assumed_msg_size=10) - - # Actually run the method and prove that modack and schedule - # are called in the expected way. - manager._on_response(response) - - # all messages should be added to the lease management and have their ACK - # deadline extended, even those not dispatched to callbacks - dispatcher.modify_ack_deadline.assert_called_once_with( - [ - requests.ModAckRequest("fack", 10), - requests.ModAckRequest("back", 10), - requests.ModAckRequest("zack", 10), - ] - ) - - # one message should be scheduled, the flow control limits allow for it - schedule_calls = scheduler.schedule.mock_calls - assert len(schedule_calls) == 1 - call_args = schedule_calls[0][1] - assert call_args[0] == mock.sentinel.callback - assert isinstance(call_args[1], message.Message) - assert call_args[1].message_id == "1" - - # the rest of the messages should have been put on hold - assert manager._messages_on_hold.qsize() == 2 - while True: - try: - msg = manager._messages_on_hold.get_nowait() - except queue.Empty: - break - else: - assert isinstance(msg, message.Message) - assert msg.message_id in ("2", "3") - - -def test__on_response_none_data(caplog): - caplog.set_level(logging.DEBUG) - - manager, _, dispatcher, leaser, _, scheduler = make_running_manager() - manager._callback = mock.sentinel.callback - - # adjust message bookkeeping in leaser - fake_leaser_add(leaser, init_msg_count=0, assumed_msg_size=10) - - manager._on_response(response=None) - - scheduler.schedule.assert_not_called() - assert "callback invoked with None" in caplog.text - - -def test_retryable_stream_errors(): - # Make sure the config matches our hard-coded tuple of exceptions. - interfaces = subscriber_client_config.config["interfaces"] - retry_codes = interfaces["google.pubsub.v1.Subscriber"]["retry_codes"] - idempotent = retry_codes["idempotent"] - - status_codes = tuple(getattr(grpc.StatusCode, name, None) for name in idempotent) - expected = tuple( - exceptions.exception_class_for_grpc_status(status_code) - for status_code in status_codes - ) - assert set(expected).issubset(set(streaming_pull_manager._RETRYABLE_STREAM_ERRORS)) - - -def test__should_recover_true(): - manager = make_manager() - - details = "UNAVAILABLE. Service taking nap." - exc = exceptions.ServiceUnavailable(details) - - assert manager._should_recover(exc) is True - - -def test__should_recover_false(): - manager = make_manager() - - exc = TypeError("wahhhhhh") - - assert manager._should_recover(exc) is False - - -def test__should_terminate_true(): - manager = make_manager() - - details = "Cancelled. Go away, before I taunt you a second time." - exc = exceptions.Cancelled(details) - - assert manager._should_terminate(exc) is True - - -def test__should_terminate_false(): - manager = make_manager() - - exc = TypeError("wahhhhhh") - - assert manager._should_terminate(exc) is False - - -@mock.patch("threading.Thread", autospec=True) -def test__on_rpc_done(thread): - manager = make_manager() - - manager._on_rpc_done(mock.sentinel.error) - - thread.assert_called_once_with( - name=mock.ANY, target=manager.close, kwargs={"reason": mock.sentinel.error} - ) diff --git a/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py b/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py deleted file mode 100644 index b367733aa705..000000000000 --- a/pubsub/tests/unit/pubsub_v1/subscriber/test_subscriber_client.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from google.auth import credentials -import mock - -from google.cloud.pubsub_v1 import subscriber -from google.cloud.pubsub_v1.gapic import subscriber_client -from google.cloud.pubsub_v1 import types -from google.cloud.pubsub_v1.subscriber import futures - - -def test_init(): - creds = mock.Mock(spec=credentials.Credentials) - client = subscriber.Client(credentials=creds) - assert isinstance(client.api, subscriber_client.SubscriberClient) - - -def test_init_w_custom_transport(): - transport = object() - client = subscriber.Client(transport=transport) - assert isinstance(client.api, subscriber_client.SubscriberClient) - assert client.api.transport is transport - - -def test_init_emulator(monkeypatch): - monkeypatch.setenv("PUBSUB_EMULATOR_HOST", "/baz/bacon/") - # NOTE: When the emulator host is set, a custom channel will be used, so - # no credentials (mock ot otherwise) can be passed in. - client = subscriber.Client() - - # Establish that a gRPC request would attempt to hit the emulator host. - # - # Sadly, there seems to be no good way to do this without poking at - # the private API of gRPC. - channel = client.api.transport.pull._channel - assert channel.target().decode("utf8") == "/baz/bacon/" - - -def test_class_method_factory(): - patch = mock.patch( - "google.oauth2.service_account.Credentials.from_service_account_file" - ) - - with patch: - client = subscriber.Client.from_service_account_file("filename.json") - - assert isinstance(client, subscriber.Client) - - -@mock.patch( - "google.cloud.pubsub_v1.subscriber._protocol.streaming_pull_manager." - "StreamingPullManager.open", - autospec=True, -) -def test_subscribe(manager_open): - creds = mock.Mock(spec=credentials.Credentials) - client = subscriber.Client(credentials=creds) - - future = client.subscribe("sub_name_a", callback=mock.sentinel.callback) - assert isinstance(future, futures.StreamingPullFuture) - - assert future._manager._subscription == "sub_name_a" - manager_open.assert_called_once_with( - mock.ANY, - callback=mock.sentinel.callback, - on_callback_error=future.set_exception, - ) - - -@mock.patch( - "google.cloud.pubsub_v1.subscriber._protocol.streaming_pull_manager." - "StreamingPullManager.open", - autospec=True, -) -def test_subscribe_options(manager_open): - creds = mock.Mock(spec=credentials.Credentials) - client = subscriber.Client(credentials=creds) - flow_control = types.FlowControl(max_bytes=42) - scheduler = mock.sentinel.scheduler - - future = client.subscribe( - "sub_name_a", - callback=mock.sentinel.callback, - flow_control=flow_control, - scheduler=scheduler, - ) - assert isinstance(future, futures.StreamingPullFuture) - - assert future._manager._subscription == "sub_name_a" - assert future._manager.flow_control == flow_control - assert future._manager._scheduler == scheduler - manager_open.assert_called_once_with( - mock.ANY, - callback=mock.sentinel.callback, - on_callback_error=future.set_exception, - ) diff --git a/pubsub/tests/unit/pubsub_v1/test__gapic.py b/pubsub/tests/unit/pubsub_v1/test__gapic.py deleted file mode 100644 index 5478aee18213..000000000000 --- a/pubsub/tests/unit/pubsub_v1/test__gapic.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2019 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from google.cloud.pubsub_v1 import _gapic - - -class SourceClass(object): - def __init__(self): - self.x = "x" - - def method(self): - return "source class instance method" - - @staticmethod - def static_method(): - return "source class static method" - - @classmethod - def class_method(cls): - return "source class class method" - - @classmethod - def blacklisted_method(cls): - return "source class blacklisted method" - - -def test_add_method(): - @_gapic.add_methods(SourceClass, ("blacklisted_method",)) - class Foo(object): - def __init__(self): - self.api = SourceClass() - - def method(self): - return "foo class instance method" - - foo = Foo() - - # Any method that's callable and not blacklisted is "inherited". - assert set(["method", "static_method", "class_method"]) <= set(dir(foo)) - assert "blacklisted_method" not in dir(foo) - - # Source Class's static and class methods become static methods. - assert type(Foo.__dict__["static_method"]) == staticmethod - assert foo.static_method() == "source class static method" - assert type(Foo.__dict__["class_method"]) == staticmethod - assert foo.class_method() == "source class class method" - - # The decorator changes the behavior of instance methods of the wrapped class. - # method() is called on an instance of the Source Class (stored as an - # attribute on the wrapped class). - assert foo.method() == "source class instance method" diff --git a/pubsub/tests/unit/pubsub_v1/test_futures.py b/pubsub/tests/unit/pubsub_v1/test_futures.py deleted file mode 100644 index 11349d5d480a..000000000000 --- a/pubsub/tests/unit/pubsub_v1/test_futures.py +++ /dev/null @@ -1,148 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import threading - -import mock -import pytest - -from google.cloud.pubsub_v1 import exceptions -from google.cloud.pubsub_v1 import futures - - -def _future(*args, **kwargs): - return futures.Future(*args, **kwargs) - - -def test_constructor_defaults(): - with mock.patch.object(threading, "Event", autospec=True) as Event: - future = _future() - - assert future._result == futures.Future._SENTINEL - assert future._exception == futures.Future._SENTINEL - assert future._callbacks == [] - assert future._completed is Event.return_value - - Event.assert_called_once_with() - - -def test_constructor_explicit_completed(): - completed = mock.sentinel.completed - future = _future(completed=completed) - - assert future._result == futures.Future._SENTINEL - assert future._exception == futures.Future._SENTINEL - assert future._callbacks == [] - assert future._completed is completed - - -def test_cancel(): - assert _future().cancel() is False - - -def test_cancelled(): - assert _future().cancelled() is False - - -def test_running(): - future = _future() - assert future.running() is True - future.set_result("foobar") - assert future.running() is False - - -def test_done(): - future = _future() - assert future.done() is False - future.set_result("12345") - assert future.done() is True - - -def test_exception_no_error(): - future = _future() - future.set_result("12345") - assert future.exception() is None - - -def test_exception_with_error(): - future = _future() - error = RuntimeError("Something really bad happened.") - future.set_exception(error) - - # Make sure that the exception that is returned is the batch's error. - # Also check the type to ensure the batch's error did not somehow - # change internally. - assert future.exception() is error - assert isinstance(future.exception(), RuntimeError) - with pytest.raises(RuntimeError): - future.result() - - -def test_exception_timeout(): - future = _future() - with pytest.raises(exceptions.TimeoutError): - future.exception(timeout=0.01) - - -def test_result_no_error(): - future = _future() - future.set_result("42") - assert future.result() == "42" - - -def test_result_with_error(): - future = _future() - future.set_exception(RuntimeError("Something really bad happened.")) - with pytest.raises(RuntimeError): - future.result() - - -def test_add_done_callback_pending_batch(): - future = _future() - callback = mock.Mock() - future.add_done_callback(callback) - assert len(future._callbacks) == 1 - assert callback in future._callbacks - assert callback.call_count == 0 - - -def test_add_done_callback_completed_batch(): - future = _future() - future.set_result("12345") - callback = mock.Mock(spec=()) - future.add_done_callback(callback) - callback.assert_called_once_with(future) - - -def test_trigger(): - future = _future() - callback = mock.Mock(spec=()) - future.add_done_callback(callback) - assert callback.call_count == 0 - future.set_result("12345") - callback.assert_called_once_with(future) - - -def test_set_result_once_only(): - future = _future() - future.set_result("12345") - with pytest.raises(RuntimeError): - future.set_result("67890") - - -def test_set_exception_once_only(): - future = _future() - future.set_exception(ValueError("wah wah")) - with pytest.raises(RuntimeError): - future.set_exception(TypeError("other wah wah")) diff --git a/pubsub/tests/unit/test_pubsub.py b/pubsub/tests/unit/test_pubsub.py deleted file mode 100644 index 76d590a492c5..000000000000 --- a/pubsub/tests/unit/test_pubsub.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from google.cloud import pubsub -from google.cloud import pubsub_v1 - - -def test_exported_things(): - assert pubsub.PublisherClient is pubsub_v1.PublisherClient - assert pubsub.SubscriberClient is pubsub_v1.SubscriberClient - assert pubsub.types is pubsub_v1.types diff --git a/redis/.coveragerc b/redis/.coveragerc deleted file mode 100644 index b178b094aa1d..000000000000 --- a/redis/.coveragerc +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[run] -branch = True - -[report] -fail_under = 100 -show_missing = True -exclude_lines = - # Re-enable the standard pragma - pragma: NO COVER - # Ignore debug-only repr - def __repr__ - # Ignore abstract methods - raise NotImplementedError -omit = - */gapic/*.py - */proto/*.py - */core/*.py - */site-packages/*.py \ No newline at end of file diff --git a/redis/.flake8 b/redis/.flake8 deleted file mode 100644 index 0268ecc9c55c..000000000000 --- a/redis/.flake8 +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[flake8] -ignore = E203, E266, E501, W503 -exclude = - # Exclude generated code. - **/proto/** - **/gapic/** - *_pb2.py - - # Standard linting exemptions. - __pycache__, - .git, - *.pyc, - conf.py diff --git a/redis/.repo-metadata.json b/redis/.repo-metadata.json deleted file mode 100644 index 7f7f221f15c4..000000000000 --- a/redis/.repo-metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "redis", - "name_pretty": "Cloud Redis", - "product_documentation": "https://cloud.google.com/memorystore/docs/redis/", - "client_documentation": "https://googleapis.dev/python/redis/latest", - "issue_tracker": "https://issuetracker.google.com/savedsearches/5169231", - "release_level": "alpha", - "language": "python", - "repo": "googleapis/google-cloud-python", - "distribution_name": "google-cloud-redis", - "api_id": "redis.googleapis.com", - "requires_billing": true -} \ No newline at end of file diff --git a/redis/CHANGELOG.md b/redis/CHANGELOG.md deleted file mode 100644 index 8813cf9e6471..000000000000 --- a/redis/CHANGELOG.md +++ /dev/null @@ -1,104 +0,0 @@ -# Changelog - -[PyPI History][1] - -[1]: https://pypi.org/project/google-cloud-redis/#history - -## 0.3.0 - -07-24-2019 17:15 PDT - - -### Implementation Changes -- Allow kwargs to be passed to create_channel (via synth). ([#8400](https://github.com/googleapis/google-cloud-python/pull/8400)) -- Remove classifier for Python 3.4 for end-of-life. ([#7535](https://github.com/googleapis/google-cloud-python/pull/7535)) -- Remove unused message exports. ([#7272](https://github.com/googleapis/google-cloud-python/pull/7272)) -- Protoc-generated serialization update. ([#7092](https://github.com/googleapis/google-cloud-python/pull/7092)) -- Pick up stub docstring fix in GAPIC generator. ([#6979](https://github.com/googleapis/google-cloud-python/pull/6979)) - -### New Features -- Add 'client_options' support, update list method docstrings (via synth). ([#8519](https://github.com/googleapis/google-cloud-python/pull/8519)) -- Add 'import_instance' / 'export_instance' support (via synth). ([#8220](https://github.com/googleapis/google-cloud-python/pull/8220)) -- Remove v1 'import_instance' / 'export_instance'; add v1beta1 'failover_instance' (via synth). ([#7937](https://github.com/googleapis/google-cloud-python/pull/7937)) -- Add support for instance import / export / failover (via synth). ([#7423](https://github.com/googleapis/google-cloud-python/pull/7423)) - -### Dependencies -- Bump minimum version for google-api-core to 1.14.0. ([#8709](https://github.com/googleapis/google-cloud-python/pull/8709)) -- Pin black version (via synth). ([#8592](https://github.com/googleapis/google-cloud-python/pull/8592)) - -### Documentation -- Link to googleapis.dev documentation in READMEs. ([#8705](https://github.com/googleapis/google-cloud-python/pull/8705)) -- Add compatibility check badges to READMEs. ([#8288](https://github.com/googleapis/google-cloud-python/pull/8288)) -- Updated client library documentation URLs. ([#7307](https://github.com/googleapis/google-cloud-python/pull/7307)) -- Update year: 2018 -> 2019. ([#7154](https://github.com/googleapis/google-cloud-python/pull/7154)) - -### Internal / Testing Changes -- Add docs job to publish to googleapis.dev. ([#8464](https://github.com/googleapis/google-cloud-python/pull/8464)) -- Declare encoding as utf-8 in pb2 files (via synth). ([#8360](https://github.com/googleapis/google-cloud-python/pull/8360)) -- Add disclaimer to auto-generated template files (via synth). ([#8324](https://github.com/googleapis/google-cloud-python/pull/8324)) -- Suppress checking 'cov-fail-under' in nox default session (via synth). ([#8249](https://github.com/googleapis/google-cloud-python/pull/8249)) -- Fix coverage in 'types.py' (via synth). ([#8161](https://github.com/googleapis/google-cloud-python/pull/8161)) -- Blacken noxfile.py, setup.py (via synth). ([#8129](https://github.com/googleapis/google-cloud-python/pull/8129)) -- Add empty lines (via synth). ([#8068](https://github.com/googleapis/google-cloud-python/pull/8068)) -- Finsh setup for 'docs' session in nox. ([#8101](https://github.com/googleapis/google-cloud-python/pull/8101)) -- Use alabaster theme everwhere. ([#8021](https://github.com/googleapis/google-cloud-python/pull/8021)) -- Copy lintified proto files (via synth). -- Add clarifying comment to blacken nox target. ([#7400](https://github.com/googleapis/google-cloud-python/pull/7400)) -- Copy proto files alongside protoc versions. -- Add protos as an artifact to library ([#7205](https://github.com/googleapis/google-cloud-python/pull/7205)) - -## 0.2.1 - -12-18-2018 09:40 PST - - -### Implementation Changes -- Import `iam.policy` from `google.api_core`. ([#6741](https://github.com/googleapis/google-cloud-python/pull/6741)) -- Pick up fixes to GAPIC generator. ([#6504](https://github.com/googleapis/google-cloud-python/pull/6504)) -- Assorted synth fixups / cleanups ([#6400](https://github.com/googleapis/google-cloud-python/pull/6400)) -- Fix `client_info` bug, update docstrings. ([#6419](https://github.com/googleapis/google-cloud-python/pull/6419)) -- Re-generate library using redis/synth.py ([#6016](https://github.com/googleapis/google-cloud-python/pull/6016)) -- Re-generate library using redis/synth.py ([#5993](https://github.com/googleapis/google-cloud-python/pull/5993)) - -### Dependencies -- Bump minimum `api_core` version for all GAPIC libs to 1.4.1. ([#6391](https://github.com/googleapis/google-cloud-python/pull/6391)) - -### Documentation -- Document Python 2 deprecation ([#6910](https://github.com/googleapis/google-cloud-python/pull/6910)) -- Normalize use of support level badges ([#6159](https://github.com/googleapis/google-cloud-python/pull/6159)) - -### Internal / Testing Changes -- Add baseline for synth.metadata -- Update noxfile. -- Blacken all gen'd libs ([#6792](https://github.com/googleapis/google-cloud-python/pull/6792)) -- Omit local deps ([#6701](https://github.com/googleapis/google-cloud-python/pull/6701)) -- Run black at end of synth.py ([#6698](https://github.com/googleapis/google-cloud-python/pull/6698)) -- Run Black on Generated libraries ([#6666](https://github.com/googleapis/google-cloud-python/pull/6666)) -- Add templates for flake8, coveragerc, noxfile, and black. ([#6642](https://github.com/googleapis/google-cloud-python/pull/6642)) -- Don't synth 'README.rst'. ([#6262](https://github.com/googleapis/google-cloud-python/pull/6262)) -- Add / fix badges for PyPI / versions. ([#6158](https://github.com/googleapis/google-cloud-python/pull/6158)) -- Use new Nox ([#6175](https://github.com/googleapis/google-cloud-python/pull/6175)) - -## 0.2.0 - -### New Features - -- Add the v1 API client library. ([#5945](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5945)) - -### Documentation - -- Docs: Replace links to '/stable/' with '/latest/'. ([#5901](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5901)) -- Redis: Fix README.md links ([#5745](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5745)) -- Add redis documentation to main index.rst ([#5405](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5405)) - -### Internal / Testing Changes - -- Nox: use inplace installs ([#5865](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5865)) -- Avoid overwriting '__module__' of messages from shared modules. ([#5364](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5364)) -- Unit tests require grpcio. ([#5363](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5363)) - -## 0.1.0 - -### New Features -Initial version of Redis client library v1beta1. - diff --git a/redis/LICENSE b/redis/LICENSE deleted file mode 100644 index a8ee855de2aa..000000000000 --- a/redis/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/redis/MANIFEST.in b/redis/MANIFEST.in deleted file mode 100644 index 9cbf175afe6b..000000000000 --- a/redis/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include README.rst LICENSE -recursive-include google *.json *.proto -recursive-include tests * -global-exclude *.py[co] -global-exclude __pycache__ diff --git a/redis/README.rst b/redis/README.rst deleted file mode 100644 index e66a8716154a..000000000000 --- a/redis/README.rst +++ /dev/null @@ -1,88 +0,0 @@ -Python Client for Google Cloud Memorystore for Redis API -======================================================== - -|alpha| |pypi| |versions| - -`Google Cloud Memorystore for Redis API`_: The Google Cloud Memorystore for -Redis API is used for creating and managing Redis instances on the Google -Cloud Platform. - -- `Client Library Documentation`_ -- `Product Documentation`_ - -.. |alpha| image:: https://img.shields.io/badge/support-alpha-orange.svg - :target: https://github.com/googleapis/google-cloud-python/blob/master/README.rst#alpha-support -.. |pypi| image:: https://img.shields.io/pypi/v/google-cloud-redis.svg - :target: https://pypi.org/project/google-cloud-redis/ -.. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-redis.svg - :target: https://pypi.org/project/google-cloud-redis/ -.. _Google Cloud Memorystore for Redis API: https://cloud.google.com/memorystore/ -.. _Client Library Documentation: https://googleapis.dev/python/redis/latest -.. _Product Documentation: https://cloud.google.com/memorystore/ - -Quick Start ------------ - -In order to use this library, you first need to go through the following steps: - -1. `Select or create a Cloud Platform project.`_ -2. `Enable billing for your project.`_ -3. `Enable the Google Cloud Memorystore for Redis API.`_ -4. `Setup Authentication.`_ - -.. _Select or create a Cloud Platform project.: https://console.cloud.google.com/project -.. _Enable billing for your project.: https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project -.. _Enable the Google Cloud Memorystore for Redis API.: https://console.cloud.google.com/apis/library/redis.googleapis.com -.. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html - -Installation -~~~~~~~~~~~~ - -Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to -create isolated Python environments. The basic problem it addresses is one of -dependencies and versions, and indirectly permissions. - -With `virtualenv`_, it's possible to install this library without needing system -install permissions, and without clashing with the installed system -dependencies. - -.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ - - -Supported Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.5 - -Deprecated Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^^ -Python == 2.7. Python 2.7 support will be removed on January 1, 2020. - - -Mac/Linux -^^^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - source /bin/activate - /bin/pip install google-cloud-redis - - -Windows -^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - \Scripts\activate - \Scripts\pip.exe install google-cloud-redis - -Next Steps -~~~~~~~~~~ - -- Read the `Client Library Documentation`_ for Google Cloud Memorystore for - Redis API to see other available methods on the client. -- Read the `Product documentation`_ to learn more about the product and see - How-to Guides. diff --git a/redis/docs/README.rst b/redis/docs/README.rst deleted file mode 120000 index 89a0106941ff..000000000000 --- a/redis/docs/README.rst +++ /dev/null @@ -1 +0,0 @@ -../README.rst \ No newline at end of file diff --git a/redis/docs/_static/custom.css b/redis/docs/_static/custom.css deleted file mode 100644 index 0abaf229fce3..000000000000 --- a/redis/docs/_static/custom.css +++ /dev/null @@ -1,4 +0,0 @@ -div#python2-eol { - border-color: red; - border-width: medium; -} \ No newline at end of file diff --git a/redis/docs/_templates/layout.html b/redis/docs/_templates/layout.html deleted file mode 100644 index 228529efe2d2..000000000000 --- a/redis/docs/_templates/layout.html +++ /dev/null @@ -1,50 +0,0 @@ - -{% extends "!layout.html" %} -{%- block content %} -{%- if theme_fixed_sidebar|lower == 'true' %} -
- {{ sidebar() }} - {%- block document %} -
- {%- if render_sidebar %} -
- {%- endif %} - - {%- block relbar_top %} - {%- if theme_show_relbar_top|tobool %} - - {%- endif %} - {% endblock %} - -
-
- On January 1, 2020 this library will no longer support Python 2 on the latest released version. - Previously released library versions will continue to be available. For more information please - visit Python 2 support on Google Cloud. -
- {% block body %} {% endblock %} -
- - {%- block relbar_bottom %} - {%- if theme_show_relbar_bottom|tobool %} - - {%- endif %} - {% endblock %} - - {%- if render_sidebar %} -
- {%- endif %} -
- {%- endblock %} -
-
-{%- else %} -{{ super() }} -{%- endif %} -{%- endblock %} diff --git a/redis/docs/conf.py b/redis/docs/conf.py deleted file mode 100644 index 58e9db4665d2..000000000000 --- a/redis/docs/conf.py +++ /dev/null @@ -1,359 +0,0 @@ -# -*- coding: utf-8 -*- -# -# google-cloud-redis documentation build configuration file -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -import shlex - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath("..")) - -__version__ = "0.1.0" - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.intersphinx", - "sphinx.ext.coverage", - "sphinx.ext.napoleon", - "sphinx.ext.viewcode", -] - -# autodoc/autosummary flags -autoclass_content = "both" -autodoc_default_flags = ["members"] -autosummary_generate = True - - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# Allow markdown includes (so releases.md can include CHANGLEOG.md) -# http://www.sphinx-doc.org/en/master/markdown.html -source_parsers = {".md": "recommonmark.parser.CommonMarkParser"} - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = [".rst", "md"] - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = u"google-cloud-redis" -copyright = u"2017, Google" -author = u"Google APIs" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The full version, including alpha/beta/rc tags. -release = __version__ -# The short X.Y version. -version = ".".join(release.split(".")[0:2]) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["_build"] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "alabaster" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = { - "description": "Google Cloud Client Libraries for Python", - "github_user": "googleapis", - "github_repo": "google-cloud-python", - "github_banner": True, - "font_family": "'Roboto', Georgia, sans", - "head_font_family": "'Roboto', Georgia, serif", - "code_font_family": "'Roboto Mono', 'Consolas', monospace", -} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -# html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -# html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = "google-cloud-redis-doc" - -# -- Options for warnings ------------------------------------------------------ - - -suppress_warnings = [ - # Temporarily suppress this to avoid "more than one target found for - # cross-reference" warning, which are intractable for us to avoid while in - # a mono-repo. - # See https://github.com/sphinx-doc/sphinx/blob - # /2a65ffeef5c107c19084fabdd706cdff3f52d93c/sphinx/domains/python.py#L843 - "ref.python" -] - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - #'preamble': '', - # Latex figure (float) alignment - #'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "google-cloud-redis.tex", - u"google-cloud-redis Documentation", - author, - "manual", - ) -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ( - master_doc, - "google-cloud-automl", - u"google-cloud-automl Documentation", - [author], - 1, - ) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "google-cloud-redis", - u"google-cloud-redis Documentation", - author, - "google-cloud-redis", - "GAPIC library for the {metadata.shortName} v1beta1 service", - "APIs", - ) -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - "python": ("http://python.readthedocs.org/en/latest/", None), - "gax": ("https://gax-python.readthedocs.org/en/latest/", None), - "google-auth": ("https://google-auth.readthedocs.io/en/stable", None), - "google-gax": ("https://gax-python.readthedocs.io/en/latest/", None), - "google.api_core": ("https://googleapis.dev/python/google-api-core/latest", None), - "grpc": ("https://grpc.io/grpc/python/", None), - "requests": ("https://requests.kennethreitz.org/en/stable/", None), - "fastavro": ("https://fastavro.readthedocs.io/en/stable/", None), - "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), -} - -# Napoleon settings -napoleon_google_docstring = True -napoleon_numpy_docstring = True -napoleon_include_private_with_doc = False -napoleon_include_special_with_doc = True -napoleon_use_admonition_for_examples = False -napoleon_use_admonition_for_notes = False -napoleon_use_admonition_for_references = False -napoleon_use_ivar = False -napoleon_use_param = True -napoleon_use_rtype = True diff --git a/redis/docs/gapic/v1/api.rst b/redis/docs/gapic/v1/api.rst deleted file mode 100644 index 50ad1f8a5f64..000000000000 --- a/redis/docs/gapic/v1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Google Cloud Memorystore for Redis API -================================================= - -.. automodule:: google.cloud.redis_v1 - :members: - :inherited-members: \ No newline at end of file diff --git a/redis/docs/gapic/v1/types.rst b/redis/docs/gapic/v1/types.rst deleted file mode 100644 index ba92173ded8e..000000000000 --- a/redis/docs/gapic/v1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Google Cloud Memorystore for Redis API Client -======================================================= - -.. automodule:: google.cloud.redis_v1.types - :members: \ No newline at end of file diff --git a/redis/docs/gapic/v1beta1/api.rst b/redis/docs/gapic/v1beta1/api.rst deleted file mode 100644 index b1505646c85c..000000000000 --- a/redis/docs/gapic/v1beta1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Google Cloud Memorystore for Redis API -================================================= - -.. automodule:: google.cloud.redis_v1beta1 - :members: - :inherited-members: \ No newline at end of file diff --git a/redis/docs/gapic/v1beta1/types.rst b/redis/docs/gapic/v1beta1/types.rst deleted file mode 100644 index 579707e712de..000000000000 --- a/redis/docs/gapic/v1beta1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Google Cloud Memorystore for Redis API Client -======================================================= - -.. automodule:: google.cloud.redis_v1beta1.types - :members: \ No newline at end of file diff --git a/redis/docs/index.rst b/redis/docs/index.rst deleted file mode 100644 index 5338f59ab023..000000000000 --- a/redis/docs/index.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. include:: README.rst - -Api Reference -------------- -.. toctree:: - :maxdepth: 2 - - gapic/v1/api - gapic/v1/types - gapic/v1beta1/api - gapic/v1beta1/types diff --git a/redis/google/__init__.py b/redis/google/__init__.py deleted file mode 100644 index 9a1b64a6d586..000000000000 --- a/redis/google/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/redis/google/cloud/__init__.py b/redis/google/cloud/__init__.py deleted file mode 100644 index 9a1b64a6d586..000000000000 --- a/redis/google/cloud/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/redis/google/cloud/redis.py b/redis/google/cloud/redis.py deleted file mode 100644 index b30f4a972845..000000000000 --- a/redis/google/cloud/redis.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import - -from google.cloud.redis_v1 import CloudRedisClient -from google.cloud.redis_v1 import enums -from google.cloud.redis_v1 import types - - -__all__ = ("enums", "types", "CloudRedisClient") diff --git a/redis/google/cloud/redis_v1/__init__.py b/redis/google/cloud/redis_v1/__init__.py deleted file mode 100644 index 10c3f5080697..000000000000 --- a/redis/google/cloud/redis_v1/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys -import warnings - -from google.cloud.redis_v1 import types -from google.cloud.redis_v1.gapic import cloud_redis_client -from google.cloud.redis_v1.gapic import enums - - -if sys.version_info[:2] == (2, 7): - message = ( - "A future version of this library will drop support for Python 2.7." - "More details about Python 2 support for Google Cloud Client Libraries" - "can be found at https://cloud.google.com/python/docs/python2-sunset/" - ) - warnings.warn(message, DeprecationWarning) - - -class CloudRedisClient(cloud_redis_client.CloudRedisClient): - __doc__ = cloud_redis_client.CloudRedisClient.__doc__ - enums = enums - - -__all__ = ("enums", "types", "CloudRedisClient") diff --git a/redis/google/cloud/redis_v1/gapic/__init__.py b/redis/google/cloud/redis_v1/gapic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/redis/google/cloud/redis_v1/gapic/cloud_redis_client.py b/redis/google/cloud/redis_v1/gapic/cloud_redis_client.py deleted file mode 100644 index 04621b9cf815..000000000000 --- a/redis/google/cloud/redis_v1/gapic/cloud_redis_client.py +++ /dev/null @@ -1,1031 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.cloud.redis.v1 CloudRedis API.""" - -import functools -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.gapic_v1.routing_header -import google.api_core.grpc_helpers -import google.api_core.operation -import google.api_core.operations_v1 -import google.api_core.page_iterator -import google.api_core.path_template -import grpc - -from google.cloud.redis_v1.gapic import cloud_redis_client_config -from google.cloud.redis_v1.gapic import enums -from google.cloud.redis_v1.gapic.transports import cloud_redis_grpc_transport -from google.cloud.redis_v1.proto import cloud_redis_pb2 -from google.cloud.redis_v1.proto import cloud_redis_pb2_grpc -from google.longrunning import operations_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-redis").version - - -class CloudRedisClient(object): - """ - Configures and manages Cloud Memorystore for Redis instances - - Google Cloud Memorystore for Redis v1 - - The ``redis.googleapis.com`` service implements the Google Cloud - Memorystore for Redis API and defines the following resource model for - managing Redis instances: - - - The service works with a collection of cloud projects, named: - ``/projects/*`` - - Each project has a collection of available locations, named: - ``/locations/*`` - - Each location has a collection of Redis instances, named: - ``/instances/*`` - - As such, Redis instances are resources of the form: - ``/projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - - Note that location\_id must be referring to a GCP ``region``; for - example: - - - ``projects/redpepper-1290/locations/us-central1/instances/my-redis`` - """ - - SERVICE_ADDRESS = "redis.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.redis.v1.CloudRedis" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - CloudRedisClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - @classmethod - def instance_path(cls, project, location, instance): - """Return a fully-qualified instance string.""" - return google.api_core.path_template.expand( - "projects/{project}/locations/{location}/instances/{instance}", - project=project, - location=location, - instance=instance, - ) - - @classmethod - def location_path(cls, project, location): - """Return a fully-qualified location string.""" - return google.api_core.path_template.expand( - "projects/{project}/locations/{location}", - project=project, - location=location, - ) - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.CloudRedisGrpcTransport, - Callable[[~.Credentials, type], ~.CloudRedisGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = cloud_redis_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=cloud_redis_grpc_transport.CloudRedisGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = cloud_redis_grpc_transport.CloudRedisGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def list_instances( - self, - parent, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Lists all Redis instances owned by a project in either the specified - location (region) or all locations. - - The location should have the following format: - - - ``projects/{project_id}/locations/{location_id}`` - - If ``location_id`` is specified as ``-`` (wildcard), then all regions - available to the project are queried, and the results are aggregated. - - Example: - >>> from google.cloud import redis_v1 - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> parent = client.location_path('[PROJECT]', '[LOCATION]') - >>> - >>> # Iterate over all results - >>> for element in client.list_instances(parent): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_instances(parent).pages: - ... for element in page: - ... # process element - ... pass - - Args: - parent (str): Required. The resource name of the instance location using the form: - ``projects/{project_id}/locations/{location_id}`` where ``location_id`` - refers to a GCP region. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.PageIterator` instance. - An iterable of :class:`~google.cloud.redis_v1.types.Instance` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_instances" not in self._inner_api_calls: - self._inner_api_calls[ - "list_instances" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_instances, - default_retry=self._method_configs["ListInstances"].retry, - default_timeout=self._method_configs["ListInstances"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.ListInstancesRequest( - parent=parent, page_size=page_size - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_instances"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="instances", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def get_instance( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets the details of a specific Redis instance. - - Example: - >>> from google.cloud import redis_v1 - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> name = client.instance_path('[PROJECT]', '[LOCATION]', '[INSTANCE]') - >>> - >>> response = client.get_instance(name) - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1.types.Instance` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "get_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_instance, - default_retry=self._method_configs["GetInstance"].retry, - default_timeout=self._method_configs["GetInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.GetInstanceRequest(name=name) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def create_instance( - self, - parent, - instance_id, - instance, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Creates a Redis instance based on the specified tier and memory size. - - By default, the instance is accessible from the project's `default - network `__. - - The creation is executed asynchronously and callers may check the - returned operation to track its progress. Once the operation is - completed the Redis instance will be fully functional. Completed - longrunning.Operation will contain the new instance object in the - response field. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1 - >>> from google.cloud.redis_v1 import enums - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> parent = client.location_path('[PROJECT]', '[LOCATION]') - >>> instance_id = 'test_instance' - >>> tier = enums.Instance.Tier.BASIC - >>> memory_size_gb = 1 - >>> instance = {'tier': tier, 'memory_size_gb': memory_size_gb} - >>> - >>> response = client.create_instance(parent, instance_id, instance) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - parent (str): Required. The resource name of the instance location using the form: - ``projects/{project_id}/locations/{location_id}`` where ``location_id`` - refers to a GCP region. - instance_id (str): Required. The logical name of the Redis instance in the customer project - with the following restrictions: - - - Must contain only lowercase letters, numbers, and hyphens. - - Must start with a letter. - - Must be between 1-40 characters. - - Must end with a number or a letter. - - Must be unique within the customer project / location - instance (Union[dict, ~google.cloud.redis_v1.types.Instance]): Required. A Redis [Instance] resource - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1.types.Instance` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "create_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "create_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_instance, - default_retry=self._method_configs["CreateInstance"].retry, - default_timeout=self._method_configs["CreateInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.CreateInstanceRequest( - parent=parent, instance_id=instance_id, instance=instance - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["create_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=cloud_redis_pb2.OperationMetadata, - ) - - def update_instance( - self, - update_mask, - instance, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Updates the metadata and configuration of a specific Redis instance. - - Completed longrunning.Operation will contain the new instance object - in the response field. The returned operation is automatically deleted - after a few hours, so there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1 - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> paths_element = 'display_name' - >>> paths_element_2 = 'memory_size_gb' - >>> paths = [paths_element, paths_element_2] - >>> update_mask = {'paths': paths} - >>> display_name = ' instance.memory_size_gb=4' - >>> instance = {'display_name': display_name} - >>> - >>> response = client.update_instance(update_mask, instance) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - update_mask (Union[dict, ~google.cloud.redis_v1.types.FieldMask]): Required. Mask of fields to update. At least one path must be supplied - in this field. The elements of the repeated paths field may only include - these fields from ``Instance``: - - - ``displayName`` - - ``labels`` - - ``memorySizeGb`` - - ``redisConfig`` - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1.types.FieldMask` - instance (Union[dict, ~google.cloud.redis_v1.types.Instance]): Required. Update description. Only fields specified in update\_mask are - updated. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1.types.Instance` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "update_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "update_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.update_instance, - default_retry=self._method_configs["UpdateInstance"].retry, - default_timeout=self._method_configs["UpdateInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.UpdateInstanceRequest( - update_mask=update_mask, instance=instance - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("instance.name", instance.name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["update_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=cloud_redis_pb2.OperationMetadata, - ) - - def import_instance( - self, - name, - input_config, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - - Redis may stop serving during this operation. Instance state will be - IMPORTING for entire operation. When complete, the instance will contain - only data from the imported file. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1 - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> # TODO: Initialize `name`: - >>> name = '' - >>> - >>> # TODO: Initialize `input_config`: - >>> input_config = {} - >>> - >>> response = client.import_instance(name, input_config) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - input_config (Union[dict, ~google.cloud.redis_v1.types.InputConfig]): Required. Specify data to be imported. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1.types.InputConfig` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "import_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "import_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.import_instance, - default_retry=self._method_configs["ImportInstance"].retry, - default_timeout=self._method_configs["ImportInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.ImportInstanceRequest( - name=name, input_config=input_config - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["import_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=cloud_redis_pb2.OperationMetadata, - ) - - def export_instance( - self, - name, - output_config, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Export Redis instance data into a Redis RDB format file in Cloud Storage. - - Redis will continue serving during this operation. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1 - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> # TODO: Initialize `name`: - >>> name = '' - >>> - >>> # TODO: Initialize `output_config`: - >>> output_config = {} - >>> - >>> response = client.export_instance(name, output_config) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - output_config (Union[dict, ~google.cloud.redis_v1.types.OutputConfig]): Required. Specify data to be exported. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1.types.OutputConfig` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "export_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "export_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.export_instance, - default_retry=self._method_configs["ExportInstance"].retry, - default_timeout=self._method_configs["ExportInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.ExportInstanceRequest( - name=name, output_config=output_config - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["export_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=cloud_redis_pb2.OperationMetadata, - ) - - def failover_instance( - self, - name, - data_protection_mode=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Initiates a failover of the master node to current replica node for a - specific STANDARD tier Cloud Memorystore for Redis instance. - - Example: - >>> from google.cloud import redis_v1 - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> name = client.instance_path('[PROJECT]', '[LOCATION]', '[INSTANCE]') - >>> - >>> response = client.failover_instance(name) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - data_protection_mode (~google.cloud.redis_v1.types.DataProtectionMode): Optional. Available data protection modes that the user can choose. If - it's unspecified, data protection mode will be LIMITED\_DATA\_LOSS by - default. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "failover_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "failover_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.failover_instance, - default_retry=self._method_configs["FailoverInstance"].retry, - default_timeout=self._method_configs["FailoverInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.FailoverInstanceRequest( - name=name, data_protection_mode=data_protection_mode - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["failover_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=cloud_redis_pb2.OperationMetadata, - ) - - def delete_instance( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Deletes a specific Redis instance. Instance stops serving and data is - deleted. - - Example: - >>> from google.cloud import redis_v1 - >>> - >>> client = redis_v1.CloudRedisClient() - >>> - >>> name = client.instance_path('[PROJECT]', '[LOCATION]', '[INSTANCE]') - >>> - >>> response = client.delete_instance(name) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "delete_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "delete_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_instance, - default_retry=self._method_configs["DeleteInstance"].retry, - default_timeout=self._method_configs["DeleteInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.DeleteInstanceRequest(name=name) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["delete_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - empty_pb2.Empty, - metadata_type=cloud_redis_pb2.OperationMetadata, - ) diff --git a/redis/google/cloud/redis_v1/gapic/cloud_redis_client_config.py b/redis/google/cloud/redis_v1/gapic/cloud_redis_client_config.py deleted file mode 100644 index 9d0264891f0b..000000000000 --- a/redis/google/cloud/redis_v1/gapic/cloud_redis_client_config.py +++ /dev/null @@ -1,63 +0,0 @@ -config = { - "interfaces": { - "google.cloud.redis.v1.CloudRedis": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "ListInstances": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "GetInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "CreateInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "UpdateInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "ImportInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "ExportInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "FailoverInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "DeleteInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/redis/google/cloud/redis_v1/gapic/enums.py b/redis/google/cloud/redis_v1/gapic/enums.py deleted file mode 100644 index d5a628a8cab5..000000000000 --- a/redis/google/cloud/redis_v1/gapic/enums.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class FailoverInstanceRequest(object): - class DataProtectionMode(enum.IntEnum): - """ - Attributes: - DATA_PROTECTION_MODE_UNSPECIFIED (int): Defaults to LIMITED\_DATA\_LOSS if a data protection mode is not - specified. - LIMITED_DATA_LOSS (int): Instance failover will be protected with data loss control. More - specifically, the failover will only be performed if the current - replication offset diff between master and replica is under a certain - threshold. - FORCE_DATA_LOSS (int): Instance failover will be performed without data loss control. - """ - - DATA_PROTECTION_MODE_UNSPECIFIED = 0 - LIMITED_DATA_LOSS = 1 - FORCE_DATA_LOSS = 2 - - -class Instance(object): - class State(enum.IntEnum): - """ - Represents the different states of a Redis instance. - - Attributes: - STATE_UNSPECIFIED (int): Not set. - CREATING (int): Redis instance is being created. - READY (int): Redis instance has been created and is fully usable. - UPDATING (int): Redis instance configuration is being updated. Certain kinds of updates - may cause the instance to become unusable while the update is in - progress. - DELETING (int): Redis instance is being deleted. - REPAIRING (int): Redis instance is being repaired and may be unusable. - MAINTENANCE (int): Maintenance is being performed on this Redis instance. - IMPORTING (int): Redis instance is importing data (availability may be affected). - FAILING_OVER (int): Redis instance is failing over (availability may be affected). - """ - - STATE_UNSPECIFIED = 0 - CREATING = 1 - READY = 2 - UPDATING = 3 - DELETING = 4 - REPAIRING = 5 - MAINTENANCE = 6 - IMPORTING = 8 - FAILING_OVER = 9 - - class Tier(enum.IntEnum): - """ - Available service tiers to choose from - - Attributes: - TIER_UNSPECIFIED (int): Not set. - BASIC (int): BASIC tier: standalone instance - STANDARD_HA (int): STANDARD\_HA tier: highly available primary/replica instances - """ - - TIER_UNSPECIFIED = 0 - BASIC = 1 - STANDARD_HA = 3 diff --git a/redis/google/cloud/redis_v1/gapic/transports/__init__.py b/redis/google/cloud/redis_v1/gapic/transports/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/redis/google/cloud/redis_v1/gapic/transports/cloud_redis_grpc_transport.py b/redis/google/cloud/redis_v1/gapic/transports/cloud_redis_grpc_transport.py deleted file mode 100644 index 3cb1ef684dea..000000000000 --- a/redis/google/cloud/redis_v1/gapic/transports/cloud_redis_grpc_transport.py +++ /dev/null @@ -1,256 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers -import google.api_core.operations_v1 - -from google.cloud.redis_v1.proto import cloud_redis_pb2_grpc - - -class CloudRedisGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.redis.v1 CloudRedis API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, channel=None, credentials=None, address="redis.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = {"cloud_redis_stub": cloud_redis_pb2_grpc.CloudRedisStub(channel)} - - # Because this API includes a method that returns a - # long-running operation (proto: google.longrunning.Operation), - # instantiate an LRO client. - self._operations_client = google.api_core.operations_v1.OperationsClient( - channel - ) - - @classmethod - def create_channel( - cls, address="redis.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def list_instances(self): - """Return the gRPC stub for :meth:`CloudRedisClient.list_instances`. - - Lists all Redis instances owned by a project in either the specified - location (region) or all locations. - - The location should have the following format: - - - ``projects/{project_id}/locations/{location_id}`` - - If ``location_id`` is specified as ``-`` (wildcard), then all regions - available to the project are queried, and the results are aggregated. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].ListInstances - - @property - def get_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.get_instance`. - - Gets the details of a specific Redis instance. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].GetInstance - - @property - def create_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.create_instance`. - - Creates a Redis instance based on the specified tier and memory size. - - By default, the instance is accessible from the project's `default - network `__. - - The creation is executed asynchronously and callers may check the - returned operation to track its progress. Once the operation is - completed the Redis instance will be fully functional. Completed - longrunning.Operation will contain the new instance object in the - response field. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].CreateInstance - - @property - def update_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.update_instance`. - - Updates the metadata and configuration of a specific Redis instance. - - Completed longrunning.Operation will contain the new instance object - in the response field. The returned operation is automatically deleted - after a few hours, so there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].UpdateInstance - - @property - def import_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.import_instance`. - - Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - - Redis may stop serving during this operation. Instance state will be - IMPORTING for entire operation. When complete, the instance will contain - only data from the imported file. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].ImportInstance - - @property - def export_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.export_instance`. - - Export Redis instance data into a Redis RDB format file in Cloud Storage. - - Redis will continue serving during this operation. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].ExportInstance - - @property - def failover_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.failover_instance`. - - Initiates a failover of the master node to current replica node for a - specific STANDARD tier Cloud Memorystore for Redis instance. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].FailoverInstance - - @property - def delete_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.delete_instance`. - - Deletes a specific Redis instance. Instance stops serving and data is - deleted. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].DeleteInstance diff --git a/redis/google/cloud/redis_v1/proto/__init__.py b/redis/google/cloud/redis_v1/proto/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/redis/google/cloud/redis_v1/proto/cloud_redis.proto b/redis/google/cloud/redis_v1/proto/cloud_redis.proto deleted file mode 100644 index 1c9cd495da6e..000000000000 --- a/redis/google/cloud/redis_v1/proto/cloud_redis.proto +++ /dev/null @@ -1,579 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.cloud.redis.v1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/api/resource.proto"; -import "google/longrunning/operations.proto"; -import "google/protobuf/field_mask.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "google.golang.org/genproto/googleapis/cloud/redis/v1;redis"; -option java_multiple_files = true; -option java_outer_classname = "CloudRedisServiceV1Proto"; -option java_package = "com.google.cloud.redis.v1"; - -// Configures and manages Cloud Memorystore for Redis instances -// -// Google Cloud Memorystore for Redis v1 -// -// The `redis.googleapis.com` service implements the Google Cloud Memorystore -// for Redis API and defines the following resource model for managing Redis -// instances: -// * The service works with a collection of cloud projects, named: `/projects/*` -// * Each project has a collection of available locations, named: `/locations/*` -// * Each location has a collection of Redis instances, named: `/instances/*` -// * As such, Redis instances are resources of the form: -// `/projects/{project_id}/locations/{location_id}/instances/{instance_id}` -// -// Note that location_id must be referring to a GCP `region`; for example: -// * `projects/redpepper-1290/locations/us-central1/instances/my-redis` -service CloudRedis { - option (google.api.default_host) = "redis.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Lists all Redis instances owned by a project in either the specified - // location (region) or all locations. - // - // The location should have the following format: - // * `projects/{project_id}/locations/{location_id}` - // - // If `location_id` is specified as `-` (wildcard), then all regions - // available to the project are queried, and the results are aggregated. - rpc ListInstances(ListInstancesRequest) returns (ListInstancesResponse) { - option (google.api.http) = { - get: "/v1/{parent=projects/*/locations/*}/instances" - }; - option (google.api.method_signature) = "parent"; - } - - // Gets the details of a specific Redis instance. - rpc GetInstance(GetInstanceRequest) returns (Instance) { - option (google.api.http) = { - get: "/v1/{name=projects/*/locations/*/instances/*}" - }; - option (google.api.method_signature) = "name"; - } - - // Creates a Redis instance based on the specified tier and memory size. - // - // By default, the instance is accessible from the project's - // [default network](/compute/docs/networks-and-firewalls#networks). - // - // The creation is executed asynchronously and callers may check the returned - // operation to track its progress. Once the operation is completed the Redis - // instance will be fully functional. Completed longrunning.Operation will - // contain the new instance object in the response field. - // - // The returned operation is automatically deleted after a few hours, so there - // is no need to call DeleteOperation. - rpc CreateInstance(CreateInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{parent=projects/*/locations/*}/instances" - body: "instance" - }; - option (google.api.method_signature) = "parent,instance_id,instance"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1.Instance" - metadata_type: "google.cloud.redis.v1.OperationMetadata" - }; - } - - // Updates the metadata and configuration of a specific Redis instance. - // - // Completed longrunning.Operation will contain the new instance object - // in the response field. The returned operation is automatically deleted - // after a few hours, so there is no need to call DeleteOperation. - rpc UpdateInstance(UpdateInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - patch: "/v1/{instance.name=projects/*/locations/*/instances/*}" - body: "instance" - }; - option (google.api.method_signature) = "update_mask,instance"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1.Instance" - metadata_type: "google.cloud.redis.v1.OperationMetadata" - }; - } - - // Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - // - // Redis may stop serving during this operation. Instance state will be - // IMPORTING for entire operation. When complete, the instance will contain - // only data from the imported file. - // - // The returned operation is automatically deleted after a few hours, so - // there is no need to call DeleteOperation. - rpc ImportInstance(ImportInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=projects/*/locations/*/instances/*}:import" - body: "*" - }; - option (google.api.method_signature) = "name,input_config"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1.Instance" - metadata_type: "google.cloud.redis.v1.OperationMetadata" - }; - } - - // Export Redis instance data into a Redis RDB format file in Cloud Storage. - // - // Redis will continue serving during this operation. - // - // The returned operation is automatically deleted after a few hours, so - // there is no need to call DeleteOperation. - rpc ExportInstance(ExportInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=projects/*/locations/*/instances/*}:export" - body: "*" - }; - option (google.api.method_signature) = "name,output_config"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1.Instance" - metadata_type: "google.cloud.redis.v1.OperationMetadata" - }; - } - - // Initiates a failover of the master node to current replica node for a - // specific STANDARD tier Cloud Memorystore for Redis instance. - rpc FailoverInstance(FailoverInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/{name=projects/*/locations/*/instances/*}:failover" - body: "*" - }; - option (google.api.method_signature) = "name,data_protection_mode"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1.Instance" - metadata_type: "google.cloud.redis.v1.OperationMetadata" - }; - } - - // Deletes a specific Redis instance. Instance stops serving and data is - // deleted. - rpc DeleteInstance(DeleteInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - delete: "/v1/{name=projects/*/locations/*/instances/*}" - }; - option (google.api.method_signature) = "name"; - option (google.longrunning.operation_info) = { - response_type: "google.protobuf.Empty" - metadata_type: "google.cloud.redis.v1.OperationMetadata" - }; - } -} - -// A Google Cloud Redis instance. -message Instance { - option (google.api.resource) = { - type: "redis.googleapis.com/Instance" - pattern: "projects/{project}/locations/{location}/instances/{instance}" - }; - - // Represents the different states of a Redis instance. - enum State { - // Not set. - STATE_UNSPECIFIED = 0; - - // Redis instance is being created. - CREATING = 1; - - // Redis instance has been created and is fully usable. - READY = 2; - - // Redis instance configuration is being updated. Certain kinds of updates - // may cause the instance to become unusable while the update is in - // progress. - UPDATING = 3; - - // Redis instance is being deleted. - DELETING = 4; - - // Redis instance is being repaired and may be unusable. - REPAIRING = 5; - - // Maintenance is being performed on this Redis instance. - MAINTENANCE = 6; - - // Redis instance is importing data (availability may be affected). - IMPORTING = 8; - - // Redis instance is failing over (availability may be affected). - FAILING_OVER = 9; - } - - // Available service tiers to choose from - enum Tier { - // Not set. - TIER_UNSPECIFIED = 0; - - // BASIC tier: standalone instance - BASIC = 1; - - // STANDARD_HA tier: highly available primary/replica instances - STANDARD_HA = 3; - } - - // Required. Unique name of the resource in this scope including project and - // location using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // - // Note: Redis instances are managed and addressed at regional level so - // location_id here refers to a GCP region; however, users may choose which - // specific zone (or collection of zones for cross-zone instances) an instance - // should be provisioned in. Refer to [location_id] and - // [alternative_location_id] fields for more details. - string name = 1 [(google.api.field_behavior) = REQUIRED]; - - // An arbitrary and optional user-provided name for the instance. - string display_name = 2; - - // Resource labels to represent user provided metadata - map labels = 3; - - // Optional. The zone where the instance will be provisioned. If not provided, - // the service will choose a zone for the instance. For STANDARD_HA tier, - // instances will be created across two zones for protection against zonal - // failures. If [alternative_location_id] is also provided, it must be - // different from [location_id]. - string location_id = 4 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. Only applicable to STANDARD_HA tier which protects the instance - // against zonal failures by provisioning it across two zones. If provided, it - // must be a different zone from the one provided in [location_id]. - string alternative_location_id = 5 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. The version of Redis software. - // If not provided, latest supported version will be used. Updating the - // version will perform an upgrade/downgrade to the new version. Currently, - // the supported values are: - // - // * `REDIS_4_0` for Redis 4.0 compatibility (default) - // * `REDIS_3_2` for Redis 3.2 compatibility - string redis_version = 7 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. The CIDR range of internal addresses that are reserved for this - // instance. If not provided, the service will choose an unused /29 block, - // for example, 10.0.0.0/29 or 192.168.0.0/29. Ranges must be unique - // and non-overlapping with existing subnets in an authorized network. - string reserved_ip_range = 9 [(google.api.field_behavior) = OPTIONAL]; - - // Output only. Hostname or IP address of the exposed Redis endpoint used by - // clients to connect to the service. - string host = 10 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The port number of the exposed Redis endpoint. - int32 port = 11 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The current zone where the Redis endpoint is placed. For Basic - // Tier instances, this will always be the same as the [location_id] - // provided by the user at creation time. For Standard Tier instances, - // this can be either [location_id] or [alternative_location_id] and can - // change after a failover event. - string current_location_id = 12 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The time the instance was created. - google.protobuf.Timestamp create_time = 13 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The current state of this instance. - State state = 14 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. Additional information about the current status of this - // instance, if available. - string status_message = 15 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Optional. Redis configuration parameters, according to - // http://redis.io/topics/config. Currently, the only supported parameters - // are: - // - // Redis 3.2 and above: - // - // * maxmemory-policy - // * notify-keyspace-events - // - // Redis 4.0 and above: - // - // * activedefrag - // * lfu-log-factor - // * lfu-decay-time - map redis_configs = 16 [(google.api.field_behavior) = OPTIONAL]; - - // Required. The service tier of the instance. - Tier tier = 17 [(google.api.field_behavior) = REQUIRED]; - - // Required. Redis memory size in GiB. - int32 memory_size_gb = 18 [(google.api.field_behavior) = REQUIRED]; - - // Optional. The full name of the Google Compute Engine - // [network](/compute/docs/networks-and-firewalls#networks) to which the - // instance is connected. If left unspecified, the `default` network - // will be used. - string authorized_network = 20 [(google.api.field_behavior) = OPTIONAL]; - - // Output only. Cloud IAM identity used by import / export operations to - // transfer data to/from Cloud Storage. Format is - // "serviceAccount:". The value may change over time - // for a given instance so should be checked before each import/export - // operation. - string persistence_iam_identity = 21 [(google.api.field_behavior) = OUTPUT_ONLY]; -} - -// Request for [ListInstances][google.cloud.redis.v1.CloudRedis.ListInstances]. -message ListInstancesRequest { - // Required. The resource name of the instance location using the form: - // `projects/{project_id}/locations/{location_id}` - // where `location_id` refers to a GCP region. - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "locations.googleapis.com/Location" - } - ]; - - // The maximum number of items to return. - // - // If not specified, a default value of 1000 will be used by the service. - // Regardless of the page_size value, the response may include a partial list - // and a caller should only rely on response's - // [next_page_token][CloudRedis.ListInstancesResponse.next_page_token] - // to determine if there are more instances left to be queried. - int32 page_size = 2; - - // The next_page_token value returned from a previous List request, - // if any. - string page_token = 3; -} - -// Response for [ListInstances][google.cloud.redis.v1.CloudRedis.ListInstances]. -message ListInstancesResponse { - // A list of Redis instances in the project in the specified location, - // or across all locations. - // - // If the `location_id` in the parent field of the request is "-", all regions - // available to the project are queried, and the results aggregated. - // If in such an aggregated query a location is unavailable, a dummy Redis - // entry is included in the response with the "name" field set to a value of - // the form projects/{project_id}/locations/{location_id}/instances/- and the - // "status" field set to ERROR and "status_message" field set to "location not - // available for ListInstances". - repeated Instance instances = 1; - - // Token to retrieve the next page of results, or empty if there are no more - // results in the list. - string next_page_token = 2; - - // Locations that could not be reached. - repeated string unreachable = 3; -} - -// Request for [GetInstance][google.cloud.redis.v1.CloudRedis.GetInstance]. -message GetInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "redis.googleapis.com/Instance" - } - ]; -} - -// Request for [CreateInstance][google.cloud.redis.v1.CloudRedis.CreateInstance]. -message CreateInstanceRequest { - // Required. The resource name of the instance location using the form: - // `projects/{project_id}/locations/{location_id}` - // where `location_id` refers to a GCP region. - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "locations.googleapis.com/Location" - } - ]; - - // Required. The logical name of the Redis instance in the customer project - // with the following restrictions: - // - // * Must contain only lowercase letters, numbers, and hyphens. - // * Must start with a letter. - // * Must be between 1-40 characters. - // * Must end with a number or a letter. - // * Must be unique within the customer project / location - string instance_id = 2 [(google.api.field_behavior) = REQUIRED]; - - // Required. A Redis [Instance] resource - Instance instance = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// Request for [UpdateInstance][google.cloud.redis.v1.CloudRedis.UpdateInstance]. -message UpdateInstanceRequest { - // Required. Mask of fields to update. At least one path must be supplied in - // this field. The elements of the repeated paths field may only include these - // fields from [Instance][CloudRedis.Instance]: - // - // * `displayName` - // * `labels` - // * `memorySizeGb` - // * `redisConfig` - google.protobuf.FieldMask update_mask = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. Update description. - // Only fields specified in update_mask are updated. - Instance instance = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// Request for [DeleteInstance][google.cloud.redis.v1.CloudRedis.DeleteInstance]. -message DeleteInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "redis.googleapis.com/Instance" - } - ]; -} - -// The Cloud Storage location for the input content -message GcsSource { - // Required. Source data URI. (e.g. 'gs://my_bucket/my_object'). - string uri = 1 [(google.api.field_behavior) = REQUIRED]; -} - -// The input content -message InputConfig { - // Required. Specify source location of input data - oneof source { - // Google Cloud Storage location where input content is located. - GcsSource gcs_source = 1; - } -} - -// Request for [Import][google.cloud.redis.v1.CloudRedis.ImportInstance]. -message ImportInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. Specify data to be imported. - InputConfig input_config = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// The Cloud Storage location for the output content -message GcsDestination { - // Required. Data destination URI (e.g. - // 'gs://my_bucket/my_object'). Existing files will be overwritten. - string uri = 1 [(google.api.field_behavior) = REQUIRED]; -} - -// The output content -message OutputConfig { - // Required. Specify destination location of output data - oneof destination { - // Google Cloud Storage destination for output content. - GcsDestination gcs_destination = 1; - } -} - -// Request for [Export][google.cloud.redis.v1.CloudRedis.ExportInstance]. -message ExportInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. Specify data to be exported. - OutputConfig output_config = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// Request for [Failover][google.cloud.redis.v1.CloudRedis.FailoverInstance]. -message FailoverInstanceRequest { - enum DataProtectionMode { - // Defaults to LIMITED_DATA_LOSS if a data protection mode is not - // specified. - DATA_PROTECTION_MODE_UNSPECIFIED = 0; - - // Instance failover will be protected with data loss control. More - // specifically, the failover will only be performed if the current - // replication offset diff between master and replica is under a certain - // threshold. - LIMITED_DATA_LOSS = 1; - - // Instance failover will be performed without data loss control. - FORCE_DATA_LOSS = 2; - } - - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "redis.googleapis.com/Instance" - } - ]; - - // Optional. Available data protection modes that the user can choose. If it's - // unspecified, data protection mode will be LIMITED_DATA_LOSS by default. - DataProtectionMode data_protection_mode = 2 [(google.api.field_behavior) = OPTIONAL]; -} - -// Represents the v1 metadata of the long-running operation. -message OperationMetadata { - // Creation timestamp. - google.protobuf.Timestamp create_time = 1; - - // End timestamp. - google.protobuf.Timestamp end_time = 2; - - // Operation target. - string target = 3; - - // Operation verb. - string verb = 4; - - // Operation status details. - string status_detail = 5; - - // Specifies if cancellation was requested for the operation. - bool cancel_requested = 6; - - // API version. - string api_version = 7; -} - -// This location metadata represents additional configuration options for a -// given location where a Redis instance may be created. All fields are output -// only. It is returned as content of the -// `google.cloud.location.Location.metadata` field. -message LocationMetadata { - // Output only. The set of available zones in the location. The map is keyed - // by the lowercase ID of each zone, as defined by GCE. These keys can be - // specified in `location_id` or `alternative_location_id` fields when - // creating a Redis instance. - map available_zones = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; -} - -// Defines specific information for a particular zone. Currently empty and -// reserved for future use only. -message ZoneMetadata { - -} diff --git a/redis/google/cloud/redis_v1/proto/cloud_redis_pb2.py b/redis/google/cloud/redis_v1/proto/cloud_redis_pb2.py deleted file mode 100644 index fc6e1400e0b4..000000000000 --- a/redis/google/cloud/redis_v1/proto/cloud_redis_pb2.py +++ /dev/null @@ -1,2313 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/redis_v1/proto/cloud_redis.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) -from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 -from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/redis_v1/proto/cloud_redis.proto", - package="google.cloud.redis.v1", - syntax="proto3", - serialized_options=_b( - "\n\031com.google.cloud.redis.v1B\030CloudRedisServiceV1ProtoP\001Z:google.golang.org/genproto/googleapis/cloud/redis/v1;redis" - ), - serialized_pb=_b( - '\n-google/cloud/redis_v1/proto/cloud_redis.proto\x12\x15google.cloud.redis.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a#google/longrunning/operations.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xc6\x08\n\x08Instance\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12;\n\x06labels\x18\x03 \x03(\x0b\x32+.google.cloud.redis.v1.Instance.LabelsEntry\x12\x18\n\x0blocation_id\x18\x04 \x01(\tB\x03\xe0\x41\x01\x12$\n\x17\x61lternative_location_id\x18\x05 \x01(\tB\x03\xe0\x41\x01\x12\x1a\n\rredis_version\x18\x07 \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11reserved_ip_range\x18\t \x01(\tB\x03\xe0\x41\x01\x12\x11\n\x04host\x18\n \x01(\tB\x03\xe0\x41\x03\x12\x11\n\x04port\x18\x0b \x01(\x05\x42\x03\xe0\x41\x03\x12 \n\x13\x63urrent_location_id\x18\x0c \x01(\tB\x03\xe0\x41\x03\x12\x34\n\x0b\x63reate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12\x39\n\x05state\x18\x0e \x01(\x0e\x32%.google.cloud.redis.v1.Instance.StateB\x03\xe0\x41\x03\x12\x1b\n\x0estatus_message\x18\x0f \x01(\tB\x03\xe0\x41\x03\x12M\n\rredis_configs\x18\x10 \x03(\x0b\x32\x31.google.cloud.redis.v1.Instance.RedisConfigsEntryB\x03\xe0\x41\x01\x12\x37\n\x04tier\x18\x11 \x01(\x0e\x32$.google.cloud.redis.v1.Instance.TierB\x03\xe0\x41\x02\x12\x1b\n\x0ememory_size_gb\x18\x12 \x01(\x05\x42\x03\xe0\x41\x02\x12\x1f\n\x12\x61uthorized_network\x18\x14 \x01(\tB\x03\xe0\x41\x01\x12%\n\x18persistence_iam_identity\x18\x15 \x01(\tB\x03\xe0\x41\x03\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x33\n\x11RedisConfigsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x94\x01\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\x0c\n\x08\x43REATING\x10\x01\x12\t\n\x05READY\x10\x02\x12\x0c\n\x08UPDATING\x10\x03\x12\x0c\n\x08\x44\x45LETING\x10\x04\x12\r\n\tREPAIRING\x10\x05\x12\x0f\n\x0bMAINTENANCE\x10\x06\x12\r\n\tIMPORTING\x10\x08\x12\x10\n\x0c\x46\x41ILING_OVER\x10\t"8\n\x04Tier\x12\x14\n\x10TIER_UNSPECIFIED\x10\x00\x12\t\n\x05\x42\x41SIC\x10\x01\x12\x0f\n\x0bSTANDARD_HA\x10\x03:`\xea\x41]\n\x1dredis.googleapis.com/Instance\x12\x82\xd3\xe4\x93\x02/\x12-/v1/{parent=projects/*/locations/*}/instances\xda\x41\x06parent\x12\x97\x01\n\x0bGetInstance\x12).google.cloud.redis.v1.GetInstanceRequest\x1a\x1f.google.cloud.redis.v1.Instance"<\x82\xd3\xe4\x93\x02/\x12-/v1/{name=projects/*/locations/*/instances/*}\xda\x41\x04name\x12\x89\x02\n\x0e\x43reateInstance\x12,.google.cloud.redis.v1.CreateInstanceRequest\x1a\x1d.google.longrunning.Operation"\xa9\x01\x82\xd3\xe4\x93\x02\x39"-/v1/{parent=projects/*/locations/*}/instances:\x08instance\xda\x41\x1bparent,instance_id,instance\xca\x41I\n\x1egoogle.cloud.redis.v1.Instance\x12\'google.cloud.redis.v1.OperationMetadata\x12\x8b\x02\n\x0eUpdateInstance\x12,.google.cloud.redis.v1.UpdateInstanceRequest\x1a\x1d.google.longrunning.Operation"\xab\x01\x82\xd3\xe4\x93\x02\x42\x32\x36/v1/{instance.name=projects/*/locations/*/instances/*}:\x08instance\xda\x41\x14update_mask,instance\xca\x41I\n\x1egoogle.cloud.redis.v1.Instance\x12\'google.cloud.redis.v1.OperationMetadata\x12\xff\x01\n\x0eImportInstance\x12,.google.cloud.redis.v1.ImportInstanceRequest\x1a\x1d.google.longrunning.Operation"\x9f\x01\x82\xd3\xe4\x93\x02\x39"4/v1/{name=projects/*/locations/*/instances/*}:import:\x01*\xda\x41\x11name,input_config\xca\x41I\n\x1egoogle.cloud.redis.v1.Instance\x12\'google.cloud.redis.v1.OperationMetadata\x12\x80\x02\n\x0e\x45xportInstance\x12,.google.cloud.redis.v1.ExportInstanceRequest\x1a\x1d.google.longrunning.Operation"\xa0\x01\x82\xd3\xe4\x93\x02\x39"4/v1/{name=projects/*/locations/*/instances/*}:export:\x01*\xda\x41\x12name,output_config\xca\x41I\n\x1egoogle.cloud.redis.v1.Instance\x12\'google.cloud.redis.v1.OperationMetadata\x12\x8d\x02\n\x10\x46\x61iloverInstance\x12..google.cloud.redis.v1.FailoverInstanceRequest\x1a\x1d.google.longrunning.Operation"\xa9\x01\x82\xd3\xe4\x93\x02;"6/v1/{name=projects/*/locations/*/instances/*}:failover:\x01*\xda\x41\x19name,data_protection_mode\xca\x41I\n\x1egoogle.cloud.redis.v1.Instance\x12\'google.cloud.redis.v1.OperationMetadata\x12\xde\x01\n\x0e\x44\x65leteInstance\x12,.google.cloud.redis.v1.DeleteInstanceRequest\x1a\x1d.google.longrunning.Operation"\x7f\x82\xd3\xe4\x93\x02/*-/v1/{name=projects/*/locations/*/instances/*}\xda\x41\x04name\xca\x41@\n\x15google.protobuf.Empty\x12\'google.cloud.redis.v1.OperationMetadata\x1aH\xca\x41\x14redis.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformBs\n\x19\x63om.google.cloud.redis.v1B\x18\x43loudRedisServiceV1ProtoP\x01Z:google.golang.org/genproto/googleapis/cloud/redis/v1;redisb\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_api_dot_resource__pb2.DESCRIPTOR, - google_dot_longrunning_dot_operations__pb2.DESCRIPTOR, - google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR, - google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, - ], -) - - -_INSTANCE_STATE = _descriptor.EnumDescriptor( - name="State", - full_name="google.cloud.redis.v1.Instance.State", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="STATE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="CREATING", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="READY", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="UPDATING", index=3, number=3, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="DELETING", index=4, number=4, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="REPAIRING", index=5, number=5, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="MAINTENANCE", index=6, number=6, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="IMPORTING", index=7, number=8, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="FAILING_OVER", index=8, number=9, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1082, - serialized_end=1230, -) -_sym_db.RegisterEnumDescriptor(_INSTANCE_STATE) - -_INSTANCE_TIER = _descriptor.EnumDescriptor( - name="Tier", - full_name="google.cloud.redis.v1.Instance.Tier", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="TIER_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="BASIC", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="STANDARD_HA", index=2, number=3, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1232, - serialized_end=1288, -) -_sym_db.RegisterEnumDescriptor(_INSTANCE_TIER) - -_FAILOVERINSTANCEREQUEST_DATAPROTECTIONMODE = _descriptor.EnumDescriptor( - name="DataProtectionMode", - full_name="google.cloud.redis.v1.FailoverInstanceRequest.DataProtectionMode", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="DATA_PROTECTION_MODE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="LIMITED_DATA_LOSS", - index=1, - number=1, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="FORCE_DATA_LOSS", - index=2, - number=2, - serialized_options=None, - type=None, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=2733, - serialized_end=2835, -) -_sym_db.RegisterEnumDescriptor(_FAILOVERINSTANCEREQUEST_DATAPROTECTIONMODE) - - -_INSTANCE_LABELSENTRY = _descriptor.Descriptor( - name="LabelsEntry", - full_name="google.cloud.redis.v1.Instance.LabelsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.cloud.redis.v1.Instance.LabelsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.cloud.redis.v1.Instance.LabelsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=981, - serialized_end=1026, -) - -_INSTANCE_REDISCONFIGSENTRY = _descriptor.Descriptor( - name="RedisConfigsEntry", - full_name="google.cloud.redis.v1.Instance.RedisConfigsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.cloud.redis.v1.Instance.RedisConfigsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.cloud.redis.v1.Instance.RedisConfigsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1028, - serialized_end=1079, -) - -_INSTANCE = _descriptor.Descriptor( - name="Instance", - full_name="google.cloud.redis.v1.Instance", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.redis.v1.Instance.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="display_name", - full_name="google.cloud.redis.v1.Instance.display_name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="labels", - full_name="google.cloud.redis.v1.Instance.labels", - index=2, - number=3, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="location_id", - full_name="google.cloud.redis.v1.Instance.location_id", - index=3, - number=4, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="alternative_location_id", - full_name="google.cloud.redis.v1.Instance.alternative_location_id", - index=4, - number=5, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="redis_version", - full_name="google.cloud.redis.v1.Instance.redis_version", - index=5, - number=7, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="reserved_ip_range", - full_name="google.cloud.redis.v1.Instance.reserved_ip_range", - index=6, - number=9, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="host", - full_name="google.cloud.redis.v1.Instance.host", - index=7, - number=10, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="port", - full_name="google.cloud.redis.v1.Instance.port", - index=8, - number=11, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="current_location_id", - full_name="google.cloud.redis.v1.Instance.current_location_id", - index=9, - number=12, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="create_time", - full_name="google.cloud.redis.v1.Instance.create_time", - index=10, - number=13, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="state", - full_name="google.cloud.redis.v1.Instance.state", - index=11, - number=14, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="status_message", - full_name="google.cloud.redis.v1.Instance.status_message", - index=12, - number=15, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="redis_configs", - full_name="google.cloud.redis.v1.Instance.redis_configs", - index=13, - number=16, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="tier", - full_name="google.cloud.redis.v1.Instance.tier", - index=14, - number=17, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="memory_size_gb", - full_name="google.cloud.redis.v1.Instance.memory_size_gb", - index=15, - number=18, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="authorized_network", - full_name="google.cloud.redis.v1.Instance.authorized_network", - index=16, - number=20, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="persistence_iam_identity", - full_name="google.cloud.redis.v1.Instance.persistence_iam_identity", - index=17, - number=21, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_INSTANCE_LABELSENTRY, _INSTANCE_REDISCONFIGSENTRY], - enum_types=[_INSTANCE_STATE, _INSTANCE_TIER], - serialized_options=_b( - "\352A]\n\035redis.googleapis.com/Instance\022`__ to which - the instance is connected. If left unspecified, the - ``default`` network will be used. - persistence_iam_identity: - Output only. Cloud IAM identity used by import / export - operations to transfer data to/from Cloud Storage. Format is - "serviceAccount:". The value may change over time for a given - instance so should be checked before each import/export - operation. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.Instance) - ), -) -_sym_db.RegisterMessage(Instance) -_sym_db.RegisterMessage(Instance.LabelsEntry) -_sym_db.RegisterMessage(Instance.RedisConfigsEntry) - -ListInstancesRequest = _reflection.GeneratedProtocolMessageType( - "ListInstancesRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTINSTANCESREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [ListInstances][google.cloud.redis.v1.CloudRedis.ListInstances]. - - - Attributes: - parent: - Required. The resource name of the instance location using the - form: ``projects/{project_id}/locations/{location_id}`` where - ``location_id`` refers to a GCP region. - page_size: - The maximum number of items to return. If not specified, a - default value of 1000 will be used by the service. Regardless - of the page\_size value, the response may include a partial - list and a caller should only rely on response's [next\_page\_ - token][CloudRedis.ListInstancesResponse.next\_page\_token] to - determine if there are more instances left to be queried. - page_token: - The next\_page\_token value returned from a previous List - request, if any. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.ListInstancesRequest) - ), -) -_sym_db.RegisterMessage(ListInstancesRequest) - -ListInstancesResponse = _reflection.GeneratedProtocolMessageType( - "ListInstancesResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTINSTANCESRESPONSE, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Response for - [ListInstances][google.cloud.redis.v1.CloudRedis.ListInstances]. - - - Attributes: - instances: - A list of Redis instances in the project in the specified - location, or across all locations. If the ``location_id`` in - the parent field of the request is "-", all regions available - to the project are queried, and the results aggregated. If in - such an aggregated query a location is unavailable, a dummy - Redis entry is included in the response with the "name" field - set to a value of the form - projects/{project\_id}/locations/{location\_id}/instances/- - and the "status" field set to ERROR and "status\_message" - field set to "location not available for ListInstances". - next_page_token: - Token to retrieve the next page of results, or empty if there - are no more results in the list. - unreachable: - Locations that could not be reached. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.ListInstancesResponse) - ), -) -_sym_db.RegisterMessage(ListInstancesResponse) - -GetInstanceRequest = _reflection.GeneratedProtocolMessageType( - "GetInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GETINSTANCEREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [GetInstance][google.cloud.redis.v1.CloudRedis.GetInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.GetInstanceRequest) - ), -) -_sym_db.RegisterMessage(GetInstanceRequest) - -CreateInstanceRequest = _reflection.GeneratedProtocolMessageType( - "CreateInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_CREATEINSTANCEREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [CreateInstance][google.cloud.redis.v1.CloudRedis.CreateInstance]. - - - Attributes: - parent: - Required. The resource name of the instance location using the - form: ``projects/{project_id}/locations/{location_id}`` where - ``location_id`` refers to a GCP region. - instance_id: - Required. The logical name of the Redis instance in the - customer project with the following restrictions: - Must - contain only lowercase letters, numbers, and hyphens. - Must - start with a letter. - Must be between 1-40 characters. - - Must end with a number or a letter. - Must be unique within - the customer project / location - instance: - Required. A Redis [Instance] resource - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.CreateInstanceRequest) - ), -) -_sym_db.RegisterMessage(CreateInstanceRequest) - -UpdateInstanceRequest = _reflection.GeneratedProtocolMessageType( - "UpdateInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_UPDATEINSTANCEREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [UpdateInstance][google.cloud.redis.v1.CloudRedis.UpdateInstance]. - - - Attributes: - update_mask: - Required. Mask of fields to update. At least one path must be - supplied in this field. The elements of the repeated paths - field may only include these fields from - [Instance][CloudRedis.Instance]: - ``displayName`` - - ``labels`` - ``memorySizeGb`` - ``redisConfig`` - instance: - Required. Update description. Only fields specified in - update\_mask are updated. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.UpdateInstanceRequest) - ), -) -_sym_db.RegisterMessage(UpdateInstanceRequest) - -DeleteInstanceRequest = _reflection.GeneratedProtocolMessageType( - "DeleteInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_DELETEINSTANCEREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [DeleteInstance][google.cloud.redis.v1.CloudRedis.DeleteInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.DeleteInstanceRequest) - ), -) -_sym_db.RegisterMessage(DeleteInstanceRequest) - -GcsSource = _reflection.GeneratedProtocolMessageType( - "GcsSource", - (_message.Message,), - dict( - DESCRIPTOR=_GCSSOURCE, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""The Cloud Storage location for the input content - - - Attributes: - uri: - Required. Source data URI. (e.g. - 'gs://my\_bucket/my\_object'). - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.GcsSource) - ), -) -_sym_db.RegisterMessage(GcsSource) - -InputConfig = _reflection.GeneratedProtocolMessageType( - "InputConfig", - (_message.Message,), - dict( - DESCRIPTOR=_INPUTCONFIG, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""The input content - - - Attributes: - source: - Required. Specify source location of input data - gcs_source: - Google Cloud Storage location where input content is located. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.InputConfig) - ), -) -_sym_db.RegisterMessage(InputConfig) - -ImportInstanceRequest = _reflection.GeneratedProtocolMessageType( - "ImportInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_IMPORTINSTANCEREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [Import][google.cloud.redis.v1.CloudRedis.ImportInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - input_config: - Required. Specify data to be imported. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.ImportInstanceRequest) - ), -) -_sym_db.RegisterMessage(ImportInstanceRequest) - -GcsDestination = _reflection.GeneratedProtocolMessageType( - "GcsDestination", - (_message.Message,), - dict( - DESCRIPTOR=_GCSDESTINATION, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""The Cloud Storage location for the output content - - - Attributes: - uri: - Required. Data destination URI (e.g. - 'gs://my\_bucket/my\_object'). Existing files will be - overwritten. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.GcsDestination) - ), -) -_sym_db.RegisterMessage(GcsDestination) - -OutputConfig = _reflection.GeneratedProtocolMessageType( - "OutputConfig", - (_message.Message,), - dict( - DESCRIPTOR=_OUTPUTCONFIG, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""The output content - - - Attributes: - destination: - Required. Specify destination location of output data - gcs_destination: - Google Cloud Storage destination for output content. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.OutputConfig) - ), -) -_sym_db.RegisterMessage(OutputConfig) - -ExportInstanceRequest = _reflection.GeneratedProtocolMessageType( - "ExportInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_EXPORTINSTANCEREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [Export][google.cloud.redis.v1.CloudRedis.ExportInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - output_config: - Required. Specify data to be exported. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.ExportInstanceRequest) - ), -) -_sym_db.RegisterMessage(ExportInstanceRequest) - -FailoverInstanceRequest = _reflection.GeneratedProtocolMessageType( - "FailoverInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_FAILOVERINSTANCEREQUEST, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Request for - [Failover][google.cloud.redis.v1.CloudRedis.FailoverInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - data_protection_mode: - Optional. Available data protection modes that the user can - choose. If it's unspecified, data protection mode will be - LIMITED\_DATA\_LOSS by default. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.FailoverInstanceRequest) - ), -) -_sym_db.RegisterMessage(FailoverInstanceRequest) - -OperationMetadata = _reflection.GeneratedProtocolMessageType( - "OperationMetadata", - (_message.Message,), - dict( - DESCRIPTOR=_OPERATIONMETADATA, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Represents the v1 metadata of the long-running operation. - - - Attributes: - create_time: - Creation timestamp. - end_time: - End timestamp. - target: - Operation target. - verb: - Operation verb. - status_detail: - Operation status details. - cancel_requested: - Specifies if cancellation was requested for the operation. - api_version: - API version. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.OperationMetadata) - ), -) -_sym_db.RegisterMessage(OperationMetadata) - -LocationMetadata = _reflection.GeneratedProtocolMessageType( - "LocationMetadata", - (_message.Message,), - dict( - AvailableZonesEntry=_reflection.GeneratedProtocolMessageType( - "AvailableZonesEntry", - (_message.Message,), - dict( - DESCRIPTOR=_LOCATIONMETADATA_AVAILABLEZONESENTRY, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2" - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.LocationMetadata.AvailableZonesEntry) - ), - ), - DESCRIPTOR=_LOCATIONMETADATA, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""This location metadata represents additional configuration - options for a given location where a Redis instance may be created. All - fields are output only. It is returned as content of the - ``google.cloud.location.Location.metadata`` field. - - - Attributes: - available_zones: - Output only. The set of available zones in the location. The - map is keyed by the lowercase ID of each zone, as defined by - GCE. These keys can be specified in ``location_id`` or - ``alternative_location_id`` fields when creating a Redis - instance. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.LocationMetadata) - ), -) -_sym_db.RegisterMessage(LocationMetadata) -_sym_db.RegisterMessage(LocationMetadata.AvailableZonesEntry) - -ZoneMetadata = _reflection.GeneratedProtocolMessageType( - "ZoneMetadata", - (_message.Message,), - dict( - DESCRIPTOR=_ZONEMETADATA, - __module__="google.cloud.redis_v1.proto.cloud_redis_pb2", - __doc__="""Defines specific information for a particular zone. - Currently empty and reserved for future use only. - - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1.ZoneMetadata) - ), -) -_sym_db.RegisterMessage(ZoneMetadata) - - -DESCRIPTOR._options = None -_INSTANCE_LABELSENTRY._options = None -_INSTANCE_REDISCONFIGSENTRY._options = None -_INSTANCE.fields_by_name["name"]._options = None -_INSTANCE.fields_by_name["location_id"]._options = None -_INSTANCE.fields_by_name["alternative_location_id"]._options = None -_INSTANCE.fields_by_name["redis_version"]._options = None -_INSTANCE.fields_by_name["reserved_ip_range"]._options = None -_INSTANCE.fields_by_name["host"]._options = None -_INSTANCE.fields_by_name["port"]._options = None -_INSTANCE.fields_by_name["current_location_id"]._options = None -_INSTANCE.fields_by_name["create_time"]._options = None -_INSTANCE.fields_by_name["state"]._options = None -_INSTANCE.fields_by_name["status_message"]._options = None -_INSTANCE.fields_by_name["redis_configs"]._options = None -_INSTANCE.fields_by_name["tier"]._options = None -_INSTANCE.fields_by_name["memory_size_gb"]._options = None -_INSTANCE.fields_by_name["authorized_network"]._options = None -_INSTANCE.fields_by_name["persistence_iam_identity"]._options = None -_INSTANCE._options = None -_LISTINSTANCESREQUEST.fields_by_name["parent"]._options = None -_GETINSTANCEREQUEST.fields_by_name["name"]._options = None -_CREATEINSTANCEREQUEST.fields_by_name["parent"]._options = None -_CREATEINSTANCEREQUEST.fields_by_name["instance_id"]._options = None -_CREATEINSTANCEREQUEST.fields_by_name["instance"]._options = None -_UPDATEINSTANCEREQUEST.fields_by_name["update_mask"]._options = None -_UPDATEINSTANCEREQUEST.fields_by_name["instance"]._options = None -_DELETEINSTANCEREQUEST.fields_by_name["name"]._options = None -_GCSSOURCE.fields_by_name["uri"]._options = None -_IMPORTINSTANCEREQUEST.fields_by_name["name"]._options = None -_IMPORTINSTANCEREQUEST.fields_by_name["input_config"]._options = None -_GCSDESTINATION.fields_by_name["uri"]._options = None -_EXPORTINSTANCEREQUEST.fields_by_name["name"]._options = None -_EXPORTINSTANCEREQUEST.fields_by_name["output_config"]._options = None -_FAILOVERINSTANCEREQUEST.fields_by_name["name"]._options = None -_FAILOVERINSTANCEREQUEST.fields_by_name["data_protection_mode"]._options = None -_LOCATIONMETADATA_AVAILABLEZONESENTRY._options = None -_LOCATIONMETADATA.fields_by_name["available_zones"]._options = None - -_CLOUDREDIS = _descriptor.ServiceDescriptor( - name="CloudRedis", - full_name="google.cloud.redis.v1.CloudRedis", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\024redis.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=3275, - serialized_end=5240, - methods=[ - _descriptor.MethodDescriptor( - name="ListInstances", - full_name="google.cloud.redis.v1.CloudRedis.ListInstances", - index=0, - containing_service=None, - input_type=_LISTINSTANCESREQUEST, - output_type=_LISTINSTANCESRESPONSE, - serialized_options=_b( - "\202\323\344\223\002/\022-/v1/{parent=projects/*/locations/*}/instances\332A\006parent" - ), - ), - _descriptor.MethodDescriptor( - name="GetInstance", - full_name="google.cloud.redis.v1.CloudRedis.GetInstance", - index=1, - containing_service=None, - input_type=_GETINSTANCEREQUEST, - output_type=_INSTANCE, - serialized_options=_b( - "\202\323\344\223\002/\022-/v1/{name=projects/*/locations/*/instances/*}\332A\004name" - ), - ), - _descriptor.MethodDescriptor( - name="CreateInstance", - full_name="google.cloud.redis.v1.CloudRedis.CreateInstance", - index=2, - containing_service=None, - input_type=_CREATEINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\0029\"-/v1/{parent=projects/*/locations/*}/instances:\010instance\332A\033parent,instance_id,instance\312AI\n\036google.cloud.redis.v1.Instance\022'google.cloud.redis.v1.OperationMetadata" - ), - ), - _descriptor.MethodDescriptor( - name="UpdateInstance", - full_name="google.cloud.redis.v1.CloudRedis.UpdateInstance", - index=3, - containing_service=None, - input_type=_UPDATEINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\002B26/v1/{instance.name=projects/*/locations/*/instances/*}:\010instance\332A\024update_mask,instance\312AI\n\036google.cloud.redis.v1.Instance\022'google.cloud.redis.v1.OperationMetadata" - ), - ), - _descriptor.MethodDescriptor( - name="ImportInstance", - full_name="google.cloud.redis.v1.CloudRedis.ImportInstance", - index=4, - containing_service=None, - input_type=_IMPORTINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\0029\"4/v1/{name=projects/*/locations/*/instances/*}:import:\001*\332A\021name,input_config\312AI\n\036google.cloud.redis.v1.Instance\022'google.cloud.redis.v1.OperationMetadata" - ), - ), - _descriptor.MethodDescriptor( - name="ExportInstance", - full_name="google.cloud.redis.v1.CloudRedis.ExportInstance", - index=5, - containing_service=None, - input_type=_EXPORTINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\0029\"4/v1/{name=projects/*/locations/*/instances/*}:export:\001*\332A\022name,output_config\312AI\n\036google.cloud.redis.v1.Instance\022'google.cloud.redis.v1.OperationMetadata" - ), - ), - _descriptor.MethodDescriptor( - name="FailoverInstance", - full_name="google.cloud.redis.v1.CloudRedis.FailoverInstance", - index=6, - containing_service=None, - input_type=_FAILOVERINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\002;\"6/v1/{name=projects/*/locations/*/instances/*}:failover:\001*\332A\031name,data_protection_mode\312AI\n\036google.cloud.redis.v1.Instance\022'google.cloud.redis.v1.OperationMetadata" - ), - ), - _descriptor.MethodDescriptor( - name="DeleteInstance", - full_name="google.cloud.redis.v1.CloudRedis.DeleteInstance", - index=7, - containing_service=None, - input_type=_DELETEINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\002/*-/v1/{name=projects/*/locations/*/instances/*}\332A\004name\312A@\n\025google.protobuf.Empty\022'google.cloud.redis.v1.OperationMetadata" - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_CLOUDREDIS) - -DESCRIPTOR.services_by_name["CloudRedis"] = _CLOUDREDIS - -# @@protoc_insertion_point(module_scope) diff --git a/redis/google/cloud/redis_v1/proto/cloud_redis_pb2_grpc.py b/redis/google/cloud/redis_v1/proto/cloud_redis_pb2_grpc.py deleted file mode 100644 index e066fbf19a23..000000000000 --- a/redis/google/cloud/redis_v1/proto/cloud_redis_pb2_grpc.py +++ /dev/null @@ -1,235 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.redis_v1.proto import ( - cloud_redis_pb2 as google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2, -) -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) - - -class CloudRedisStub(object): - """Configures and manages Cloud Memorystore for Redis instances - - Google Cloud Memorystore for Redis v1 - - The `redis.googleapis.com` service implements the Google Cloud Memorystore - for Redis API and defines the following resource model for managing Redis - instances: - * The service works with a collection of cloud projects, named: `/projects/*` - * Each project has a collection of available locations, named: `/locations/*` - * Each location has a collection of Redis instances, named: `/instances/*` - * As such, Redis instances are resources of the form: - `/projects/{project_id}/locations/{location_id}/instances/{instance_id}` - - Note that location_id must be referring to a GCP `region`; for example: - * `projects/redpepper-1290/locations/us-central1/instances/my-redis` - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.ListInstances = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/ListInstances", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ListInstancesRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ListInstancesResponse.FromString, - ) - self.GetInstance = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/GetInstance", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.GetInstanceRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.Instance.FromString, - ) - self.CreateInstance = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/CreateInstance", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.CreateInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.UpdateInstance = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/UpdateInstance", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.UpdateInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.ImportInstance = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/ImportInstance", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ImportInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.ExportInstance = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/ExportInstance", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ExportInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.FailoverInstance = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/FailoverInstance", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.FailoverInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.DeleteInstance = channel.unary_unary( - "/google.cloud.redis.v1.CloudRedis/DeleteInstance", - request_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.DeleteInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - - -class CloudRedisServicer(object): - """Configures and manages Cloud Memorystore for Redis instances - - Google Cloud Memorystore for Redis v1 - - The `redis.googleapis.com` service implements the Google Cloud Memorystore - for Redis API and defines the following resource model for managing Redis - instances: - * The service works with a collection of cloud projects, named: `/projects/*` - * Each project has a collection of available locations, named: `/locations/*` - * Each location has a collection of Redis instances, named: `/instances/*` - * As such, Redis instances are resources of the form: - `/projects/{project_id}/locations/{location_id}/instances/{instance_id}` - - Note that location_id must be referring to a GCP `region`; for example: - * `projects/redpepper-1290/locations/us-central1/instances/my-redis` - """ - - def ListInstances(self, request, context): - """Lists all Redis instances owned by a project in either the specified - location (region) or all locations. - - The location should have the following format: - * `projects/{project_id}/locations/{location_id}` - - If `location_id` is specified as `-` (wildcard), then all regions - available to the project are queried, and the results are aggregated. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetInstance(self, request, context): - """Gets the details of a specific Redis instance. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def CreateInstance(self, request, context): - """Creates a Redis instance based on the specified tier and memory size. - - By default, the instance is accessible from the project's - [default network](/compute/docs/networks-and-firewalls#networks). - - The creation is executed asynchronously and callers may check the returned - operation to track its progress. Once the operation is completed the Redis - instance will be fully functional. Completed longrunning.Operation will - contain the new instance object in the response field. - - The returned operation is automatically deleted after a few hours, so there - is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def UpdateInstance(self, request, context): - """Updates the metadata and configuration of a specific Redis instance. - - Completed longrunning.Operation will contain the new instance object - in the response field. The returned operation is automatically deleted - after a few hours, so there is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ImportInstance(self, request, context): - """Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - - Redis may stop serving during this operation. Instance state will be - IMPORTING for entire operation. When complete, the instance will contain - only data from the imported file. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ExportInstance(self, request, context): - """Export Redis instance data into a Redis RDB format file in Cloud Storage. - - Redis will continue serving during this operation. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def FailoverInstance(self, request, context): - """Initiates a failover of the master node to current replica node for a - specific STANDARD tier Cloud Memorystore for Redis instance. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def DeleteInstance(self, request, context): - """Deletes a specific Redis instance. Instance stops serving and data is - deleted. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_CloudRedisServicer_to_server(servicer, server): - rpc_method_handlers = { - "ListInstances": grpc.unary_unary_rpc_method_handler( - servicer.ListInstances, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ListInstancesRequest.FromString, - response_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ListInstancesResponse.SerializeToString, - ), - "GetInstance": grpc.unary_unary_rpc_method_handler( - servicer.GetInstance, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.GetInstanceRequest.FromString, - response_serializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.Instance.SerializeToString, - ), - "CreateInstance": grpc.unary_unary_rpc_method_handler( - servicer.CreateInstance, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.CreateInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "UpdateInstance": grpc.unary_unary_rpc_method_handler( - servicer.UpdateInstance, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.UpdateInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "ImportInstance": grpc.unary_unary_rpc_method_handler( - servicer.ImportInstance, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ImportInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "ExportInstance": grpc.unary_unary_rpc_method_handler( - servicer.ExportInstance, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.ExportInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "FailoverInstance": grpc.unary_unary_rpc_method_handler( - servicer.FailoverInstance, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.FailoverInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "DeleteInstance": grpc.unary_unary_rpc_method_handler( - servicer.DeleteInstance, - request_deserializer=google_dot_cloud_dot_redis__v1_dot_proto_dot_cloud__redis__pb2.DeleteInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.redis.v1.CloudRedis", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/redis/google/cloud/redis_v1/types.py b/redis/google/cloud/redis_v1/types.py deleted file mode 100644 index a5a0b20db9c9..000000000000 --- a/redis/google/cloud/redis_v1/types.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.redis_v1.proto import cloud_redis_pb2 -from google.longrunning import operations_pb2 -from google.protobuf import any_pb2 -from google.protobuf import field_mask_pb2 -from google.protobuf import timestamp_pb2 -from google.rpc import status_pb2 - - -_shared_modules = [operations_pb2, any_pb2, field_mask_pb2, timestamp_pb2, status_pb2] - -_local_modules = [cloud_redis_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.redis_v1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/redis/google/cloud/redis_v1beta1/__init__.py b/redis/google/cloud/redis_v1beta1/__init__.py deleted file mode 100644 index 6fb67cb28fde..000000000000 --- a/redis/google/cloud/redis_v1beta1/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys -import warnings - -from google.cloud.redis_v1beta1 import types -from google.cloud.redis_v1beta1.gapic import cloud_redis_client -from google.cloud.redis_v1beta1.gapic import enums - - -if sys.version_info[:2] == (2, 7): - message = ( - "A future version of this library will drop support for Python 2.7." - "More details about Python 2 support for Google Cloud Client Libraries" - "can be found at https://cloud.google.com/python/docs/python2-sunset/" - ) - warnings.warn(message, DeprecationWarning) - - -class CloudRedisClient(cloud_redis_client.CloudRedisClient): - __doc__ = cloud_redis_client.CloudRedisClient.__doc__ - enums = enums - - -__all__ = ("enums", "types", "CloudRedisClient") diff --git a/redis/google/cloud/redis_v1beta1/gapic/__init__.py b/redis/google/cloud/redis_v1beta1/gapic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client.py b/redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client.py deleted file mode 100644 index 9a09a053ac07..000000000000 --- a/redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client.py +++ /dev/null @@ -1,1033 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.cloud.redis.v1beta1 CloudRedis API.""" - -import functools -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.gapic_v1.routing_header -import google.api_core.grpc_helpers -import google.api_core.operation -import google.api_core.operations_v1 -import google.api_core.page_iterator -import google.api_core.path_template -import grpc - -from google.cloud.redis_v1beta1.gapic import cloud_redis_client_config -from google.cloud.redis_v1beta1.gapic import enums -from google.cloud.redis_v1beta1.gapic.transports import cloud_redis_grpc_transport -from google.cloud.redis_v1beta1.proto import cloud_redis_pb2 -from google.cloud.redis_v1beta1.proto import cloud_redis_pb2_grpc -from google.longrunning import operations_pb2 -from google.protobuf import any_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-redis").version - - -class CloudRedisClient(object): - """ - Configures and manages Cloud Memorystore for Redis instances - - Google Cloud Memorystore for Redis v1beta1 - - The ``redis.googleapis.com`` service implements the Google Cloud - Memorystore for Redis API and defines the following resource model for - managing Redis instances: - - - The service works with a collection of cloud projects, named: - ``/projects/*`` - - Each project has a collection of available locations, named: - ``/locations/*`` - - Each location has a collection of Redis instances, named: - ``/instances/*`` - - As such, Redis instances are resources of the form: - ``/projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - - Note that location\_id must be refering to a GCP ``region``; for - example: - - - ``projects/redpepper-1290/locations/us-central1/instances/my-redis`` - """ - - SERVICE_ADDRESS = "redis.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.redis.v1beta1.CloudRedis" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - CloudRedisClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - @classmethod - def instance_path(cls, project, location, instance): - """Return a fully-qualified instance string.""" - return google.api_core.path_template.expand( - "projects/{project}/locations/{location}/instances/{instance}", - project=project, - location=location, - instance=instance, - ) - - @classmethod - def location_path(cls, project, location): - """Return a fully-qualified location string.""" - return google.api_core.path_template.expand( - "projects/{project}/locations/{location}", - project=project, - location=location, - ) - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.CloudRedisGrpcTransport, - Callable[[~.Credentials, type], ~.CloudRedisGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = cloud_redis_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=cloud_redis_grpc_transport.CloudRedisGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = cloud_redis_grpc_transport.CloudRedisGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def list_instances( - self, - parent, - page_size=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Lists all Redis instances owned by a project in either the specified - location (region) or all locations. - - The location should have the following format: - - - ``projects/{project_id}/locations/{location_id}`` - - If ``location_id`` is specified as ``-`` (wildcard), then all regions - available to the project are queried, and the results are aggregated. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> parent = client.location_path('[PROJECT]', '[LOCATION]') - >>> - >>> # Iterate over all results - >>> for element in client.list_instances(parent): - ... # process element - ... pass - >>> - >>> - >>> # Alternatively: - >>> - >>> # Iterate over results one page at a time - >>> for page in client.list_instances(parent).pages: - ... for element in page: - ... # process element - ... pass - - Args: - parent (str): Required. The resource name of the instance location using the form: - ``projects/{project_id}/locations/{location_id}`` where ``location_id`` - refers to a GCP region. - page_size (int): The maximum number of resources contained in the - underlying API response. If page streaming is performed per- - resource, this parameter does not affect the return value. If page - streaming is performed per-page, this determines the maximum number - of resources in a page. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.api_core.page_iterator.PageIterator` instance. - An iterable of :class:`~google.cloud.redis_v1beta1.types.Instance` instances. - You can also iterate over the pages of the response - using its `pages` property. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "list_instances" not in self._inner_api_calls: - self._inner_api_calls[ - "list_instances" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.list_instances, - default_retry=self._method_configs["ListInstances"].retry, - default_timeout=self._method_configs["ListInstances"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.ListInstancesRequest( - parent=parent, page_size=page_size - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - iterator = google.api_core.page_iterator.GRPCIterator( - client=None, - method=functools.partial( - self._inner_api_calls["list_instances"], - retry=retry, - timeout=timeout, - metadata=metadata, - ), - request=request, - items_field="instances", - request_token_field="page_token", - response_token_field="next_page_token", - ) - return iterator - - def get_instance( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Gets the details of a specific Redis instance. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> name = client.instance_path('[PROJECT]', '[LOCATION]', '[INSTANCE]') - >>> - >>> response = client.get_instance(name) - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1beta1.types.Instance` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "get_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "get_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.get_instance, - default_retry=self._method_configs["GetInstance"].retry, - default_timeout=self._method_configs["GetInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.GetInstanceRequest(name=name) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - return self._inner_api_calls["get_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def create_instance( - self, - parent, - instance_id, - instance, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Creates a Redis instance based on the specified tier and memory size. - - By default, the instance is accessible from the project's `default - network `__. - - The creation is executed asynchronously and callers may check the - returned operation to track its progress. Once the operation is - completed the Redis instance will be fully functional. Completed - longrunning.Operation will contain the new instance object in the - response field. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> from google.cloud.redis_v1beta1 import enums - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> parent = client.location_path('[PROJECT]', '[LOCATION]') - >>> instance_id = 'test_instance' - >>> tier = enums.Instance.Tier.BASIC - >>> memory_size_gb = 1 - >>> instance = {'tier': tier, 'memory_size_gb': memory_size_gb} - >>> - >>> response = client.create_instance(parent, instance_id, instance) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - parent (str): Required. The resource name of the instance location using the form: - ``projects/{project_id}/locations/{location_id}`` where ``location_id`` - refers to a GCP region. - instance_id (str): Required. The logical name of the Redis instance in the customer project - with the following restrictions: - - - Must contain only lowercase letters, numbers, and hyphens. - - Must start with a letter. - - Must be between 1-40 characters. - - Must end with a number or a letter. - - Must be unique within the customer project / location - instance (Union[dict, ~google.cloud.redis_v1beta1.types.Instance]): Required. A Redis [Instance] resource - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1beta1.types.Instance` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1beta1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "create_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "create_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.create_instance, - default_retry=self._method_configs["CreateInstance"].retry, - default_timeout=self._method_configs["CreateInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.CreateInstanceRequest( - parent=parent, instance_id=instance_id, instance=instance - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("parent", parent)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["create_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=any_pb2.Any, - ) - - def update_instance( - self, - update_mask, - instance, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Updates the metadata and configuration of a specific Redis instance. - - Completed longrunning.Operation will contain the new instance object - in the response field. The returned operation is automatically deleted - after a few hours, so there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> paths_element = 'display_name' - >>> paths_element_2 = 'memory_size_gb' - >>> paths = [paths_element, paths_element_2] - >>> update_mask = {'paths': paths} - >>> display_name = 'UpdatedDisplayName' - >>> memory_size_gb = 4 - >>> instance = {'display_name': display_name, 'memory_size_gb': memory_size_gb} - >>> - >>> response = client.update_instance(update_mask, instance) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - update_mask (Union[dict, ~google.cloud.redis_v1beta1.types.FieldMask]): Required. Mask of fields to update. At least one path must be supplied - in this field. The elements of the repeated paths field may only include - these fields from ``Instance``: - - - ``displayName`` - - ``labels`` - - ``memorySizeGb`` - - ``redisConfig`` - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1beta1.types.FieldMask` - instance (Union[dict, ~google.cloud.redis_v1beta1.types.Instance]): Required. Update description. Only fields specified in update\_mask are - updated. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1beta1.types.Instance` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1beta1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "update_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "update_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.update_instance, - default_retry=self._method_configs["UpdateInstance"].retry, - default_timeout=self._method_configs["UpdateInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.UpdateInstanceRequest( - update_mask=update_mask, instance=instance - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("instance.name", instance.name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["update_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=any_pb2.Any, - ) - - def import_instance( - self, - name, - input_config, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - - Redis may stop serving during this operation. Instance state will be - IMPORTING for entire operation. When complete, the instance will contain - only data from the imported file. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> # TODO: Initialize `name`: - >>> name = '' - >>> - >>> # TODO: Initialize `input_config`: - >>> input_config = {} - >>> - >>> response = client.import_instance(name, input_config) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - input_config (Union[dict, ~google.cloud.redis_v1beta1.types.InputConfig]): Required. Specify data to be imported. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1beta1.types.InputConfig` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1beta1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "import_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "import_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.import_instance, - default_retry=self._method_configs["ImportInstance"].retry, - default_timeout=self._method_configs["ImportInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.ImportInstanceRequest( - name=name, input_config=input_config - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["import_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=any_pb2.Any, - ) - - def export_instance( - self, - name, - output_config, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Export Redis instance data into a Redis RDB format file in Cloud Storage. - - Redis will continue serving during this operation. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> # TODO: Initialize `name`: - >>> name = '' - >>> - >>> # TODO: Initialize `output_config`: - >>> output_config = {} - >>> - >>> response = client.export_instance(name, output_config) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - output_config (Union[dict, ~google.cloud.redis_v1beta1.types.OutputConfig]): Required. Specify data to be exported. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.redis_v1beta1.types.OutputConfig` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1beta1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "export_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "export_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.export_instance, - default_retry=self._method_configs["ExportInstance"].retry, - default_timeout=self._method_configs["ExportInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.ExportInstanceRequest( - name=name, output_config=output_config - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["export_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=any_pb2.Any, - ) - - def failover_instance( - self, - name, - data_protection_mode=None, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Initiates a failover of the master node to current replica node for a - specific STANDARD tier Cloud Memorystore for Redis instance. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> name = client.instance_path('[PROJECT]', '[LOCATION]', '[INSTANCE]') - >>> - >>> response = client.failover_instance(name) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - data_protection_mode (~google.cloud.redis_v1beta1.types.DataProtectionMode): Optional. Available data protection modes that the user can choose. If - it's unspecified, data protection mode will be LIMITED\_DATA\_LOSS by - default. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1beta1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "failover_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "failover_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.failover_instance, - default_retry=self._method_configs["FailoverInstance"].retry, - default_timeout=self._method_configs["FailoverInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.FailoverInstanceRequest( - name=name, data_protection_mode=data_protection_mode - ) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["failover_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_redis_pb2.Instance, - metadata_type=any_pb2.Any, - ) - - def delete_instance( - self, - name, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Deletes a specific Redis instance. Instance stops serving and data is - deleted. - - Example: - >>> from google.cloud import redis_v1beta1 - >>> - >>> client = redis_v1beta1.CloudRedisClient() - >>> - >>> name = client.instance_path('[PROJECT]', '[LOCATION]', '[INSTANCE]') - >>> - >>> response = client.delete_instance(name) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - name (str): Required. Redis instance resource name using the form: - ``projects/{project_id}/locations/{location_id}/instances/{instance_id}`` - where ``location_id`` refers to a GCP region. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.redis_v1beta1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "delete_instance" not in self._inner_api_calls: - self._inner_api_calls[ - "delete_instance" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.delete_instance, - default_retry=self._method_configs["DeleteInstance"].retry, - default_timeout=self._method_configs["DeleteInstance"].timeout, - client_info=self._client_info, - ) - - request = cloud_redis_pb2.DeleteInstanceRequest(name=name) - if metadata is None: - metadata = [] - metadata = list(metadata) - try: - routing_header = [("name", name)] - except AttributeError: - pass - else: - routing_metadata = google.api_core.gapic_v1.routing_header.to_grpc_metadata( - routing_header - ) - metadata.append(routing_metadata) - - operation = self._inner_api_calls["delete_instance"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - empty_pb2.Empty, - metadata_type=any_pb2.Any, - ) diff --git a/redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client_config.py b/redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client_config.py deleted file mode 100644 index 262a77dc9af0..000000000000 --- a/redis/google/cloud/redis_v1beta1/gapic/cloud_redis_client_config.py +++ /dev/null @@ -1,63 +0,0 @@ -config = { - "interfaces": { - "google.cloud.redis.v1beta1.CloudRedis": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 20000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 20000, - "total_timeout_millis": 600000, - } - }, - "methods": { - "ListInstances": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "GetInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "CreateInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "UpdateInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "ImportInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "ExportInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "FailoverInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "DeleteInstance": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/redis/google/cloud/redis_v1beta1/gapic/enums.py b/redis/google/cloud/redis_v1beta1/gapic/enums.py deleted file mode 100644 index 6f7648270d21..000000000000 --- a/redis/google/cloud/redis_v1beta1/gapic/enums.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class FailoverInstanceRequest(object): - class DataProtectionMode(enum.IntEnum): - """ - Attributes: - DATA_PROTECTION_MODE_UNSPECIFIED (int): Defaults to LIMITED\_DATA\_LOSS if a data protection mode is not - specified. - LIMITED_DATA_LOSS (int): Instance failover will be protected with data loss control. More - specifically, the failover will only be performed if the current - replication offset diff between master and replica is under a certain - threshold. - FORCE_DATA_LOSS (int): Instance failover will be performed without data loss control. - """ - - DATA_PROTECTION_MODE_UNSPECIFIED = 0 - LIMITED_DATA_LOSS = 1 - FORCE_DATA_LOSS = 2 - - -class Instance(object): - class State(enum.IntEnum): - """ - Represents the different states of a Redis instance. - - Attributes: - STATE_UNSPECIFIED (int): Not set. - CREATING (int): Redis instance is being created. - READY (int): Redis instance has been created and is fully usable. - UPDATING (int): Redis instance configuration is being updated. Certain kinds of updates - may cause the instance to become unusable while the update is in - progress. - DELETING (int): Redis instance is being deleted. - REPAIRING (int): Redis instance is being repaired and may be unusable. - MAINTENANCE (int): Maintenance is being performed on this Redis instance. - IMPORTING (int): Redis instance is importing data (availability may be affected). - FAILING_OVER (int): Redis instance is failing over (availability may be affected). - """ - - STATE_UNSPECIFIED = 0 - CREATING = 1 - READY = 2 - UPDATING = 3 - DELETING = 4 - REPAIRING = 5 - MAINTENANCE = 6 - IMPORTING = 8 - FAILING_OVER = 10 - - class Tier(enum.IntEnum): - """ - Available service tiers to choose from - - Attributes: - TIER_UNSPECIFIED (int): Not set. - BASIC (int): BASIC tier: standalone instance - STANDARD_HA (int): STANDARD\_HA tier: highly available primary/replica instances - """ - - TIER_UNSPECIFIED = 0 - BASIC = 1 - STANDARD_HA = 3 diff --git a/redis/google/cloud/redis_v1beta1/gapic/transports/__init__.py b/redis/google/cloud/redis_v1beta1/gapic/transports/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/redis/google/cloud/redis_v1beta1/gapic/transports/cloud_redis_grpc_transport.py b/redis/google/cloud/redis_v1beta1/gapic/transports/cloud_redis_grpc_transport.py deleted file mode 100644 index 7ab4727a360a..000000000000 --- a/redis/google/cloud/redis_v1beta1/gapic/transports/cloud_redis_grpc_transport.py +++ /dev/null @@ -1,256 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers -import google.api_core.operations_v1 - -from google.cloud.redis_v1beta1.proto import cloud_redis_pb2_grpc - - -class CloudRedisGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.redis.v1beta1 CloudRedis API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, channel=None, credentials=None, address="redis.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = {"cloud_redis_stub": cloud_redis_pb2_grpc.CloudRedisStub(channel)} - - # Because this API includes a method that returns a - # long-running operation (proto: google.longrunning.Operation), - # instantiate an LRO client. - self._operations_client = google.api_core.operations_v1.OperationsClient( - channel - ) - - @classmethod - def create_channel( - cls, address="redis.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def list_instances(self): - """Return the gRPC stub for :meth:`CloudRedisClient.list_instances`. - - Lists all Redis instances owned by a project in either the specified - location (region) or all locations. - - The location should have the following format: - - - ``projects/{project_id}/locations/{location_id}`` - - If ``location_id`` is specified as ``-`` (wildcard), then all regions - available to the project are queried, and the results are aggregated. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].ListInstances - - @property - def get_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.get_instance`. - - Gets the details of a specific Redis instance. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].GetInstance - - @property - def create_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.create_instance`. - - Creates a Redis instance based on the specified tier and memory size. - - By default, the instance is accessible from the project's `default - network `__. - - The creation is executed asynchronously and callers may check the - returned operation to track its progress. Once the operation is - completed the Redis instance will be fully functional. Completed - longrunning.Operation will contain the new instance object in the - response field. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].CreateInstance - - @property - def update_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.update_instance`. - - Updates the metadata and configuration of a specific Redis instance. - - Completed longrunning.Operation will contain the new instance object - in the response field. The returned operation is automatically deleted - after a few hours, so there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].UpdateInstance - - @property - def import_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.import_instance`. - - Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - - Redis may stop serving during this operation. Instance state will be - IMPORTING for entire operation. When complete, the instance will contain - only data from the imported file. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].ImportInstance - - @property - def export_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.export_instance`. - - Export Redis instance data into a Redis RDB format file in Cloud Storage. - - Redis will continue serving during this operation. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].ExportInstance - - @property - def failover_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.failover_instance`. - - Initiates a failover of the master node to current replica node for a - specific STANDARD tier Cloud Memorystore for Redis instance. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].FailoverInstance - - @property - def delete_instance(self): - """Return the gRPC stub for :meth:`CloudRedisClient.delete_instance`. - - Deletes a specific Redis instance. Instance stops serving and data is - deleted. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["cloud_redis_stub"].DeleteInstance diff --git a/redis/google/cloud/redis_v1beta1/proto/__init__.py b/redis/google/cloud/redis_v1beta1/proto/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/redis/google/cloud/redis_v1beta1/proto/cloud_redis.proto b/redis/google/cloud/redis_v1beta1/proto/cloud_redis.proto deleted file mode 100644 index eafd8eb4ea86..000000000000 --- a/redis/google/cloud/redis_v1beta1/proto/cloud_redis.proto +++ /dev/null @@ -1,555 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.cloud.redis.v1beta1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/api/resource.proto"; -import "google/longrunning/operations.proto"; -import "google/protobuf/field_mask.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "google.golang.org/genproto/googleapis/cloud/redis/v1beta1;redis"; -option java_multiple_files = true; -option java_outer_classname = "CloudRedisServiceBetaProto"; -option java_package = "com.google.cloud.redis.v1beta1"; - -// Configures and manages Cloud Memorystore for Redis instances -// -// Google Cloud Memorystore for Redis v1beta1 -// -// The `redis.googleapis.com` service implements the Google Cloud Memorystore -// for Redis API and defines the following resource model for managing Redis -// instances: -// * The service works with a collection of cloud projects, named: `/projects/*` -// * Each project has a collection of available locations, named: `/locations/*` -// * Each location has a collection of Redis instances, named: `/instances/*` -// * As such, Redis instances are resources of the form: -// `/projects/{project_id}/locations/{location_id}/instances/{instance_id}` -// -// Note that location_id must be refering to a GCP `region`; for example: -// * `projects/redpepper-1290/locations/us-central1/instances/my-redis` -service CloudRedis { - option (google.api.default_host) = "redis.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Lists all Redis instances owned by a project in either the specified - // location (region) or all locations. - // - // The location should have the following format: - // * `projects/{project_id}/locations/{location_id}` - // - // If `location_id` is specified as `-` (wildcard), then all regions - // available to the project are queried, and the results are aggregated. - rpc ListInstances(ListInstancesRequest) returns (ListInstancesResponse) { - option (google.api.http) = { - get: "/v1beta1/{parent=projects/*/locations/*}/instances" - }; - option (google.api.method_signature) = "parent"; - } - - // Gets the details of a specific Redis instance. - rpc GetInstance(GetInstanceRequest) returns (Instance) { - option (google.api.http) = { - get: "/v1beta1/{name=projects/*/locations/*/instances/*}" - }; - option (google.api.method_signature) = "name"; - } - - // Creates a Redis instance based on the specified tier and memory size. - // - // By default, the instance is accessible from the project's - // [default network](/compute/docs/networks-and-firewalls#networks). - // - // The creation is executed asynchronously and callers may check the returned - // operation to track its progress. Once the operation is completed the Redis - // instance will be fully functional. Completed longrunning.Operation will - // contain the new instance object in the response field. - // - // The returned operation is automatically deleted after a few hours, so there - // is no need to call DeleteOperation. - rpc CreateInstance(CreateInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1beta1/{parent=projects/*/locations/*}/instances" - body: "instance" - }; - option (google.api.method_signature) = "parent,instance_id,instance"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1beta1.Instance" - metadata_type: "google.protobuf.Any" - }; - } - - // Updates the metadata and configuration of a specific Redis instance. - // - // Completed longrunning.Operation will contain the new instance object - // in the response field. The returned operation is automatically deleted - // after a few hours, so there is no need to call DeleteOperation. - rpc UpdateInstance(UpdateInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - patch: "/v1beta1/{instance.name=projects/*/locations/*/instances/*}" - body: "instance" - }; - option (google.api.method_signature) = "update_mask,instance"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1beta1.Instance" - metadata_type: "google.protobuf.Any" - }; - } - - // Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - // - // Redis may stop serving during this operation. Instance state will be - // IMPORTING for entire operation. When complete, the instance will contain - // only data from the imported file. - // - // The returned operation is automatically deleted after a few hours, so - // there is no need to call DeleteOperation. - rpc ImportInstance(ImportInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1beta1/{name=projects/*/locations/*/instances/*}:import" - body: "*" - }; - option (google.api.method_signature) = "name,input_config"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1beta1.Instance" - metadata_type: "google.protobuf.Any" - }; - } - - // Export Redis instance data into a Redis RDB format file in Cloud Storage. - // - // Redis will continue serving during this operation. - // - // The returned operation is automatically deleted after a few hours, so - // there is no need to call DeleteOperation. - rpc ExportInstance(ExportInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1beta1/{name=projects/*/locations/*/instances/*}:export" - body: "*" - }; - option (google.api.method_signature) = "name,output_config"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1beta1.Instance" - metadata_type: "google.protobuf.Any" - }; - } - - // Initiates a failover of the master node to current replica node for a - // specific STANDARD tier Cloud Memorystore for Redis instance. - rpc FailoverInstance(FailoverInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1beta1/{name=projects/*/locations/*/instances/*}:failover" - body: "*" - }; - option (google.api.method_signature) = "name,data_protection_mode"; - option (google.longrunning.operation_info) = { - response_type: "google.cloud.redis.v1beta1.Instance" - metadata_type: "google.protobuf.Any" - }; - } - - // Deletes a specific Redis instance. Instance stops serving and data is - // deleted. - rpc DeleteInstance(DeleteInstanceRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - delete: "/v1beta1/{name=projects/*/locations/*/instances/*}" - }; - option (google.api.method_signature) = "name"; - option (google.longrunning.operation_info) = { - response_type: "google.protobuf.Empty" - metadata_type: "google.protobuf.Any" - }; - } -} - -// A Google Cloud Redis instance. -message Instance { - option (google.api.resource) = { - type: "redis.googleapis.com/Instance" - pattern: "projects/{project}/locations/{location}/instances/{instance}" - }; - - // Represents the different states of a Redis instance. - enum State { - // Not set. - STATE_UNSPECIFIED = 0; - - // Redis instance is being created. - CREATING = 1; - - // Redis instance has been created and is fully usable. - READY = 2; - - // Redis instance configuration is being updated. Certain kinds of updates - // may cause the instance to become unusable while the update is in - // progress. - UPDATING = 3; - - // Redis instance is being deleted. - DELETING = 4; - - // Redis instance is being repaired and may be unusable. - REPAIRING = 5; - - // Maintenance is being performed on this Redis instance. - MAINTENANCE = 6; - - // Redis instance is importing data (availability may be affected). - IMPORTING = 8; - - // Redis instance is failing over (availability may be affected). - FAILING_OVER = 10; - } - - // Available service tiers to choose from - enum Tier { - // Not set. - TIER_UNSPECIFIED = 0; - - // BASIC tier: standalone instance - BASIC = 1; - - // STANDARD_HA tier: highly available primary/replica instances - STANDARD_HA = 3; - } - - // Required. Unique name of the resource in this scope including project and - // location using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // - // Note: Redis instances are managed and addressed at regional level so - // location_id here refers to a GCP region; however, users may choose which - // specific zone (or collection of zones for cross-zone instances) an instance - // should be provisioned in. Refer to [location_id] and - // [alternative_location_id] fields for more details. - string name = 1 [(google.api.field_behavior) = REQUIRED]; - - // An arbitrary and optional user-provided name for the instance. - string display_name = 2; - - // Resource labels to represent user provided metadata - map labels = 3; - - // Optional. The zone where the instance will be provisioned. If not provided, - // the service will choose a zone for the instance. For STANDARD_HA tier, - // instances will be created across two zones for protection against zonal - // failures. If [alternative_location_id] is also provided, it must be - // different from [location_id]. - string location_id = 4 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. Only applicable to STANDARD_HA tier which protects the instance - // against zonal failures by provisioning it across two zones. If provided, it - // must be a different zone from the one provided in [location_id]. - string alternative_location_id = 5 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. The version of Redis software. - // If not provided, latest supported version will be used. Updating the - // version will perform an upgrade/downgrade to the new version. Currently, - // the supported values are: - // - // * `REDIS_4_0` for Redis 4.0 compatibility (default) - // * `REDIS_3_2` for Redis 3.2 compatibility - string redis_version = 7 [(google.api.field_behavior) = OPTIONAL]; - - // Optional. The CIDR range of internal addresses that are reserved for this - // instance. If not provided, the service will choose an unused /29 block, - // for example, 10.0.0.0/29 or 192.168.0.0/29. Ranges must be unique - // and non-overlapping with existing subnets in an authorized network. - string reserved_ip_range = 9 [(google.api.field_behavior) = OPTIONAL]; - - // Output only. Hostname or IP address of the exposed Redis endpoint used by - // clients to connect to the service. - string host = 10 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The port number of the exposed Redis endpoint. - int32 port = 11 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The current zone where the Redis endpoint is placed. For Basic - // Tier instances, this will always be the same as the [location_id] - // provided by the user at creation time. For Standard Tier instances, - // this can be either [location_id] or [alternative_location_id] and can - // change after a failover event. - string current_location_id = 12 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The time the instance was created. - google.protobuf.Timestamp create_time = 13 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. The current state of this instance. - State state = 14 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Output only. Additional information about the current status of this - // instance, if available. - string status_message = 15 [(google.api.field_behavior) = OUTPUT_ONLY]; - - // Optional. Redis configuration parameters, according to - // http://redis.io/topics/config. Currently, the only supported parameters - // are: - // - // Redis 3.2 and above: - // - // * maxmemory-policy - // * notify-keyspace-events - // - // Redis 4.0 and above: - // - // * activedefrag - // * lfu-log-factor - // * lfu-decay-time - map redis_configs = 16 [(google.api.field_behavior) = OPTIONAL]; - - // Required. The service tier of the instance. - Tier tier = 17 [(google.api.field_behavior) = REQUIRED]; - - // Required. Redis memory size in GiB. - int32 memory_size_gb = 18 [(google.api.field_behavior) = REQUIRED]; - - // Optional. The full name of the Google Compute Engine - // [network](/compute/docs/networks-and-firewalls#networks) to which the - // instance is connected. If left unspecified, the `default` network - // will be used. - string authorized_network = 20 [(google.api.field_behavior) = OPTIONAL]; - - // Output only. Cloud IAM identity used by import / export operations to - // transfer data to/from Cloud Storage. Format is - // "serviceAccount:". The value may change over time - // for a given instance so should be checked before each import/export - // operation. - string persistence_iam_identity = 21 [(google.api.field_behavior) = OUTPUT_ONLY]; -} - -// Request for [ListInstances][google.cloud.redis.v1beta1.CloudRedis.ListInstances]. -message ListInstancesRequest { - // Required. The resource name of the instance location using the form: - // `projects/{project_id}/locations/{location_id}` - // where `location_id` refers to a GCP region. - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "locations.googleapis.com/Location" - } - ]; - - // The maximum number of items to return. - // - // If not specified, a default value of 1000 will be used by the service. - // Regardless of the page_size value, the response may include a partial list - // and a caller should only rely on response's - // [next_page_token][CloudRedis.ListInstancesResponse.next_page_token] - // to determine if there are more instances left to be queried. - int32 page_size = 2; - - // The next_page_token value returned from a previous List request, - // if any. - string page_token = 3; -} - -// Response for [ListInstances][google.cloud.redis.v1beta1.CloudRedis.ListInstances]. -message ListInstancesResponse { - // A list of Redis instances in the project in the specified location, - // or across all locations. - // - // If the `location_id` in the parent field of the request is "-", all regions - // available to the project are queried, and the results aggregated. - // If in such an aggregated query a location is unavailable, a dummy Redis - // entry is included in the response with the "name" field set to a value of - // the form projects/{project_id}/locations/{location_id}/instances/- and the - // "status" field set to ERROR and "status_message" field set to "location not - // available for ListInstances". - repeated Instance instances = 1; - - // Token to retrieve the next page of results, or empty if there are no more - // results in the list. - string next_page_token = 2; - - // Locations that could not be reached. - repeated string unreachable = 3; -} - -// Request for [GetInstance][google.cloud.redis.v1beta1.CloudRedis.GetInstance]. -message GetInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "redis.googleapis.com/Instance" - } - ]; -} - -// Request for [CreateInstance][google.cloud.redis.v1beta1.CloudRedis.CreateInstance]. -message CreateInstanceRequest { - // Required. The resource name of the instance location using the form: - // `projects/{project_id}/locations/{location_id}` - // where `location_id` refers to a GCP region. - string parent = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "locations.googleapis.com/Location" - } - ]; - - // Required. The logical name of the Redis instance in the customer project - // with the following restrictions: - // - // * Must contain only lowercase letters, numbers, and hyphens. - // * Must start with a letter. - // * Must be between 1-40 characters. - // * Must end with a number or a letter. - // * Must be unique within the customer project / location - string instance_id = 2 [(google.api.field_behavior) = REQUIRED]; - - // Required. A Redis [Instance] resource - Instance instance = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// Request for [UpdateInstance][google.cloud.redis.v1beta1.CloudRedis.UpdateInstance]. -message UpdateInstanceRequest { - // Required. Mask of fields to update. At least one path must be supplied in - // this field. The elements of the repeated paths field may only include these - // fields from [Instance][google.cloud.redis.v1beta1.Instance]: - // - // * `displayName` - // * `labels` - // * `memorySizeGb` - // * `redisConfig` - google.protobuf.FieldMask update_mask = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. Update description. - // Only fields specified in update_mask are updated. - Instance instance = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// Request for [DeleteInstance][google.cloud.redis.v1beta1.CloudRedis.DeleteInstance]. -message DeleteInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "redis.googleapis.com/Instance" - } - ]; -} - -// The Cloud Storage location for the input content -message GcsSource { - // Required. Source data URI. (e.g. 'gs://my_bucket/my_object'). - string uri = 1 [(google.api.field_behavior) = REQUIRED]; -} - -// The input content -message InputConfig { - // Required. Specify source location of input data - oneof source { - // Google Cloud Storage location where input content is located. - GcsSource gcs_source = 1; - } -} - -// Request for [Import][google.cloud.redis.v1beta1.CloudRedis.ImportInstance]. -message ImportInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. Specify data to be imported. - InputConfig input_config = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// The Cloud Storage location for the output content -message GcsDestination { - // Required. Data destination URI (e.g. - // 'gs://my_bucket/my_object'). Existing files will be overwritten. - string uri = 1 [(google.api.field_behavior) = REQUIRED]; -} - -// The output content -message OutputConfig { - // Required. Specify destination location of output data - oneof destination { - // Google Cloud Storage destination for output content. - GcsDestination gcs_destination = 1; - } -} - -// Request for [Export][google.cloud.redis.v1beta1.CloudRedis.ExportInstance]. -message ExportInstanceRequest { - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. Specify data to be exported. - OutputConfig output_config = 3 [(google.api.field_behavior) = REQUIRED]; -} - -// Request for [Failover][google.cloud.redis.v1beta1.CloudRedis.FailoverInstance]. -message FailoverInstanceRequest { - enum DataProtectionMode { - // Defaults to LIMITED_DATA_LOSS if a data protection mode is not - // specified. - DATA_PROTECTION_MODE_UNSPECIFIED = 0; - - // Instance failover will be protected with data loss control. More - // specifically, the failover will only be performed if the current - // replication offset diff between master and replica is under a certain - // threshold. - LIMITED_DATA_LOSS = 1; - - // Instance failover will be performed without data loss control. - FORCE_DATA_LOSS = 2; - } - - // Required. Redis instance resource name using the form: - // `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - // where `location_id` refers to a GCP region. - string name = 1 [ - (google.api.field_behavior) = REQUIRED, - (google.api.resource_reference) = { - type: "redis.googleapis.com/Instance" - } - ]; - - // Optional. Available data protection modes that the user can choose. If it's - // unspecified, data protection mode will be LIMITED_DATA_LOSS by default. - DataProtectionMode data_protection_mode = 2 [(google.api.field_behavior) = OPTIONAL]; -} - -// This location metadata represents additional configuration options for a -// given location where a Redis instance may be created. All fields are output -// only. It is returned as content of the -// `google.cloud.location.Location.metadata` field. -message LocationMetadata { - // Output only. The set of available zones in the location. The map is keyed - // by the lowercase ID of each zone, as defined by GCE. These keys can be - // specified in `location_id` or `alternative_location_id` fields when - // creating a Redis instance. - map available_zones = 1 [(google.api.field_behavior) = OUTPUT_ONLY]; -} - -// Defines specific information for a particular zone. Currently empty and -// reserved for future use only. -message ZoneMetadata { - -} diff --git a/redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2.py b/redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2.py deleted file mode 100644 index 528075a7420b..000000000000 --- a/redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2.py +++ /dev/null @@ -1,2130 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/redis_v1beta1/proto/cloud_redis.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.api import resource_pb2 as google_dot_api_dot_resource__pb2 -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) -from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 -from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/redis_v1beta1/proto/cloud_redis.proto", - package="google.cloud.redis.v1beta1", - syntax="proto3", - serialized_options=_b( - "\n\036com.google.cloud.redis.v1beta1B\032CloudRedisServiceBetaProtoP\001Z?google.golang.org/genproto/googleapis/cloud/redis/v1beta1;redis" - ), - serialized_pb=_b( - '\n2google/cloud/redis_v1beta1/proto/cloud_redis.proto\x12\x1agoogle.cloud.redis.v1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a#google/longrunning/operations.proto\x1a google/protobuf/field_mask.proto\x1a\x1fgoogle/protobuf/timestamp.proto"\xda\x08\n\x08Instance\x12\x11\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12@\n\x06labels\x18\x03 \x03(\x0b\x32\x30.google.cloud.redis.v1beta1.Instance.LabelsEntry\x12\x18\n\x0blocation_id\x18\x04 \x01(\tB\x03\xe0\x41\x01\x12$\n\x17\x61lternative_location_id\x18\x05 \x01(\tB\x03\xe0\x41\x01\x12\x1a\n\rredis_version\x18\x07 \x01(\tB\x03\xe0\x41\x01\x12\x1e\n\x11reserved_ip_range\x18\t \x01(\tB\x03\xe0\x41\x01\x12\x11\n\x04host\x18\n \x01(\tB\x03\xe0\x41\x03\x12\x11\n\x04port\x18\x0b \x01(\x05\x42\x03\xe0\x41\x03\x12 \n\x13\x63urrent_location_id\x18\x0c \x01(\tB\x03\xe0\x41\x03\x12\x34\n\x0b\x63reate_time\x18\r \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x03\x12>\n\x05state\x18\x0e \x01(\x0e\x32*.google.cloud.redis.v1beta1.Instance.StateB\x03\xe0\x41\x03\x12\x1b\n\x0estatus_message\x18\x0f \x01(\tB\x03\xe0\x41\x03\x12R\n\rredis_configs\x18\x10 \x03(\x0b\x32\x36.google.cloud.redis.v1beta1.Instance.RedisConfigsEntryB\x03\xe0\x41\x01\x12<\n\x04tier\x18\x11 \x01(\x0e\x32).google.cloud.redis.v1beta1.Instance.TierB\x03\xe0\x41\x02\x12\x1b\n\x0ememory_size_gb\x18\x12 \x01(\x05\x42\x03\xe0\x41\x02\x12\x1f\n\x12\x61uthorized_network\x18\x14 \x01(\tB\x03\xe0\x41\x01\x12%\n\x18persistence_iam_identity\x18\x15 \x01(\tB\x03\xe0\x41\x03\x1a-\n\x0bLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x33\n\x11RedisConfigsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"\x94\x01\n\x05State\x12\x15\n\x11STATE_UNSPECIFIED\x10\x00\x12\x0c\n\x08\x43REATING\x10\x01\x12\t\n\x05READY\x10\x02\x12\x0c\n\x08UPDATING\x10\x03\x12\x0c\n\x08\x44\x45LETING\x10\x04\x12\r\n\tREPAIRING\x10\x05\x12\x0f\n\x0bMAINTENANCE\x10\x06\x12\r\n\tIMPORTING\x10\x08\x12\x10\n\x0c\x46\x41ILING_OVER\x10\n"8\n\x04Tier\x12\x14\n\x10TIER_UNSPECIFIED\x10\x00\x12\t\n\x05\x42\x41SIC\x10\x01\x12\x0f\n\x0bSTANDARD_HA\x10\x03:`\xea\x41]\n\x1dredis.googleapis.com/Instance\x12"2/v1beta1/{parent=projects/*/locations/*}/instances:\x08instance\xda\x41\x1bparent,instance_id,instance\xca\x41:\n#google.cloud.redis.v1beta1.Instance\x12\x13google.protobuf.Any\x12\x86\x02\n\x0eUpdateInstance\x12\x31.google.cloud.redis.v1beta1.UpdateInstanceRequest\x1a\x1d.google.longrunning.Operation"\xa1\x01\x82\xd3\xe4\x93\x02G2;/v1beta1/{instance.name=projects/*/locations/*/instances/*}:\x08instance\xda\x41\x14update_mask,instance\xca\x41:\n#google.cloud.redis.v1beta1.Instance\x12\x13google.protobuf.Any\x12\xfa\x01\n\x0eImportInstance\x12\x31.google.cloud.redis.v1beta1.ImportInstanceRequest\x1a\x1d.google.longrunning.Operation"\x95\x01\x82\xd3\xe4\x93\x02>"9/v1beta1/{name=projects/*/locations/*/instances/*}:import:\x01*\xda\x41\x11name,input_config\xca\x41:\n#google.cloud.redis.v1beta1.Instance\x12\x13google.protobuf.Any\x12\xfb\x01\n\x0e\x45xportInstance\x12\x31.google.cloud.redis.v1beta1.ExportInstanceRequest\x1a\x1d.google.longrunning.Operation"\x96\x01\x82\xd3\xe4\x93\x02>"9/v1beta1/{name=projects/*/locations/*/instances/*}:export:\x01*\xda\x41\x12name,output_config\xca\x41:\n#google.cloud.redis.v1beta1.Instance\x12\x13google.protobuf.Any\x12\x88\x02\n\x10\x46\x61iloverInstance\x12\x33.google.cloud.redis.v1beta1.FailoverInstanceRequest\x1a\x1d.google.longrunning.Operation"\x9f\x01\x82\xd3\xe4\x93\x02@";/v1beta1/{name=projects/*/locations/*/instances/*}:failover:\x01*\xda\x41\x19name,data_protection_mode\xca\x41:\n#google.cloud.redis.v1beta1.Instance\x12\x13google.protobuf.Any\x12\xd4\x01\n\x0e\x44\x65leteInstance\x12\x31.google.cloud.redis.v1beta1.DeleteInstanceRequest\x1a\x1d.google.longrunning.Operation"p\x82\xd3\xe4\x93\x02\x34*2/v1beta1/{name=projects/*/locations/*/instances/*}\xda\x41\x04name\xca\x41,\n\x15google.protobuf.Empty\x12\x13google.protobuf.Any\x1aH\xca\x41\x14redis.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformB\x7f\n\x1e\x63om.google.cloud.redis.v1beta1B\x1a\x43loudRedisServiceBetaProtoP\x01Z?google.golang.org/genproto/googleapis/cloud/redis/v1beta1;redisb\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_api_dot_resource__pb2.DESCRIPTOR, - google_dot_longrunning_dot_operations__pb2.DESCRIPTOR, - google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR, - google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, - ], -) - - -_INSTANCE_STATE = _descriptor.EnumDescriptor( - name="State", - full_name="google.cloud.redis.v1beta1.Instance.State", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="STATE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="CREATING", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="READY", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="UPDATING", index=3, number=3, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="DELETING", index=4, number=4, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="REPAIRING", index=5, number=5, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="MAINTENANCE", index=6, number=6, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="IMPORTING", index=7, number=8, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="FAILING_OVER", index=8, number=10, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1112, - serialized_end=1260, -) -_sym_db.RegisterEnumDescriptor(_INSTANCE_STATE) - -_INSTANCE_TIER = _descriptor.EnumDescriptor( - name="Tier", - full_name="google.cloud.redis.v1beta1.Instance.Tier", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="TIER_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="BASIC", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="STANDARD_HA", index=2, number=3, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1262, - serialized_end=1318, -) -_sym_db.RegisterEnumDescriptor(_INSTANCE_TIER) - -_FAILOVERINSTANCEREQUEST_DATAPROTECTIONMODE = _descriptor.EnumDescriptor( - name="DataProtectionMode", - full_name="google.cloud.redis.v1beta1.FailoverInstanceRequest.DataProtectionMode", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="DATA_PROTECTION_MODE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="LIMITED_DATA_LOSS", - index=1, - number=1, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="FORCE_DATA_LOSS", - index=2, - number=2, - serialized_options=None, - type=None, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=2803, - serialized_end=2905, -) -_sym_db.RegisterEnumDescriptor(_FAILOVERINSTANCEREQUEST_DATAPROTECTIONMODE) - - -_INSTANCE_LABELSENTRY = _descriptor.Descriptor( - name="LabelsEntry", - full_name="google.cloud.redis.v1beta1.Instance.LabelsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.cloud.redis.v1beta1.Instance.LabelsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.cloud.redis.v1beta1.Instance.LabelsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1011, - serialized_end=1056, -) - -_INSTANCE_REDISCONFIGSENTRY = _descriptor.Descriptor( - name="RedisConfigsEntry", - full_name="google.cloud.redis.v1beta1.Instance.RedisConfigsEntry", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="key", - full_name="google.cloud.redis.v1beta1.Instance.RedisConfigsEntry.key", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="value", - full_name="google.cloud.redis.v1beta1.Instance.RedisConfigsEntry.value", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=_b("8\001"), - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1058, - serialized_end=1109, -) - -_INSTANCE = _descriptor.Descriptor( - name="Instance", - full_name="google.cloud.redis.v1beta1.Instance", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="name", - full_name="google.cloud.redis.v1beta1.Instance.name", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="display_name", - full_name="google.cloud.redis.v1beta1.Instance.display_name", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="labels", - full_name="google.cloud.redis.v1beta1.Instance.labels", - index=2, - number=3, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="location_id", - full_name="google.cloud.redis.v1beta1.Instance.location_id", - index=3, - number=4, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="alternative_location_id", - full_name="google.cloud.redis.v1beta1.Instance.alternative_location_id", - index=4, - number=5, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="redis_version", - full_name="google.cloud.redis.v1beta1.Instance.redis_version", - index=5, - number=7, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="reserved_ip_range", - full_name="google.cloud.redis.v1beta1.Instance.reserved_ip_range", - index=6, - number=9, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="host", - full_name="google.cloud.redis.v1beta1.Instance.host", - index=7, - number=10, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="port", - full_name="google.cloud.redis.v1beta1.Instance.port", - index=8, - number=11, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="current_location_id", - full_name="google.cloud.redis.v1beta1.Instance.current_location_id", - index=9, - number=12, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="create_time", - full_name="google.cloud.redis.v1beta1.Instance.create_time", - index=10, - number=13, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="state", - full_name="google.cloud.redis.v1beta1.Instance.state", - index=11, - number=14, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="status_message", - full_name="google.cloud.redis.v1beta1.Instance.status_message", - index=12, - number=15, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="redis_configs", - full_name="google.cloud.redis.v1beta1.Instance.redis_configs", - index=13, - number=16, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="tier", - full_name="google.cloud.redis.v1beta1.Instance.tier", - index=14, - number=17, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="memory_size_gb", - full_name="google.cloud.redis.v1beta1.Instance.memory_size_gb", - index=15, - number=18, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="authorized_network", - full_name="google.cloud.redis.v1beta1.Instance.authorized_network", - index=16, - number=20, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="persistence_iam_identity", - full_name="google.cloud.redis.v1beta1.Instance.persistence_iam_identity", - index=17, - number=21, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\003"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[_INSTANCE_LABELSENTRY, _INSTANCE_REDISCONFIGSENTRY], - enum_types=[_INSTANCE_STATE, _INSTANCE_TIER], - serialized_options=_b( - "\352A]\n\035redis.googleapis.com/Instance\022`__ to which - the instance is connected. If left unspecified, the - ``default`` network will be used. - persistence_iam_identity: - Output only. Cloud IAM identity used by import / export - operations to transfer data to/from Cloud Storage. Format is - "serviceAccount:". The value may change over time for a given - instance so should be checked before each import/export - operation. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.Instance) - ), -) -_sym_db.RegisterMessage(Instance) -_sym_db.RegisterMessage(Instance.LabelsEntry) -_sym_db.RegisterMessage(Instance.RedisConfigsEntry) - -ListInstancesRequest = _reflection.GeneratedProtocolMessageType( - "ListInstancesRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LISTINSTANCESREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [ListInstances][google.cloud.redis.v1beta1.CloudRedis.ListInstances]. - - - Attributes: - parent: - Required. The resource name of the instance location using the - form: ``projects/{project_id}/locations/{location_id}`` where - ``location_id`` refers to a GCP region. - page_size: - The maximum number of items to return. If not specified, a - default value of 1000 will be used by the service. Regardless - of the page\_size value, the response may include a partial - list and a caller should only rely on response's [next\_page\_ - token][CloudRedis.ListInstancesResponse.next\_page\_token] to - determine if there are more instances left to be queried. - page_token: - The next\_page\_token value returned from a previous List - request, if any. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.ListInstancesRequest) - ), -) -_sym_db.RegisterMessage(ListInstancesRequest) - -ListInstancesResponse = _reflection.GeneratedProtocolMessageType( - "ListInstancesResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LISTINSTANCESRESPONSE, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Response for - [ListInstances][google.cloud.redis.v1beta1.CloudRedis.ListInstances]. - - - Attributes: - instances: - A list of Redis instances in the project in the specified - location, or across all locations. If the ``location_id`` in - the parent field of the request is "-", all regions available - to the project are queried, and the results aggregated. If in - such an aggregated query a location is unavailable, a dummy - Redis entry is included in the response with the "name" field - set to a value of the form - projects/{project\_id}/locations/{location\_id}/instances/- - and the "status" field set to ERROR and "status\_message" - field set to "location not available for ListInstances". - next_page_token: - Token to retrieve the next page of results, or empty if there - are no more results in the list. - unreachable: - Locations that could not be reached. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.ListInstancesResponse) - ), -) -_sym_db.RegisterMessage(ListInstancesResponse) - -GetInstanceRequest = _reflection.GeneratedProtocolMessageType( - "GetInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_GETINSTANCEREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [GetInstance][google.cloud.redis.v1beta1.CloudRedis.GetInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.GetInstanceRequest) - ), -) -_sym_db.RegisterMessage(GetInstanceRequest) - -CreateInstanceRequest = _reflection.GeneratedProtocolMessageType( - "CreateInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_CREATEINSTANCEREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [CreateInstance][google.cloud.redis.v1beta1.CloudRedis.CreateInstance]. - - - Attributes: - parent: - Required. The resource name of the instance location using the - form: ``projects/{project_id}/locations/{location_id}`` where - ``location_id`` refers to a GCP region. - instance_id: - Required. The logical name of the Redis instance in the - customer project with the following restrictions: - Must - contain only lowercase letters, numbers, and hyphens. - Must - start with a letter. - Must be between 1-40 characters. - - Must end with a number or a letter. - Must be unique within - the customer project / location - instance: - Required. A Redis [Instance] resource - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.CreateInstanceRequest) - ), -) -_sym_db.RegisterMessage(CreateInstanceRequest) - -UpdateInstanceRequest = _reflection.GeneratedProtocolMessageType( - "UpdateInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_UPDATEINSTANCEREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [UpdateInstance][google.cloud.redis.v1beta1.CloudRedis.UpdateInstance]. - - - Attributes: - update_mask: - Required. Mask of fields to update. At least one path must be - supplied in this field. The elements of the repeated paths - field may only include these fields from - [Instance][google.cloud.redis.v1beta1.Instance]: - - ``displayName`` - ``labels`` - ``memorySizeGb`` - - ``redisConfig`` - instance: - Required. Update description. Only fields specified in - update\_mask are updated. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.UpdateInstanceRequest) - ), -) -_sym_db.RegisterMessage(UpdateInstanceRequest) - -DeleteInstanceRequest = _reflection.GeneratedProtocolMessageType( - "DeleteInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_DELETEINSTANCEREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [DeleteInstance][google.cloud.redis.v1beta1.CloudRedis.DeleteInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.DeleteInstanceRequest) - ), -) -_sym_db.RegisterMessage(DeleteInstanceRequest) - -GcsSource = _reflection.GeneratedProtocolMessageType( - "GcsSource", - (_message.Message,), - dict( - DESCRIPTOR=_GCSSOURCE, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""The Cloud Storage location for the input content - - - Attributes: - uri: - Required. Source data URI. (e.g. - 'gs://my\_bucket/my\_object'). - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.GcsSource) - ), -) -_sym_db.RegisterMessage(GcsSource) - -InputConfig = _reflection.GeneratedProtocolMessageType( - "InputConfig", - (_message.Message,), - dict( - DESCRIPTOR=_INPUTCONFIG, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""The input content - - - Attributes: - source: - Required. Specify source location of input data - gcs_source: - Google Cloud Storage location where input content is located. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.InputConfig) - ), -) -_sym_db.RegisterMessage(InputConfig) - -ImportInstanceRequest = _reflection.GeneratedProtocolMessageType( - "ImportInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_IMPORTINSTANCEREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [Import][google.cloud.redis.v1beta1.CloudRedis.ImportInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - input_config: - Required. Specify data to be imported. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.ImportInstanceRequest) - ), -) -_sym_db.RegisterMessage(ImportInstanceRequest) - -GcsDestination = _reflection.GeneratedProtocolMessageType( - "GcsDestination", - (_message.Message,), - dict( - DESCRIPTOR=_GCSDESTINATION, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""The Cloud Storage location for the output content - - - Attributes: - uri: - Required. Data destination URI (e.g. - 'gs://my\_bucket/my\_object'). Existing files will be - overwritten. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.GcsDestination) - ), -) -_sym_db.RegisterMessage(GcsDestination) - -OutputConfig = _reflection.GeneratedProtocolMessageType( - "OutputConfig", - (_message.Message,), - dict( - DESCRIPTOR=_OUTPUTCONFIG, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""The output content - - - Attributes: - destination: - Required. Specify destination location of output data - gcs_destination: - Google Cloud Storage destination for output content. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.OutputConfig) - ), -) -_sym_db.RegisterMessage(OutputConfig) - -ExportInstanceRequest = _reflection.GeneratedProtocolMessageType( - "ExportInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_EXPORTINSTANCEREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [Export][google.cloud.redis.v1beta1.CloudRedis.ExportInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - output_config: - Required. Specify data to be exported. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.ExportInstanceRequest) - ), -) -_sym_db.RegisterMessage(ExportInstanceRequest) - -FailoverInstanceRequest = _reflection.GeneratedProtocolMessageType( - "FailoverInstanceRequest", - (_message.Message,), - dict( - DESCRIPTOR=_FAILOVERINSTANCEREQUEST, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Request for - [Failover][google.cloud.redis.v1beta1.CloudRedis.FailoverInstance]. - - - Attributes: - name: - Required. Redis instance resource name using the form: ``proje - cts/{project_id}/locations/{location_id}/instances/{instance_i - d}`` where ``location_id`` refers to a GCP region. - data_protection_mode: - Optional. Available data protection modes that the user can - choose. If it's unspecified, data protection mode will be - LIMITED\_DATA\_LOSS by default. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.FailoverInstanceRequest) - ), -) -_sym_db.RegisterMessage(FailoverInstanceRequest) - -LocationMetadata = _reflection.GeneratedProtocolMessageType( - "LocationMetadata", - (_message.Message,), - dict( - AvailableZonesEntry=_reflection.GeneratedProtocolMessageType( - "AvailableZonesEntry", - (_message.Message,), - dict( - DESCRIPTOR=_LOCATIONMETADATA_AVAILABLEZONESENTRY, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2" - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.LocationMetadata.AvailableZonesEntry) - ), - ), - DESCRIPTOR=_LOCATIONMETADATA, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""This location metadata represents additional configuration - options for a given location where a Redis instance may be created. All - fields are output only. It is returned as content of the - ``google.cloud.location.Location.metadata`` field. - - - Attributes: - available_zones: - Output only. The set of available zones in the location. The - map is keyed by the lowercase ID of each zone, as defined by - GCE. These keys can be specified in ``location_id`` or - ``alternative_location_id`` fields when creating a Redis - instance. - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.LocationMetadata) - ), -) -_sym_db.RegisterMessage(LocationMetadata) -_sym_db.RegisterMessage(LocationMetadata.AvailableZonesEntry) - -ZoneMetadata = _reflection.GeneratedProtocolMessageType( - "ZoneMetadata", - (_message.Message,), - dict( - DESCRIPTOR=_ZONEMETADATA, - __module__="google.cloud.redis_v1beta1.proto.cloud_redis_pb2", - __doc__="""Defines specific information for a particular zone. - Currently empty and reserved for future use only. - - """, - # @@protoc_insertion_point(class_scope:google.cloud.redis.v1beta1.ZoneMetadata) - ), -) -_sym_db.RegisterMessage(ZoneMetadata) - - -DESCRIPTOR._options = None -_INSTANCE_LABELSENTRY._options = None -_INSTANCE_REDISCONFIGSENTRY._options = None -_INSTANCE.fields_by_name["name"]._options = None -_INSTANCE.fields_by_name["location_id"]._options = None -_INSTANCE.fields_by_name["alternative_location_id"]._options = None -_INSTANCE.fields_by_name["redis_version"]._options = None -_INSTANCE.fields_by_name["reserved_ip_range"]._options = None -_INSTANCE.fields_by_name["host"]._options = None -_INSTANCE.fields_by_name["port"]._options = None -_INSTANCE.fields_by_name["current_location_id"]._options = None -_INSTANCE.fields_by_name["create_time"]._options = None -_INSTANCE.fields_by_name["state"]._options = None -_INSTANCE.fields_by_name["status_message"]._options = None -_INSTANCE.fields_by_name["redis_configs"]._options = None -_INSTANCE.fields_by_name["tier"]._options = None -_INSTANCE.fields_by_name["memory_size_gb"]._options = None -_INSTANCE.fields_by_name["authorized_network"]._options = None -_INSTANCE.fields_by_name["persistence_iam_identity"]._options = None -_INSTANCE._options = None -_LISTINSTANCESREQUEST.fields_by_name["parent"]._options = None -_GETINSTANCEREQUEST.fields_by_name["name"]._options = None -_CREATEINSTANCEREQUEST.fields_by_name["parent"]._options = None -_CREATEINSTANCEREQUEST.fields_by_name["instance_id"]._options = None -_CREATEINSTANCEREQUEST.fields_by_name["instance"]._options = None -_UPDATEINSTANCEREQUEST.fields_by_name["update_mask"]._options = None -_UPDATEINSTANCEREQUEST.fields_by_name["instance"]._options = None -_DELETEINSTANCEREQUEST.fields_by_name["name"]._options = None -_GCSSOURCE.fields_by_name["uri"]._options = None -_IMPORTINSTANCEREQUEST.fields_by_name["name"]._options = None -_IMPORTINSTANCEREQUEST.fields_by_name["input_config"]._options = None -_GCSDESTINATION.fields_by_name["uri"]._options = None -_EXPORTINSTANCEREQUEST.fields_by_name["name"]._options = None -_EXPORTINSTANCEREQUEST.fields_by_name["output_config"]._options = None -_FAILOVERINSTANCEREQUEST.fields_by_name["name"]._options = None -_FAILOVERINSTANCEREQUEST.fields_by_name["data_protection_mode"]._options = None -_LOCATIONMETADATA_AVAILABLEZONESENTRY._options = None -_LOCATIONMETADATA.fields_by_name["available_zones"]._options = None - -_CLOUDREDIS = _descriptor.ServiceDescriptor( - name="CloudRedis", - full_name="google.cloud.redis.v1beta1.CloudRedis", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\024redis.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=3138, - serialized_end=5098, - methods=[ - _descriptor.MethodDescriptor( - name="ListInstances", - full_name="google.cloud.redis.v1beta1.CloudRedis.ListInstances", - index=0, - containing_service=None, - input_type=_LISTINSTANCESREQUEST, - output_type=_LISTINSTANCESRESPONSE, - serialized_options=_b( - "\202\323\344\223\0024\0222/v1beta1/{parent=projects/*/locations/*}/instances\332A\006parent" - ), - ), - _descriptor.MethodDescriptor( - name="GetInstance", - full_name="google.cloud.redis.v1beta1.CloudRedis.GetInstance", - index=1, - containing_service=None, - input_type=_GETINSTANCEREQUEST, - output_type=_INSTANCE, - serialized_options=_b( - "\202\323\344\223\0024\0222/v1beta1/{name=projects/*/locations/*/instances/*}\332A\004name" - ), - ), - _descriptor.MethodDescriptor( - name="CreateInstance", - full_name="google.cloud.redis.v1beta1.CloudRedis.CreateInstance", - index=2, - containing_service=None, - input_type=_CREATEINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - '\202\323\344\223\002>"2/v1beta1/{parent=projects/*/locations/*}/instances:\010instance\332A\033parent,instance_id,instance\312A:\n#google.cloud.redis.v1beta1.Instance\022\023google.protobuf.Any' - ), - ), - _descriptor.MethodDescriptor( - name="UpdateInstance", - full_name="google.cloud.redis.v1beta1.CloudRedis.UpdateInstance", - index=3, - containing_service=None, - input_type=_UPDATEINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\002G2;/v1beta1/{instance.name=projects/*/locations/*/instances/*}:\010instance\332A\024update_mask,instance\312A:\n#google.cloud.redis.v1beta1.Instance\022\023google.protobuf.Any" - ), - ), - _descriptor.MethodDescriptor( - name="ImportInstance", - full_name="google.cloud.redis.v1beta1.CloudRedis.ImportInstance", - index=4, - containing_service=None, - input_type=_IMPORTINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - '\202\323\344\223\002>"9/v1beta1/{name=projects/*/locations/*/instances/*}:import:\001*\332A\021name,input_config\312A:\n#google.cloud.redis.v1beta1.Instance\022\023google.protobuf.Any' - ), - ), - _descriptor.MethodDescriptor( - name="ExportInstance", - full_name="google.cloud.redis.v1beta1.CloudRedis.ExportInstance", - index=5, - containing_service=None, - input_type=_EXPORTINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - '\202\323\344\223\002>"9/v1beta1/{name=projects/*/locations/*/instances/*}:export:\001*\332A\022name,output_config\312A:\n#google.cloud.redis.v1beta1.Instance\022\023google.protobuf.Any' - ), - ), - _descriptor.MethodDescriptor( - name="FailoverInstance", - full_name="google.cloud.redis.v1beta1.CloudRedis.FailoverInstance", - index=6, - containing_service=None, - input_type=_FAILOVERINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - '\202\323\344\223\002@";/v1beta1/{name=projects/*/locations/*/instances/*}:failover:\001*\332A\031name,data_protection_mode\312A:\n#google.cloud.redis.v1beta1.Instance\022\023google.protobuf.Any' - ), - ), - _descriptor.MethodDescriptor( - name="DeleteInstance", - full_name="google.cloud.redis.v1beta1.CloudRedis.DeleteInstance", - index=7, - containing_service=None, - input_type=_DELETEINSTANCEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - "\202\323\344\223\0024*2/v1beta1/{name=projects/*/locations/*/instances/*}\332A\004name\312A,\n\025google.protobuf.Empty\022\023google.protobuf.Any" - ), - ), - ], -) -_sym_db.RegisterServiceDescriptor(_CLOUDREDIS) - -DESCRIPTOR.services_by_name["CloudRedis"] = _CLOUDREDIS - -# @@protoc_insertion_point(module_scope) diff --git a/redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2_grpc.py b/redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2_grpc.py deleted file mode 100644 index b25842d334a8..000000000000 --- a/redis/google/cloud/redis_v1beta1/proto/cloud_redis_pb2_grpc.py +++ /dev/null @@ -1,235 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.redis_v1beta1.proto import ( - cloud_redis_pb2 as google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2, -) -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) - - -class CloudRedisStub(object): - """Configures and manages Cloud Memorystore for Redis instances - - Google Cloud Memorystore for Redis v1beta1 - - The `redis.googleapis.com` service implements the Google Cloud Memorystore - for Redis API and defines the following resource model for managing Redis - instances: - * The service works with a collection of cloud projects, named: `/projects/*` - * Each project has a collection of available locations, named: `/locations/*` - * Each location has a collection of Redis instances, named: `/instances/*` - * As such, Redis instances are resources of the form: - `/projects/{project_id}/locations/{location_id}/instances/{instance_id}` - - Note that location_id must be refering to a GCP `region`; for example: - * `projects/redpepper-1290/locations/us-central1/instances/my-redis` - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.ListInstances = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/ListInstances", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ListInstancesRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ListInstancesResponse.FromString, - ) - self.GetInstance = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/GetInstance", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.GetInstanceRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.Instance.FromString, - ) - self.CreateInstance = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/CreateInstance", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.CreateInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.UpdateInstance = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/UpdateInstance", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.UpdateInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.ImportInstance = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/ImportInstance", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ImportInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.ExportInstance = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/ExportInstance", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ExportInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.FailoverInstance = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/FailoverInstance", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.FailoverInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.DeleteInstance = channel.unary_unary( - "/google.cloud.redis.v1beta1.CloudRedis/DeleteInstance", - request_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.DeleteInstanceRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - - -class CloudRedisServicer(object): - """Configures and manages Cloud Memorystore for Redis instances - - Google Cloud Memorystore for Redis v1beta1 - - The `redis.googleapis.com` service implements the Google Cloud Memorystore - for Redis API and defines the following resource model for managing Redis - instances: - * The service works with a collection of cloud projects, named: `/projects/*` - * Each project has a collection of available locations, named: `/locations/*` - * Each location has a collection of Redis instances, named: `/instances/*` - * As such, Redis instances are resources of the form: - `/projects/{project_id}/locations/{location_id}/instances/{instance_id}` - - Note that location_id must be refering to a GCP `region`; for example: - * `projects/redpepper-1290/locations/us-central1/instances/my-redis` - """ - - def ListInstances(self, request, context): - """Lists all Redis instances owned by a project in either the specified - location (region) or all locations. - - The location should have the following format: - * `projects/{project_id}/locations/{location_id}` - - If `location_id` is specified as `-` (wildcard), then all regions - available to the project are queried, and the results are aggregated. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def GetInstance(self, request, context): - """Gets the details of a specific Redis instance. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def CreateInstance(self, request, context): - """Creates a Redis instance based on the specified tier and memory size. - - By default, the instance is accessible from the project's - [default network](/compute/docs/networks-and-firewalls#networks). - - The creation is executed asynchronously and callers may check the returned - operation to track its progress. Once the operation is completed the Redis - instance will be fully functional. Completed longrunning.Operation will - contain the new instance object in the response field. - - The returned operation is automatically deleted after a few hours, so there - is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def UpdateInstance(self, request, context): - """Updates the metadata and configuration of a specific Redis instance. - - Completed longrunning.Operation will contain the new instance object - in the response field. The returned operation is automatically deleted - after a few hours, so there is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ImportInstance(self, request, context): - """Import a Redis RDB snapshot file from Cloud Storage into a Redis instance. - - Redis may stop serving during this operation. Instance state will be - IMPORTING for entire operation. When complete, the instance will contain - only data from the imported file. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def ExportInstance(self, request, context): - """Export Redis instance data into a Redis RDB format file in Cloud Storage. - - Redis will continue serving during this operation. - - The returned operation is automatically deleted after a few hours, so - there is no need to call DeleteOperation. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def FailoverInstance(self, request, context): - """Initiates a failover of the master node to current replica node for a - specific STANDARD tier Cloud Memorystore for Redis instance. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def DeleteInstance(self, request, context): - """Deletes a specific Redis instance. Instance stops serving and data is - deleted. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_CloudRedisServicer_to_server(servicer, server): - rpc_method_handlers = { - "ListInstances": grpc.unary_unary_rpc_method_handler( - servicer.ListInstances, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ListInstancesRequest.FromString, - response_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ListInstancesResponse.SerializeToString, - ), - "GetInstance": grpc.unary_unary_rpc_method_handler( - servicer.GetInstance, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.GetInstanceRequest.FromString, - response_serializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.Instance.SerializeToString, - ), - "CreateInstance": grpc.unary_unary_rpc_method_handler( - servicer.CreateInstance, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.CreateInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "UpdateInstance": grpc.unary_unary_rpc_method_handler( - servicer.UpdateInstance, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.UpdateInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "ImportInstance": grpc.unary_unary_rpc_method_handler( - servicer.ImportInstance, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ImportInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "ExportInstance": grpc.unary_unary_rpc_method_handler( - servicer.ExportInstance, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.ExportInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "FailoverInstance": grpc.unary_unary_rpc_method_handler( - servicer.FailoverInstance, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.FailoverInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "DeleteInstance": grpc.unary_unary_rpc_method_handler( - servicer.DeleteInstance, - request_deserializer=google_dot_cloud_dot_redis__v1beta1_dot_proto_dot_cloud__redis__pb2.DeleteInstanceRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.redis.v1beta1.CloudRedis", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/redis/google/cloud/redis_v1beta1/types.py b/redis/google/cloud/redis_v1beta1/types.py deleted file mode 100644 index c7de16bf64f7..000000000000 --- a/redis/google/cloud/redis_v1beta1/types.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.redis_v1beta1.proto import cloud_redis_pb2 -from google.longrunning import operations_pb2 -from google.protobuf import any_pb2 -from google.protobuf import field_mask_pb2 -from google.protobuf import timestamp_pb2 -from google.rpc import status_pb2 - - -_shared_modules = [operations_pb2, any_pb2, field_mask_pb2, timestamp_pb2, status_pb2] - -_local_modules = [cloud_redis_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.redis_v1beta1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/redis/noxfile.py b/redis/noxfile.py deleted file mode 100644 index 7949a4e3925a..000000000000 --- a/redis/noxfile.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by synthtool. DO NOT EDIT! - -from __future__ import absolute_import -import os -import shutil - -import nox - - -LOCAL_DEPS = (os.path.join("..", "api_core"), os.path.join("..", "core")) -BLACK_VERSION = "black==19.3b0" -BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] - -if os.path.exists("samples"): - BLACK_PATHS.append("samples") - - -@nox.session(python="3.7") -def lint(session): - """Run linters. - - Returns a failure if the linters find linting errors or sufficiently - serious code quality issues. - """ - session.install("flake8", BLACK_VERSION, *LOCAL_DEPS) - session.run("black", "--check", *BLACK_PATHS) - session.run("flake8", "google", "tests") - - -@nox.session(python="3.6") -def blacken(session): - """Run black. - - Format code to uniform standard. - - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. - That run uses an image that doesn't have 3.6 installed. Before updating this - check the state of the `gcp_ubuntu_config` we use for that Kokoro run. - """ - session.install(BLACK_VERSION) - session.run("black", *BLACK_PATHS) - - -@nox.session(python="3.7") -def lint_setup_py(session): - """Verify that setup.py is valid (including RST check).""" - session.install("docutils", "pygments") - session.run("python", "setup.py", "check", "--restructuredtext", "--strict") - - -def default(session): - # Install all test dependencies, then install this package in-place. - session.install("mock", "pytest", "pytest-cov") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", ".") - - # Run py.test against the unit tests. - session.run( - "py.test", - "--quiet", - "--cov=google.cloud", - "--cov=tests.unit", - "--cov-append", - "--cov-config=.coveragerc", - "--cov-report=", - "--cov-fail-under=0", - os.path.join("tests", "unit"), - *session.posargs, - ) - - -@nox.session(python=["2.7", "3.5", "3.6", "3.7", "3.8"]) -def unit(session): - """Run the unit test suite.""" - default(session) - - -@nox.session(python=["2.7", "3.7"]) -def system(session): - """Run the system test suite.""" - system_test_path = os.path.join("tests", "system.py") - system_test_folder_path = os.path.join("tests", "system") - # Sanity check: Only run tests if the environment variable is set. - if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): - session.skip("Credentials must be set via environment variable") - - system_test_exists = os.path.exists(system_test_path) - system_test_folder_exists = os.path.exists(system_test_folder_path) - # Sanity check: only run tests if found. - if not system_test_exists and not system_test_folder_exists: - session.skip("System tests were not found") - - # Use pre-release gRPC for system tests. - session.install("--pre", "grpcio") - - # Install all test dependencies, then install this package into the - # virtualenv's dist-packages. - session.install("mock", "pytest") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", "../test_utils/") - session.install("-e", ".") - - # Run py.test against the system tests. - if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) - if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) - - -@nox.session(python="3.7") -def cover(session): - """Run the final coverage report. - - This outputs the coverage report aggregating coverage from the unit - test runs (not system test runs), and then erases coverage data. - """ - session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=100") - - session.run("coverage", "erase") - - -@nox.session(python="3.7") -def docs(session): - """Build the docs for this library.""" - - session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark") - - shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) - session.run( - "sphinx-build", - "-W", # warnings as errors - "-T", # show full traceback on exception - "-N", # no colors - "-b", - "html", - "-d", - os.path.join("docs", "_build", "doctrees", ""), - os.path.join("docs", ""), - os.path.join("docs", "_build", "html", ""), - ) diff --git a/redis/setup.cfg b/redis/setup.cfg deleted file mode 100644 index 3bd555500e37..000000000000 --- a/redis/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[bdist_wheel] -universal = 1 diff --git a/redis/setup.py b/redis/setup.py deleted file mode 100644 index 5ed53d6a6119..000000000000 --- a/redis/setup.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import io -import os - -import setuptools - - -# Package metadata. - -name = "google-cloud-redis" -description = "Google Cloud Memorystore for Redis API client library" -version = "0.3.0" -# Should be one of: -# 'Development Status :: 3 - Alpha' -# 'Development Status :: 4 - Beta' -# 'Development Status :: 5 - Production/Stable' -release_status = "Development Status :: 3 - Alpha" -dependencies = [ - "google-api-core[grpc] >= 1.14.0, < 2.0.0dev", - 'enum34; python_version < "3.4"', -] -extras = {} - -# Setup boilerplate below this line. - -package_root = os.path.abspath(os.path.dirname(__file__)) - -readme_filename = os.path.join(package_root, "README.rst") -with io.open(readme_filename, encoding="utf-8") as readme_file: - readme = readme_file.read() - -# Only include packages under the 'google' namespace. Do not include tests, -# benchmarks, etc. -packages = [ - package for package in setuptools.find_packages() if package.startswith("google") -] - -# Determine which namespaces are needed. -namespaces = ["google"] -if "google.cloud" in packages: - namespaces.append("google.cloud") - - -setuptools.setup( - name=name, - version=version, - description=description, - long_description=readme, - author="Google LLC", - author_email="googleapis-packages@google.com", - license="Apache 2.0", - url="https://github.com/GoogleCloudPlatform/google-cloud-python", - classifiers=[ - release_status, - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Operating System :: OS Independent", - "Topic :: Internet", - ], - platforms="Posix; MacOS X; Windows", - packages=packages, - namespace_packages=namespaces, - install_requires=dependencies, - extras_require=extras, - python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*", - include_package_data=True, - zip_safe=False, -) diff --git a/redis/synth.metadata b/redis/synth.metadata deleted file mode 100644 index 57fc4adc4af3..000000000000 --- a/redis/synth.metadata +++ /dev/null @@ -1,202 +0,0 @@ -{ - "updateTime": "2020-01-29T13:26:20.841851Z", - "sources": [ - { - "generator": { - "name": "artman", - "version": "0.44.4", - "dockerImage": "googleapis/artman@sha256:19e945954fc960a4bdfee6cb34695898ab21a8cf0bac063ee39b91f00a1faec8" - } - }, - { - "git": { - "name": "googleapis", - "remote": "https://github.com/googleapis/googleapis.git", - "sha": "cf3b61102ed5f36b827bc82ec39be09525f018c8", - "internalRef": "292034635", - "log": "cf3b61102ed5f36b827bc82ec39be09525f018c8\n Fix to protos for v1p1beta1 release of Cloud Security Command Center\n\nPiperOrigin-RevId: 292034635\n\n4e1cfaa7c0fede9e65d64213ca3da1b1255816c0\nUpdate the public proto to support UTF-8 encoded id for CatalogService API, increase the ListCatalogItems deadline to 300s and some minor documentation change\n\nPiperOrigin-RevId: 292030970\n\n9c483584f8fd5a1b862ae07973f4cc7bb3e46648\nasset: add annotations to v1p1beta1\n\nPiperOrigin-RevId: 292009868\n\ne19209fac29731d0baf6d9ac23da1164f7bdca24\nAdd the google.rpc.context.AttributeContext message to the open source\ndirectories.\n\nPiperOrigin-RevId: 291999930\n\nae5662960573f279502bf98a108a35ba1175e782\noslogin API: move file level option on top of the file to avoid protobuf.js bug.\n\nPiperOrigin-RevId: 291990506\n\neba3897fff7c49ed85d3c47fc96fe96e47f6f684\nAdd cc_proto_library and cc_grpc_library targets for Spanner and IAM protos.\n\nPiperOrigin-RevId: 291988651\n\n8e981acfd9b97ea2f312f11bbaa7b6c16e412dea\nBeta launch for PersonDetection and FaceDetection features.\n\nPiperOrigin-RevId: 291821782\n\n994e067fae3b21e195f7da932b08fff806d70b5d\nasset: add annotations to v1p2beta1\n\nPiperOrigin-RevId: 291815259\n\n244e1d2c89346ca2e0701b39e65552330d68545a\nAdd Playable Locations service\n\nPiperOrigin-RevId: 291806349\n\n909f8f67963daf45dd88d020877fb9029b76788d\nasset: add annotations to v1beta2\n\nPiperOrigin-RevId: 291805301\n\n3c39a1d6e23c1ef63c7fba4019c25e76c40dfe19\nKMS: add file-level message for CryptoKeyPath, it is defined in gapic yaml but not\nin proto files.\n\nPiperOrigin-RevId: 291420695\n\nc6f3f350b8387f8d1b85ed4506f30187ebaaddc3\ncontaineranalysis: update v1beta1 and bazel build with annotations\n\nPiperOrigin-RevId: 291401900\n\n92887d74b44e4e636252b7b8477d0d2570cd82db\nfix: fix the location of grpc config file.\n\nPiperOrigin-RevId: 291396015\n\ne26cab8afd19d396b929039dac5d874cf0b5336c\nexpr: add default_host and method_signature annotations to CelService\n\nPiperOrigin-RevId: 291240093\n\n06093ae3952441c34ec176d1f7431b8765cec0be\nirm: fix v1alpha2 bazel build by adding missing proto imports\n\nPiperOrigin-RevId: 291227940\n\na8a2514af326e4673063f9a3c9d0ef1091c87e6c\nAdd proto annotation for cloud/irm API\n\nPiperOrigin-RevId: 291217859\n\n8d16f76de065f530d395a4c7eabbf766d6a120fd\nGenerate Memcache v1beta2 API protos and gRPC ServiceConfig files\n\nPiperOrigin-RevId: 291008516\n\n3af1dabd93df9a9f17bf3624d3b875c11235360b\ngrafeas: Add containeranalysis default_host to Grafeas service\n\nPiperOrigin-RevId: 290965849\n\nbe2663fa95e31cba67d0cd62611a6674db9f74b7\nfix(google/maps/roads): add missing opening bracket\n\nPiperOrigin-RevId: 290964086\n\nfacc26550a0af0696e0534bc9cae9df14275aa7c\nUpdating v2 protos with the latest inline documentation (in comments) and adding a per-service .yaml file.\n\nPiperOrigin-RevId: 290952261\n\ncda99c1f7dc5e4ca9b1caeae1dc330838cbc1461\nChange api_name to 'asset' for v1p1beta1\n\nPiperOrigin-RevId: 290800639\n\n94e9e90c303a820ce40643d9129e7f0d2054e8a1\nAdds Google Maps Road service\n\nPiperOrigin-RevId: 290795667\n\na3b23dcb2eaecce98c600c7d009451bdec52dbda\nrpc: new message ErrorInfo, other comment updates\n\nPiperOrigin-RevId: 290781668\n\n26420ef4e46c37f193c0fbe53d6ebac481de460e\nAdd proto definition for Org Policy v1.\n\nPiperOrigin-RevId: 290771923\n\n7f0dab8177cf371ae019a082e2512de7ac102888\nPublish Routes Preferred API v1 service definitions.\n\nPiperOrigin-RevId: 290326986\n\nad6e508d0728e1d1bca6e3f328cd562718cb772d\nFix: Qualify resource type references with \"jobs.googleapis.com/\"\n\nPiperOrigin-RevId: 290285762\n\n58e770d568a2b78168ddc19a874178fee8265a9d\ncts client library\n\nPiperOrigin-RevId: 290146169\n\naf9daa4c3b4c4a8b7133b81588dd9ffd37270af2\nAdd more programming language options to public proto\n\nPiperOrigin-RevId: 290144091\n\nd9f2bbf2df301ef84641d4cec7c828736a0bd907\ntalent: add missing resource.proto dep to Bazel build target\n\nPiperOrigin-RevId: 290143164\n\n3b3968237451d027b42471cd28884a5a1faed6c7\nAnnotate Talent API.\nAdd gRPC service config for retry.\nUpdate bazel file with google.api.resource dependency.\n\nPiperOrigin-RevId: 290125172\n\n0735b4b096872960568d1f366bfa75b7b0e1f1a3\nWeekly library update.\n\nPiperOrigin-RevId: 289939042\n\n8760d3d9a4543d7f9c0d1c7870aca08b116e4095\nWeekly library update.\n\nPiperOrigin-RevId: 289939020\n\n8607df842f782a901805187e02fff598145b0b0e\nChange Talent API timeout to 30s.\n\nPiperOrigin-RevId: 289912621\n\n908155991fe32570653bcb72ecfdcfc896642f41\nAdd Recommendations AI V1Beta1\n\nPiperOrigin-RevId: 289901914\n\n5c9a8c2bebd8b71aa66d1cc473edfaac837a2c78\nAdding no-arg method signatures for ListBillingAccounts and ListServices\n\nPiperOrigin-RevId: 289891136\n\n50b0e8286ac988b0593bd890eb31fef6ea2f5767\nlongrunning: add grpc service config and default_host annotation to operations.proto\n\nPiperOrigin-RevId: 289876944\n\n6cac27dabe51c54807b0401698c32d34998948a9\n Updating default deadline for Cloud Security Command Center's v1 APIs.\n\nPiperOrigin-RevId: 289875412\n\nd99df0d67057a233c711187e0689baa4f8e6333d\nFix: Correct spelling in C# namespace option\n\nPiperOrigin-RevId: 289709813\n\n2fa8d48165cc48e35b0c62e6f7bdade12229326c\nfeat: Publish Recommender v1 to GitHub.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289619243\n\n9118db63d1ab493a2e44a3b4973fde810a835c49\nfirestore: don't retry reads that fail with Aborted\n\nFor transaction reads that fail with ABORTED, we need to rollback and start a new transaction. Our current configuration makes it so that GAPIC retries ABORTED reads multiple times without making any progress. Instead, we should retry at the transaction level.\n\nPiperOrigin-RevId: 289532382\n\n1dbfd3fe4330790b1e99c0bb20beb692f1e20b8a\nFix bazel build\nAdd other langauges (Java was already there) for bigquery/storage/v1alpha2 api.\n\nPiperOrigin-RevId: 289519766\n\nc06599cdd7d11f8d3fd25f8d3249e5bb1a3d5d73\nInitial commit of google.cloud.policytroubleshooter API, The API helps in troubleshooting GCP policies. Refer https://cloud.google.com/iam/docs/troubleshooting-access for more information\n\nPiperOrigin-RevId: 289491444\n\nfce7d80fa16ea241e87f7bc33d68595422e94ecd\nDo not pass samples option for Artman config of recommender v1 API.\n\nPiperOrigin-RevId: 289477403\n\nef179e8c61436297e6bb124352e47e45c8c80cb1\nfix: Address missing Bazel dependency.\n\nBazel builds stopped working in 06ec6d5 because\nthe google/longrunning/operations.proto file took\nan import from google/api/client.proto, but that\nimport was not added to BUILD.bazel.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289446074\n\n8841655b242c84fd691d77d7bcf21b61044f01ff\nMigrate Data Labeling v1beta1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289446026\n\n06ec6d5d053fff299eaa6eaa38afdd36c5e2fc68\nAdd annotations to google.longrunning.v1\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289413169\n\n0480cf40be1d3cc231f4268a2fdb36a8dd60e641\nMigrate IAM Admin v1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289411084\n\n1017173e9adeb858587639af61889ad970c728b1\nSpecify a C# namespace for BigQuery Connection v1beta1\n\nPiperOrigin-RevId: 289396763\n\nb08714b378e8e5b0c4ecdde73f92c36d6303b4b6\nfix: Integrate latest proto-docs-plugin fix.\nFixes dialogflow v2\n\nPiperOrigin-RevId: 289189004\n\n51217a67e79255ee1f2e70a6a3919df082513327\nCreate BUILD file for recommender v1\n\nPiperOrigin-RevId: 289183234\n\nacacd87263c0a60e458561b8b8ce9f67c760552a\nGenerate recommender v1 API protos and gRPC ServiceConfig files\n\nPiperOrigin-RevId: 289177510\n\n9d2f7133b97720b1fa3601f6dcd30760ba6d8a1e\nFix kokoro build script\n\nPiperOrigin-RevId: 289166315\n\nc43a67530d2a47a0220cad20ca8de39b3fbaf2c5\ncloudtasks: replace missing RPC timeout config for v2beta2 and v2beta3\n\nPiperOrigin-RevId: 289162391\n\n4cefc229a9197236fc0adf02d69b71c0c5cf59de\nSynchronize new proto/yaml changes.\n\nPiperOrigin-RevId: 289158456\n\n56f263fe959c50786dab42e3c61402d32d1417bd\nCatalog API: Adding config necessary to build client libraries\n\nPiperOrigin-RevId: 289149879\n\n4543762b23a57fc3c53d409efc3a9affd47b6ab3\nFix Bazel build\nbilling/v1 and dialogflow/v2 remain broken (not bazel-related issues).\nBilling has wrong configuration, dialogflow failure is caused by a bug in documentation plugin.\n\nPiperOrigin-RevId: 289140194\n\nc9dce519127b97e866ca133a01157f4ce27dcceb\nUpdate Bigtable docs\n\nPiperOrigin-RevId: 289114419\n\n802c5c5f2bf94c3facb011267d04e71942e0d09f\nMigrate DLP to proto annotations (but not GAPIC v2).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 289102579\n\n6357f30f2ec3cff1d8239d18b707ff9d438ea5da\nRemove gRPC configuration file that was in the wrong place.\n\nPiperOrigin-RevId: 289096111\n\n360a8792ed62f944109d7e22d613a04a010665b4\n Protos for v1p1beta1 release of Cloud Security Command Center\n\nPiperOrigin-RevId: 289011995\n\na79211c20c4f2807eec524d00123bf7c06ad3d6e\nRoll back containeranalysis v1 to GAPIC v1.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288999068\n\n9e60345ba603e03484a8aaa33ce5ffa19c1c652b\nPublish Routes Preferred API v1 proto definitions.\n\nPiperOrigin-RevId: 288941399\n\nd52885b642ad2aa1f42b132ee62dbf49a73e1e24\nMigrate the service management API to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288909426\n\n6ace586805c08896fef43e28a261337fcf3f022b\ncloudtasks: replace missing RPC timeout config\n\nPiperOrigin-RevId: 288783603\n\n51d906cabee4876b12497054b15b05d4a50ad027\nImport of Grafeas from Github.\n\nUpdate BUILD.bazel accordingly.\n\nPiperOrigin-RevId: 288783426\n\n5ef42bcd363ba0440f0ee65b3c80b499e9067ede\nMigrate Recommender v1beta1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288713066\n\n94f986afd365b7d7e132315ddcd43d7af0e652fb\nMigrate Container Analysis v1 to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288708382\n\n7a751a279184970d3b6ba90e4dd4d22a382a0747\nRemove Container Analysis v1alpha1 (nobody publishes it).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288707473\n\n3c0d9c71242e70474b2b640e15bb0a435fd06ff0\nRemove specious annotation from BigQuery Data Transfer before\nanyone accidentally does anything that uses it.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288701604\n\n1af307a4764bd415ef942ac5187fa1def043006f\nMigrate BigQuery Connection to GAPIC v2.\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 288698681\n\n08b488e0660c59842a7dee0e3e2b65d9e3a514a9\nExposing cloud_catalog.proto (This API is already available through REST)\n\nPiperOrigin-RevId: 288625007\n\na613482977e11ac09fa47687a5d1b5a01efcf794\nUpdate the OS Login v1beta API description to render better in the UI.\n\nPiperOrigin-RevId: 288547940\n\n5e182b8d9943f1b17008d69d4c7e865dc83641a7\nUpdate the OS Login API description to render better in the UI.\n\nPiperOrigin-RevId: 288546443\n\ncb79155f596e0396dd900da93872be7066f6340d\nFix: Add a resource annotation for Agent\nFix: Correct the service name in annotations for Intent and SessionEntityType\n\nPiperOrigin-RevId: 288441307\n\nf7f6e9daec3315fd47cb638789bd8415bf4a27cc\nAdded cloud asset api v1p1beta1\n\nPiperOrigin-RevId: 288427239\n\nf2880f5b342c6345f3dcaad24fcb3c6ca9483654\nBilling account API: Adding config necessary to build client libraries\n\nPiperOrigin-RevId: 288351810\n\ndc250ffe071729f8f8bef9d6fd0fbbeb0254c666\nFix: Remove incorrect resource annotations in requests\n\nPiperOrigin-RevId: 288321208\n\n91ef2d9dd69807b0b79555f22566fb2d81e49ff9\nAdd GAPIC annotations to Cloud KMS (but do not migrate the GAPIC config yet).\n\nCommitter: @lukesneeringer\nPiperOrigin-RevId: 287999179\n\n" - } - }, - { - "template": { - "name": "python_library", - "origin": "synthtool.gcp", - "version": "2019.10.17" - } - } - ], - "destinations": [ - { - "client": { - "source": "googleapis", - "apiName": "redis", - "apiVersion": "v1beta1", - "language": "python", - "generator": "gapic", - "config": "google/cloud/redis/artman_redis_v1beta1.yaml" - } - }, - { - "client": { - "source": "googleapis", - "apiName": "redis", - "apiVersion": "v1", - "language": "python", - "generator": "gapic", - "config": "google/cloud/redis/artman_redis_v1.yaml" - } - } - ], - "newFiles": [ - { - "path": ".coveragerc" - }, - { - "path": ".flake8" - }, - { - "path": ".repo-metadata.json" - }, - { - "path": "CHANGELOG.md" - }, - { - "path": "LICENSE" - }, - { - "path": "MANIFEST.in" - }, - { - "path": "README.rst" - }, - { - "path": "docs/README.rst" - }, - { - "path": "docs/_static/custom.css" - }, - { - "path": "docs/_templates/layout.html" - }, - { - "path": "docs/conf.py" - }, - { - "path": "docs/gapic/v1/api.rst" - }, - { - "path": "docs/gapic/v1/types.rst" - }, - { - "path": "docs/gapic/v1beta1/api.rst" - }, - { - "path": "docs/gapic/v1beta1/types.rst" - }, - { - "path": "docs/index.rst" - }, - { - "path": "google/__init__.py" - }, - { - "path": "google/cloud/__init__.py" - }, - { - "path": "google/cloud/redis.py" - }, - { - "path": "google/cloud/redis_v1/__init__.py" - }, - { - "path": "google/cloud/redis_v1/gapic/__init__.py" - }, - { - "path": "google/cloud/redis_v1/gapic/cloud_redis_client.py" - }, - { - "path": "google/cloud/redis_v1/gapic/cloud_redis_client_config.py" - }, - { - "path": "google/cloud/redis_v1/gapic/enums.py" - }, - { - "path": "google/cloud/redis_v1/gapic/transports/__init__.py" - }, - { - "path": "google/cloud/redis_v1/gapic/transports/cloud_redis_grpc_transport.py" - }, - { - "path": "google/cloud/redis_v1/proto/__init__.py" - }, - { - "path": "google/cloud/redis_v1/proto/cloud_redis.proto" - }, - { - "path": "google/cloud/redis_v1/proto/cloud_redis_pb2.py" - }, - { - "path": "google/cloud/redis_v1/proto/cloud_redis_pb2_grpc.py" - }, - { - "path": "google/cloud/redis_v1/types.py" - }, - { - "path": "google/cloud/redis_v1beta1/__init__.py" - }, - { - "path": "google/cloud/redis_v1beta1/gapic/__init__.py" - }, - { - "path": "google/cloud/redis_v1beta1/gapic/cloud_redis_client.py" - }, - { - "path": "google/cloud/redis_v1beta1/gapic/cloud_redis_client_config.py" - }, - { - "path": "google/cloud/redis_v1beta1/gapic/enums.py" - }, - { - "path": "google/cloud/redis_v1beta1/gapic/transports/__init__.py" - }, - { - "path": "google/cloud/redis_v1beta1/gapic/transports/cloud_redis_grpc_transport.py" - }, - { - "path": "google/cloud/redis_v1beta1/proto/__init__.py" - }, - { - "path": "google/cloud/redis_v1beta1/proto/cloud_redis.proto" - }, - { - "path": "google/cloud/redis_v1beta1/proto/cloud_redis_pb2.py" - }, - { - "path": "google/cloud/redis_v1beta1/proto/cloud_redis_pb2_grpc.py" - }, - { - "path": "google/cloud/redis_v1beta1/types.py" - }, - { - "path": "noxfile.py" - }, - { - "path": "setup.cfg" - }, - { - "path": "setup.py" - }, - { - "path": "synth.metadata" - }, - { - "path": "synth.py" - }, - { - "path": "tests/unit/gapic/v1/test_cloud_redis_client_v1.py" - }, - { - "path": "tests/unit/gapic/v1beta1/test_cloud_redis_client_v1beta1.py" - } - ] -} \ No newline at end of file diff --git a/redis/synth.py b/redis/synth.py deleted file mode 100644 index b569680461f3..000000000000 --- a/redis/synth.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This script is used to synthesize generated parts of this library.""" - -import synthtool as s -import synthtool.gcp as gcp -import logging - -logging.basicConfig(level=logging.DEBUG) - -gapic = gcp.GAPICGenerator() -common = gcp.CommonTemplates() -excludes = ["README.rst", "setup.py", "nox*.py", "docs/conf.py", "docs/index.rst"] - -# ---------------------------------------------------------------------------- -# Generate redis GAPIC layer -# ---------------------------------------------------------------------------- -for version in ["v1beta1", "v1"]: - library = gapic.py_library( - "redis", - version, - config_path=f"artman_redis_{version}.yaml", - include_protos=True, - ) - - s.copy(library, excludes=excludes) - -# Fix docstrings -s.replace( - "google/cloud/**/cloud_redis_client.py", - r"resources of the form:\n ``", - r"resources of the form:\n\n ``", -) - -s.replace( - "google/cloud/**/cloud_redis_client.py", - r""" - parent \(str\): Required. The resource name of the instance location using the form: - :: - - `projects/{project_id}/locations/{location_id}` - where ``location_id`` refers to a GCP region""", - r""" - parent (str): Required. The resource name of the instance location using the form ``projects/{project_id}/locations/{location_id}`` - where ``location_id`` refers to a GCP region""", -) - - -s.replace( - "google/cloud/**/cloud_redis_client.py", - r""" - with the following restrictions: - - \* Must contain only lowercase letters, numbers, and hyphens\.""", - r""" - with the following restrictions: - * Must contain only lowercase letters, numbers, and hyphens.""", -) - -s.replace( - "google/cloud/**/cloud_redis_client.py", - r""" - name \(str\): Required. Redis instance resource name using the form: - :: - - `projects/{project_id}/locations/{location_id}/instances/{instance_id}` - where ``location_id`` refers to a GCP region""", - r""" - name (str): Required. Redis instance resource name using the form ``projects/{project_id}/locations/{location_id}/instances/{instance_id}``` - where ``location_id`` refers to a GCP region""", -) - -s.replace( - "google/cloud/**/cloud_redis_client.py", - r""" - fields from ``Instance``: - - \* ``displayName`` - \* ``labels`` - \* ``memorySizeGb`` - \* ``redisConfig``""", - r""" - fields from ``Instance``: ``displayName``, ``labels``, ``memorySizeGb``, and ``redisConfig``.""", -) - -# ---------------------------------------------------------------------------- -# Add templated files -# ---------------------------------------------------------------------------- -templated_files = common.py_library(unit_cov_level=97, cov_level=100) -s.move(templated_files) - -s.shell.run(["nox", "-s", "blacken"], hide_output=False) diff --git a/redis/tests/unit/gapic/v1/test_cloud_redis_client_v1.py b/redis/tests/unit/gapic/v1/test_cloud_redis_client_v1.py deleted file mode 100644 index f9ccc5ea0525..000000000000 --- a/redis/tests/unit/gapic/v1/test_cloud_redis_client_v1.py +++ /dev/null @@ -1,639 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit tests.""" - -import mock -import pytest - -from google.rpc import status_pb2 - -from google.cloud import redis_v1 -from google.cloud.redis_v1 import enums -from google.cloud.redis_v1.proto import cloud_redis_pb2 -from google.longrunning import operations_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestCloudRedisClient(object): - def test_list_instances(self): - # Setup Expected Response - next_page_token = "" - instances_element = {} - instances = [instances_element] - expected_response = {"next_page_token": next_page_token, "instances": instances} - expected_response = cloud_redis_pb2.ListInstancesResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - parent = client.location_path("[PROJECT]", "[LOCATION]") - - paged_list_response = client.list_instances(parent) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.instances[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.ListInstancesRequest(parent=parent) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_instances_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup request - parent = client.location_path("[PROJECT]", "[LOCATION]") - - paged_list_response = client.list_instances(parent) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_get_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.get_instance(name) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.GetInstanceRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_instance_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - with pytest.raises(CustomException): - client.get_instance(name) - - def test_create_instance(self): - # Setup Expected Response - name = "name3373707" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb_2 = 1493816946 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb_2, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_create_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - parent = client.location_path("[PROJECT]", "[LOCATION]") - instance_id = "test_instance" - tier = enums.Instance.Tier.BASIC - memory_size_gb = 1 - instance = {"tier": tier, "memory_size_gb": memory_size_gb} - - response = client.create_instance(parent, instance_id, instance) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.CreateInstanceRequest( - parent=parent, instance_id=instance_id, instance=instance - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_create_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_create_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - parent = client.location_path("[PROJECT]", "[LOCATION]") - instance_id = "test_instance" - tier = enums.Instance.Tier.BASIC - memory_size_gb = 1 - instance = {"tier": tier, "memory_size_gb": memory_size_gb} - - response = client.create_instance(parent, instance_id, instance) - exception = response.exception() - assert exception.errors[0] == error - - def test_update_instance(self): - # Setup Expected Response - name = "name3373707" - display_name_2 = "displayName21615000987" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name, - "display_name": display_name_2, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_update_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - paths_element = "display_name" - paths_element_2 = "memory_size_gb" - paths = [paths_element, paths_element_2] - update_mask = {"paths": paths} - display_name = " instance.memory_size_gb=4" - instance = {"display_name": display_name} - - response = client.update_instance(update_mask, instance) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.UpdateInstanceRequest( - update_mask=update_mask, instance=instance - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_update_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_update_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - paths_element = "display_name" - paths_element_2 = "memory_size_gb" - paths = [paths_element, paths_element_2] - update_mask = {"paths": paths} - display_name = " instance.memory_size_gb=4" - instance = {"display_name": display_name} - - response = client.update_instance(update_mask, instance) - exception = response.exception() - assert exception.errors[0] == error - - def test_import_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_import_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = "name3373707" - input_config = {} - - response = client.import_instance(name, input_config) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.ImportInstanceRequest( - name=name, input_config=input_config - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_import_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_import_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = "name3373707" - input_config = {} - - response = client.import_instance(name, input_config) - exception = response.exception() - assert exception.errors[0] == error - - def test_export_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_export_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = "name3373707" - output_config = {} - - response = client.export_instance(name, output_config) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.ExportInstanceRequest( - name=name, output_config=output_config - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_export_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_export_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = "name3373707" - output_config = {} - - response = client.export_instance(name, output_config) - exception = response.exception() - assert exception.errors[0] == error - - def test_failover_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_failover_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.failover_instance(name) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.FailoverInstanceRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_failover_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_failover_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.failover_instance(name) - exception = response.exception() - assert exception.errors[0] == error - - def test_delete_instance(self): - # Setup Expected Response - expected_response = {} - expected_response = empty_pb2.Empty(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_delete_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.delete_instance(name) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.DeleteInstanceRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_delete_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_delete_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.delete_instance(name) - exception = response.exception() - assert exception.errors[0] == error diff --git a/redis/tests/unit/gapic/v1beta1/test_cloud_redis_client_v1beta1.py b/redis/tests/unit/gapic/v1beta1/test_cloud_redis_client_v1beta1.py deleted file mode 100644 index dd6abf77992d..000000000000 --- a/redis/tests/unit/gapic/v1beta1/test_cloud_redis_client_v1beta1.py +++ /dev/null @@ -1,641 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Unit tests.""" - -import mock -import pytest - -from google.rpc import status_pb2 - -from google.cloud import redis_v1beta1 -from google.cloud.redis_v1beta1 import enums -from google.cloud.redis_v1beta1.proto import cloud_redis_pb2 -from google.longrunning import operations_pb2 -from google.protobuf import empty_pb2 -from google.protobuf import field_mask_pb2 - - -class MultiCallableStub(object): - """Stub for the grpc.UnaryUnaryMultiCallable interface.""" - - def __init__(self, method, channel_stub): - self.method = method - self.channel_stub = channel_stub - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - self.channel_stub.requests.append((self.method, request)) - - response = None - if self.channel_stub.responses: - response = self.channel_stub.responses.pop() - - if isinstance(response, Exception): - raise response - - if response: - return response - - -class ChannelStub(object): - """Stub for the grpc.Channel interface.""" - - def __init__(self, responses=[]): - self.responses = responses - self.requests = [] - - def unary_unary(self, method, request_serializer=None, response_deserializer=None): - return MultiCallableStub(method, self) - - -class CustomException(Exception): - pass - - -class TestCloudRedisClient(object): - def test_list_instances(self): - # Setup Expected Response - next_page_token = "" - instances_element = {} - instances = [instances_element] - expected_response = {"next_page_token": next_page_token, "instances": instances} - expected_response = cloud_redis_pb2.ListInstancesResponse(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - parent = client.location_path("[PROJECT]", "[LOCATION]") - - paged_list_response = client.list_instances(parent) - resources = list(paged_list_response) - assert len(resources) == 1 - - assert expected_response.instances[0] == resources[0] - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.ListInstancesRequest(parent=parent) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_list_instances_exception(self): - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup request - parent = client.location_path("[PROJECT]", "[LOCATION]") - - paged_list_response = client.list_instances(parent) - with pytest.raises(CustomException): - list(paged_list_response) - - def test_get_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - - # Mock the API response - channel = ChannelStub(responses=[expected_response]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.get_instance(name) - assert expected_response == response - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.GetInstanceRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_get_instance_exception(self): - # Mock the API response - channel = ChannelStub(responses=[CustomException()]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - with pytest.raises(CustomException): - client.get_instance(name) - - def test_create_instance(self): - # Setup Expected Response - name = "name3373707" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb_2 = 1493816946 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb_2, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_create_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - parent = client.location_path("[PROJECT]", "[LOCATION]") - instance_id = "test_instance" - tier = enums.Instance.Tier.BASIC - memory_size_gb = 1 - instance = {"tier": tier, "memory_size_gb": memory_size_gb} - - response = client.create_instance(parent, instance_id, instance) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.CreateInstanceRequest( - parent=parent, instance_id=instance_id, instance=instance - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_create_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_create_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - parent = client.location_path("[PROJECT]", "[LOCATION]") - instance_id = "test_instance" - tier = enums.Instance.Tier.BASIC - memory_size_gb = 1 - instance = {"tier": tier, "memory_size_gb": memory_size_gb} - - response = client.create_instance(parent, instance_id, instance) - exception = response.exception() - assert exception.errors[0] == error - - def test_update_instance(self): - # Setup Expected Response - name = "name3373707" - display_name_2 = "displayName21615000987" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb_2 = 1493816946 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name, - "display_name": display_name_2, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb_2, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_update_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - paths_element = "display_name" - paths_element_2 = "memory_size_gb" - paths = [paths_element, paths_element_2] - update_mask = {"paths": paths} - display_name = "UpdatedDisplayName" - memory_size_gb = 4 - instance = {"display_name": display_name, "memory_size_gb": memory_size_gb} - - response = client.update_instance(update_mask, instance) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.UpdateInstanceRequest( - update_mask=update_mask, instance=instance - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_update_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_update_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - paths_element = "display_name" - paths_element_2 = "memory_size_gb" - paths = [paths_element, paths_element_2] - update_mask = {"paths": paths} - display_name = "UpdatedDisplayName" - memory_size_gb = 4 - instance = {"display_name": display_name, "memory_size_gb": memory_size_gb} - - response = client.update_instance(update_mask, instance) - exception = response.exception() - assert exception.errors[0] == error - - def test_import_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_import_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = "name3373707" - input_config = {} - - response = client.import_instance(name, input_config) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.ImportInstanceRequest( - name=name, input_config=input_config - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_import_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_import_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = "name3373707" - input_config = {} - - response = client.import_instance(name, input_config) - exception = response.exception() - assert exception.errors[0] == error - - def test_export_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_export_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = "name3373707" - output_config = {} - - response = client.export_instance(name, output_config) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.ExportInstanceRequest( - name=name, output_config=output_config - ) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_export_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_export_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = "name3373707" - output_config = {} - - response = client.export_instance(name, output_config) - exception = response.exception() - assert exception.errors[0] == error - - def test_failover_instance(self): - # Setup Expected Response - name_2 = "name2-1052831874" - display_name = "displayName1615086568" - location_id = "locationId552319461" - alternative_location_id = "alternativeLocationId-718920621" - redis_version = "redisVersion-685310444" - reserved_ip_range = "reservedIpRange-1082940580" - host = "host3208616" - port = 3446913 - current_location_id = "currentLocationId1312712735" - status_message = "statusMessage-239442758" - memory_size_gb = 34199707 - authorized_network = "authorizedNetwork-1733809270" - persistence_iam_identity = "persistenceIamIdentity1061944584" - expected_response = { - "name": name_2, - "display_name": display_name, - "location_id": location_id, - "alternative_location_id": alternative_location_id, - "redis_version": redis_version, - "reserved_ip_range": reserved_ip_range, - "host": host, - "port": port, - "current_location_id": current_location_id, - "status_message": status_message, - "memory_size_gb": memory_size_gb, - "authorized_network": authorized_network, - "persistence_iam_identity": persistence_iam_identity, - } - expected_response = cloud_redis_pb2.Instance(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_failover_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.failover_instance(name) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.FailoverInstanceRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_failover_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_failover_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.failover_instance(name) - exception = response.exception() - assert exception.errors[0] == error - - def test_delete_instance(self): - # Setup Expected Response - expected_response = {} - expected_response = empty_pb2.Empty(**expected_response) - operation = operations_pb2.Operation( - name="operations/test_delete_instance", done=True - ) - operation.response.Pack(expected_response) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.delete_instance(name) - result = response.result() - assert expected_response == result - - assert len(channel.requests) == 1 - expected_request = cloud_redis_pb2.DeleteInstanceRequest(name=name) - actual_request = channel.requests[0][1] - assert expected_request == actual_request - - def test_delete_instance_exception(self): - # Setup Response - error = status_pb2.Status() - operation = operations_pb2.Operation( - name="operations/test_delete_instance_exception", done=True - ) - operation.error.CopyFrom(error) - - # Mock the API response - channel = ChannelStub(responses=[operation]) - patch = mock.patch("google.api_core.grpc_helpers.create_channel") - with patch as create_channel: - create_channel.return_value = channel - client = redis_v1beta1.CloudRedisClient() - - # Setup Request - name = client.instance_path("[PROJECT]", "[LOCATION]", "[INSTANCE]") - - response = client.delete_instance(name) - exception = response.exception() - assert exception.errors[0] == error diff --git a/speech/.coveragerc b/speech/.coveragerc deleted file mode 100644 index b178b094aa1d..000000000000 --- a/speech/.coveragerc +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[run] -branch = True - -[report] -fail_under = 100 -show_missing = True -exclude_lines = - # Re-enable the standard pragma - pragma: NO COVER - # Ignore debug-only repr - def __repr__ - # Ignore abstract methods - raise NotImplementedError -omit = - */gapic/*.py - */proto/*.py - */core/*.py - */site-packages/*.py \ No newline at end of file diff --git a/speech/.flake8 b/speech/.flake8 deleted file mode 100644 index 0268ecc9c55c..000000000000 --- a/speech/.flake8 +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by synthtool. DO NOT EDIT! -[flake8] -ignore = E203, E266, E501, W503 -exclude = - # Exclude generated code. - **/proto/** - **/gapic/** - *_pb2.py - - # Standard linting exemptions. - __pycache__, - .git, - *.pyc, - conf.py diff --git a/speech/.repo-metadata.json b/speech/.repo-metadata.json deleted file mode 100644 index 18500b9ac8a0..000000000000 --- a/speech/.repo-metadata.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "speech", - "name_pretty": "Cloud Speech", - "product_documentation": "https://cloud.google.com/speech-to-text/docs/", - "client_documentation": "https://googleapis.dev/python/speech/latest", - "issue_tracker": "https://issuetracker.google.com/savedsearches/559758", - "release_level": "ga", - "language": "python", - "repo": "googleapis/google-cloud-python", - "distribution_name": "google-cloud-speech", - "api_id": "speech.googleapis.com", - "requires_billing": false -} \ No newline at end of file diff --git a/speech/CHANGELOG.md b/speech/CHANGELOG.md deleted file mode 100644 index 68d1538cc2df..000000000000 --- a/speech/CHANGELOG.md +++ /dev/null @@ -1,251 +0,0 @@ -# Changelog - -[PyPI History][1] - -[1]: https://pypi.org/project/google-cloud-speech/#history - -## 1.3.1 - -12-06-2019 13:05 PST - -### Implementation Changes -- Increase timeout values in client config (via synth). ([#9922](https://github.com/googleapis/google-cloud-python/pull/9922)) - -## 1.3.0 - -11-21-2019 14:03 PST - - -### Implementation Changes -- Mark `Recognize` as idempotent (via synth). ([#9874](https://github.com/googleapis/google-cloud-python/pull/9874)) -- Re-add unused `speaker_tag`; update spacing in docs templates (via synth). ([#9765](https://github.com/googleapis/google-cloud-python/pull/9765)) -- Move `speaker_tag` field from `SpeakerDiarizationConfig` to `WordInfo` (via synth). ([#9576](https://github.com/googleapis/google-cloud-python/pull/9576)) -- Remove send/recv msg size limit (via synth). ([#8969](https://github.com/googleapis/google-cloud-python/pull/8969)) - -### New Features -- Add speaker diarization configuration support (via synth). ([#9202](https://github.com/googleapis/google-cloud-python/pull/9202)) -- Add `SpeakerDiarizationConfig`, deprecate enable_speaker_diarization and diarization_speaker_count (via synth). ([#8795](https://github.com/googleapis/google-cloud-python/pull/8795)) - -### Documentation -- Add python 2 sunset banner to documentation. ([#9036](https://github.com/googleapis/google-cloud-python/pull/9036)) -- Reorder samples. ([#9313](https://github.com/googleapis/google-cloud-python/pull/9313)) -- Update docstrings (via synth). ([#9292](https://github.com/googleapis/google-cloud-python/pull/9292)) -- Fix intersphinx reference to requests. ([#9294](https://github.com/googleapis/google-cloud-python/pull/9294)) -- Add generated code samples. ([#9153](https://github.com/googleapis/google-cloud-python/pull/9153)) -- Remove CI for gh-pages, use googleapis.dev for `api_core` refs. ([#9085](https://github.com/googleapis/google-cloud-python/pull/9085)) -- Remove compatibility badges from READMEs. ([#9035](https://github.com/googleapis/google-cloud-python/pull/9035)) -- Update intersphinx mapping for requests. ([#8805](https://github.com/googleapis/google-cloud-python/pull/8805)) - -### Internal / Testing Changes -- Add v1p1beta1 systests for longrunning / streaming recognize. ([#9287](https://github.com/googleapis/google-cloud-python/pull/9287)) -- Add v1 systests for longrunning / streaming recognize. ([#9285](https://github.com/googleapis/google-cloud-python/pull/9285)) -- Update samples manifest (via synth). ([#9211](https://github.com/googleapis/google-cloud-python/pull/9211)) - -## 1.2.0 - -07-24-2019 17:35 PDT - -### New Features -- Add 'client_options' support (via synth). ([#8534](https://github.com/googleapis/google-cloud-python/pull/8534)) - -### Dependencies -- Bump minimum version for google-api-core to 1.14.0. ([#8709](https://github.com/googleapis/google-cloud-python/pull/8709)) -- Pin black version (via synth). ([#8596](https://github.com/googleapis/google-cloud-python/pull/8596)) - -### Documentation -- Link to googleapis.dev documentation in READMEs. ([#8705](https://github.com/googleapis/google-cloud-python/pull/8705)) -- Add compatibility check badges to READMEs. ([#8288](https://github.com/googleapis/google-cloud-python/pull/8288)) - -## 1.1.0 - -06-27-2019 16:55 PDT - -### Implementation Changes -- Allow kwargs to be passed to 'create_channel' (via synth). ([#8428](https://github.com/googleapis/google-cloud-python/pull/8428)) -- Remove classifier for Python 3.4 for end-of-life. ([#7535](https://github.com/googleapis/google-cloud-python/pull/7535)) - -### New Features -- Increase speech max received msg size to 256 MiB ([#8338](https://github.com/googleapis/google-cloud-python/pull/8338)) -- Add MP3 to Audio Encoding and add boost to Speech Context (via synth). ([#8109](https://github.com/googleapis/google-cloud-python/pull/8109)) -- Add Recognition Metadata (via synth). ([#7961](https://github.com/googleapis/google-cloud-python/pull/7961)) - -### Documentation -- Update to show 'google-cloud-speech' is GA. ([#8453](https://github.com/googleapis/google-cloud-python/pull/8453)) -- Tweak 'SpeechContext' docstring (via synth). ([#8223](https://github.com/googleapis/google-cloud-python/pull/8223)) - -### Internal / Testing Changes -- All: Add docs job to publish to googleapis.dev. ([#8464](https://github.com/googleapis/google-cloud-python/pull/8464)) -- (Re)-blacken (via synth). ([#8446](https://github.com/googleapis/google-cloud-python/pull/8446)) -- Add disclaimer to auto-generated template files (via synth). ([#8328](https://github.com/googleapis/google-cloud-python/pull/8328)) -- Suppress checking 'cov-fail-under' in nox default session (via synth). ([#8252](https://github.com/googleapis/google-cloud-python/pull/8252)) -- Fix coverage in 'types.py' (via synth). ([#8164](https://github.com/googleapis/google-cloud-python/pull/8164)) -- Blacken noxfile.py, setup.py (via synth). ([#8132](https://github.com/googleapis/google-cloud-python/pull/8132)) -- Add empty lines. ([#8072](https://github.com/googleapis/google-cloud-python/pull/8072)) -- Update noxfile (via synth). ([#7836](https://github.com/googleapis/google-cloud-python/pull/7836)) -- Add nox session `docs` (via synth). ([#7782](https://github.com/googleapis/google-cloud-python/pull/7782)) - -## 1.0.0 - -03-18-2019 08:05 PDT - - -### Implementation Changes -- Remove unused message exports. ([#7275](https://github.com/googleapis/google-cloud-python/pull/7275)) - -### New Features -- Promote google-cloud-speech to GA ([#7525](https://github.com/googleapis/google-cloud-python/pull/7525)) - -### Documentation -- Updated client library documentation URLs. ([#7307](https://github.com/googleapis/google-cloud-python/pull/7307)) - -### Internal / Testing Changes -- Speech: copy lintified proto files (via synth). -- Add clarifying comment to blacken nox target. ([#7404](https://github.com/googleapis/google-cloud-python/pull/7404)) -- Copy proto files alongside protoc versions. Remove unneeded utf-8 header. - -## 0.36.3 - -01-31-2019 09:57 PST - - -### New Features -- Add 'RecognitionConfig.audio_channel_count' field via synth. ([#7240](https://github.com/googleapis/google-cloud-python/pull/7240)) - -### Documentation -- Modify file headers. ([#7158](https://github.com/googleapis/google-cloud-python/pull/7158)) - -### Internal / Testing Changes -- Add protos as an artifact to library ([#7205](https://github.com/googleapis/google-cloud-python/pull/7205)) - -## 0.36.2 - -01-10-2019 15:36 PST - -### Implementation Changes -- Protoc-generated serialization update. ([#7106](https://github.com/googleapis/google-cloud-python/pull/7106)) - -### Documentation -- Regenerate speech to change quote chars in docstr. -- Pick up stub docstring fix in GAPIC generator. ([#6982](https://github.com/googleapis/google-cloud-python/pull/6982)) - -## 0.36.1 - -12-18-2018 09:46 PST - - -### Implementation Changes -- Import `iam.policy` from `google.api_core`. ([#6741](https://github.com/googleapis/google-cloud-python/pull/6741)) -- Pick up fixes to GAIPC generator. ([#6508](https://github.com/googleapis/google-cloud-python/pull/6508)) -- Add `result_end_time`, docstring changes via synth. ([#6462](https://github.com/googleapis/google-cloud-python/pull/6462)) -- Assorted synth fixups / cleanups ([#6400](https://github.com/googleapis/google-cloud-python/pull/6400)) -- Fix `client_info` bug, update docstrings and timeouts. ([#6421](https://github.com/googleapis/google-cloud-python/pull/6421)) -- Re-generate library using speech/synth.py ([#5979](https://github.com/googleapis/google-cloud-python/pull/5979)) - -### Dependencies -- Bump minimum `api_core` version for all GAPIC libs to 1.4.1. ([#6391](https://github.com/googleapis/google-cloud-python/pull/6391)) - -### Documentation -- Document Python 2 deprecation ([#6910](https://github.com/googleapis/google-cloud-python/pull/6910)) -- Clarify passed arguments in speech examples. ([#6857](https://github.com/googleapis/google-cloud-python/pull/6857)) -- Docs: normalize use of support level badges ([#6159](https://github.com/googleapis/google-cloud-python/pull/6159)) -- Fix client library URL. ([#6052](https://github.com/googleapis/google-cloud-python/pull/6052)) -- Prep docs for repo split. ([#6017](https://github.com/googleapis/google-cloud-python/pull/6017)) - -### Internal / Testing Changes -- Synth.metadata. ([#6868](https://github.com/googleapis/google-cloud-python/pull/6868)) -- Update noxfile. -- Blacken all gen'd libs ([#6792](https://github.com/googleapis/google-cloud-python/pull/6792)) -- Omit local deps ([#6701](https://github.com/googleapis/google-cloud-python/pull/6701)) -- Run black at end of synth.py ([#6698](https://github.com/googleapis/google-cloud-python/pull/6698)) -- Run Black on Generated libraries ([#6666](https://github.com/googleapis/google-cloud-python/pull/6666)) -- Add templates for flake8, coveragerc, noxfile, and black. ([#6642](https://github.com/googleapis/google-cloud-python/pull/6642)) -- Add / fix badges for PyPI / versions. ([#6158](https://github.com/googleapis/google-cloud-python/pull/6158)) -- Use new Nox ([#6175](https://github.com/googleapis/google-cloud-python/pull/6175)) - -## 0.36.0 - -### New Features - -- Re-generate the library to pick up changes and new features in the underlying API. ([#5915](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5915)) - -### Documentation - -- Fix broken links to description of 'Beta' ([#5917](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5917)) -- Replace links to '/stable/' with '/latest/'. ([#5901](https://github.com/GoogleCloudPlatform/google-cloud-python/pull/5901)) - -## 0.35.0 - -### Implementation Changes - -- Re-generated the library to pick up new API features. (#5577) - -### Internal / Testing Changes - -- Add Test runs for Python 3.7 and remove 3.4 (#5295) -- Avoid overwriting '__module__' of messages from shared modules. (#5364) -- Modify system tests to use prerelease versions of grpcio (#5304) - -## 0.34.0 - -### Implementation Changes -- Regenerate GAPIC to account for the removal of GoogleDataCollectionConfig and google_data_collection_opt_in (#5235) - -## 0.33.0 - -### New Features - -- Add Audio Logging and Recognition Metadata. (#5123) - -### Internal / Testing Changes - -- Fix bad trove classifier - -## 0.32.1 - -### Dependencies - -- Update dependency range for api-core to include v1.0.0 releases (#4944) - -### Testing and internal changes - -- Install local dependencies when running lint (#4936) -- Re-enable lint for tests, remove usage of pylint (#4921) -- Normalize all setup.py files (#4909) - -## 0.31.1 - -### Bugfixes - -- Fix speech helpers to properly pass retry and timeout args. (#4828, #4830) - -## 0.31.0 - -This is the (hopefully) final release candidate before 1.0. - -### Breaking Changes - -- The deprecated Speech layer (deprecated since 0.27.0) has been removed. If you are still using it, the [migration guide](https://cloud.google.com/speech/docs/python-client-migration) is still available. -- The following changes are _technically_ breaking but very unlikely to affect you directly: - * `google.cloud.gapic.speech.v1` moved to `google.cloud.speech_v1.gapic`, in accordance with more recent clients. - * `google.cloud.proto.speech.v1` moved to `google.cloud.speech_v1.proto`, in accordance with more recent clients. - -### Dependencies - - * Removed dependency on `google-gax`. - * Added dependency on `google-api-core`, its replacement. - -## 0.30.0 - -### Documentation - -- Added link to "Python Development Environment Setup Guide" in - project README (#4187, h/t to @michaelawyu) - -### Dependencies - -- Upgrading to `google-cloud-core >= 0.28.0` and adding dependency - on `google-api-core` (#4221, #4280) -- Deferring to `google-api-core` for `grpcio` and - `googleapis-common-protos`dependencies (#4096, #4098) - -PyPI: https://pypi.org/project/google-cloud-speech/0.30.0/ diff --git a/speech/LICENSE b/speech/LICENSE deleted file mode 100644 index a8ee855de2aa..000000000000 --- a/speech/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/speech/MANIFEST.in b/speech/MANIFEST.in deleted file mode 100644 index 9cbf175afe6b..000000000000 --- a/speech/MANIFEST.in +++ /dev/null @@ -1,5 +0,0 @@ -include README.rst LICENSE -recursive-include google *.json *.proto -recursive-include tests * -global-exclude *.py[co] -global-exclude __pycache__ diff --git a/speech/README.rst b/speech/README.rst deleted file mode 100644 index 3cdf9fda5668..000000000000 --- a/speech/README.rst +++ /dev/null @@ -1,109 +0,0 @@ -Python Client for Cloud Speech API -================================== - - -|GA| |pypi| |versions| - -The `Cloud Speech API`_ enables developers to convert audio to text by applying -powerful neural network models. The API recognizes over 80 languages and -variants, to support your global user base. - -- `Client Library Documentation`_ -- `Product Documentation`_ - -.. |GA| image:: https://img.shields.io/badge/support-GA-gold.svg - :target: https://github.com/googleapis/google-cloud-python/blob/master/README.rst#general-availability -.. |pypi| image:: https://img.shields.io/pypi/v/google-cloud-speech.svg - :target: https://pypi.org/project/google-cloud-speech/ -.. |versions| image:: https://img.shields.io/pypi/pyversions/google-cloud-speech.svg - :target: https://pypi.org/project/google-cloud-speech/ -.. _Cloud Speech API: https://cloud.google.com/speech -.. _Client Library Documentation: https://googleapis.dev/python/speech/latest -.. _Product Documentation: https://cloud.google.com/speech - -Quick Start ------------ - -In order to use this library, you first need to go through the following steps: - -1. `Select or create a Cloud Platform project.`_ -2. `Enable billing for your project.`_ -3. `Enable the Cloud Speech API.`_ -4. `Setup Authentication.`_ - -.. _Select or create a Cloud Platform project.: https://console.cloud.google.com/project -.. _Enable billing for your project.: https://cloud.google.com/billing/docs/how-to/modify-project#enable_billing_for_a_project -.. _Enable the Cloud Speech API.: https://cloud.google.com/speech -.. _Setup Authentication.: https://googleapis.dev/python/google-api-core/latest/auth.html - -Installation -~~~~~~~~~~~~ - -Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to -create isolated Python environments. The basic problem it addresses is one of -dependencies and versions, and indirectly permissions. - -With `virtualenv`_, it's possible to install this library without needing system -install permissions, and without clashing with the installed system -dependencies. - -.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/ - - -Supported Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.5 - -Deprecated Python Versions -^^^^^^^^^^^^^^^^^^^^^^^^^^ -Python == 2.7. Python 2.7 support will be removed on January 1, 2020. - - -Mac/Linux -^^^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - source /bin/activate - /bin/pip install google-cloud-speech - - -Windows -^^^^^^^ - -.. code-block:: console - - pip install virtualenv - virtualenv - \Scripts\activate - \Scripts\pip.exe install google-cloud-speech - -Example Usage -~~~~~~~~~~~~~ - -.. code:: py - - from google.cloud import speech_v1 - from google.cloud.speech_v1 import enums - - client = speech_v1.SpeechClient() - - encoding = enums.RecognitionConfig.AudioEncoding.FLAC - sample_rate_hertz = 44100 - language_code = 'en-US' - config = {'encoding': encoding, 'sample_rate_hertz': sample_rate_hertz, 'language_code': language_code} - uri = 'gs://bucket_name/file_name.flac' - audio = {'uri': uri} - - response = client.recognize(config, audio) - -Next Steps -~~~~~~~~~~ - -- Read the `Client Library Documentation`_ for Cloud Speech API - API to see other available methods on the client. -- Read the `Product documentation`_ to learn - more about the product and see How-to Guides. - APIs that we cover. diff --git a/speech/docs/README.rst b/speech/docs/README.rst deleted file mode 120000 index 89a0106941ff..000000000000 --- a/speech/docs/README.rst +++ /dev/null @@ -1 +0,0 @@ -../README.rst \ No newline at end of file diff --git a/speech/docs/_static/custom.css b/speech/docs/_static/custom.css deleted file mode 100644 index 0abaf229fce3..000000000000 --- a/speech/docs/_static/custom.css +++ /dev/null @@ -1,4 +0,0 @@ -div#python2-eol { - border-color: red; - border-width: medium; -} \ No newline at end of file diff --git a/speech/docs/_templates/layout.html b/speech/docs/_templates/layout.html deleted file mode 100644 index 228529efe2d2..000000000000 --- a/speech/docs/_templates/layout.html +++ /dev/null @@ -1,50 +0,0 @@ - -{% extends "!layout.html" %} -{%- block content %} -{%- if theme_fixed_sidebar|lower == 'true' %} -
- {{ sidebar() }} - {%- block document %} -
- {%- if render_sidebar %} -
- {%- endif %} - - {%- block relbar_top %} - {%- if theme_show_relbar_top|tobool %} - - {%- endif %} - {% endblock %} - -
-
- On January 1, 2020 this library will no longer support Python 2 on the latest released version. - Previously released library versions will continue to be available. For more information please - visit Python 2 support on Google Cloud. -
- {% block body %} {% endblock %} -
- - {%- block relbar_bottom %} - {%- if theme_show_relbar_bottom|tobool %} - - {%- endif %} - {% endblock %} - - {%- if render_sidebar %} -
- {%- endif %} -
- {%- endblock %} -
-
-{%- else %} -{{ super() }} -{%- endif %} -{%- endblock %} diff --git a/speech/docs/changelog.md b/speech/docs/changelog.md deleted file mode 120000 index 04c99a55caae..000000000000 --- a/speech/docs/changelog.md +++ /dev/null @@ -1 +0,0 @@ -../CHANGELOG.md \ No newline at end of file diff --git a/speech/docs/conf.py b/speech/docs/conf.py deleted file mode 100644 index 75ca066ef747..000000000000 --- a/speech/docs/conf.py +++ /dev/null @@ -1,356 +0,0 @@ -# -*- coding: utf-8 -*- -# -# google-cloud-speech documentation build configuration file -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -import shlex - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath("..")) - -__version__ = "0.1.0" - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = "1.6.3" - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.intersphinx", - "sphinx.ext.coverage", - "sphinx.ext.napoleon", - "sphinx.ext.todo", - "sphinx.ext.viewcode", -] - -# autodoc/autosummary flags -autoclass_content = "both" -autodoc_default_flags = ["members"] -autosummary_generate = True - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# Allow markdown includes (so releases.md can include CHANGLEOG.md) -# http://www.sphinx-doc.org/en/master/markdown.html -source_parsers = {".md": "recommonmark.parser.CommonMarkParser"} - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = [".rst", ".md"] - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "index" - -# General information about the project. -project = u"google-cloud-speech" -copyright = u"2017, Google" -author = u"Google APIs" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The full version, including alpha/beta/rc tags. -release = __version__ -# The short X.Y version. -version = ".".join(release.split(".")[0:2]) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ["_build"] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "alabaster" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = { - "description": "Google Cloud Client Libraries for Python", - "github_user": "googleapis", - "github_repo": "google-cloud-python", - "github_banner": True, - "font_family": "'Roboto', Georgia, sans", - "head_font_family": "'Roboto', Georgia, serif", - "code_font_family": "'Roboto Mono', 'Consolas', monospace", -} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -# html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -# html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = "google-cloud-speech-doc" - -# -- Options for warnings ------------------------------------------------------ - -suppress_warnings = [ - # Temporarily suppress this to avoid "more than one target found for - # cross-reference" warning, which are intractable for us to avoid while in - # a mono-repo. - # See https://github.com/sphinx-doc/sphinx/blob - # /2a65ffeef5c107c19084fabdd706cdff3f52d93c/sphinx/domains/python.py#L843 - "ref.python" -] - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - #'preamble': '', - # Latex figure (float) alignment - #'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "google-cloud-speech.tex", - u"google-cloud-speech Documentation", - author, - "manual", - ) -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ( - master_doc, - "google-cloud-speech", - u"google-cloud-speech Documentation", - [author], - 1, - ) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "google-cloud-speech", - u"google-cloud-speech Documentation", - author, - "google-cloud-speech", - "GAPIC library for the {metadata.shortName} v1 service", - "APIs", - ) -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - "python": ("http://python.readthedocs.org/en/latest/", None), - "gax": ("https://gax-python.readthedocs.org/en/latest/", None), - "google-auth": ("https://google-auth.readthedocs.io/en/stable", None), - "google-gax": ("https://gax-python.readthedocs.io/en/latest/", None), - "google.api_core": ("https://googleapis.dev/python/google-api-core/latest", None), - "grpc": ("https://grpc.io/grpc/python/", None), - "requests": ("https://requests.kennethreitz.org/en/stable/", None), - "fastavro": ("https://fastavro.readthedocs.io/en/stable/", None), - "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), -} - -# Napoleon settings -napoleon_google_docstring = True -napoleon_numpy_docstring = True -napoleon_include_private_with_doc = False -napoleon_include_special_with_doc = True -napoleon_use_admonition_for_examples = False -napoleon_use_admonition_for_notes = False -napoleon_use_admonition_for_references = False -napoleon_use_ivar = False -napoleon_use_param = True -napoleon_use_rtype = True diff --git a/speech/docs/gapic/v1/api.rst b/speech/docs/gapic/v1/api.rst deleted file mode 100644 index a04f18ad6ba1..000000000000 --- a/speech/docs/gapic/v1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Cloud Speech-to-Text API -=================================== - -.. automodule:: google.cloud.speech_v1 - :members: - :inherited-members: \ No newline at end of file diff --git a/speech/docs/gapic/v1/types.rst b/speech/docs/gapic/v1/types.rst deleted file mode 100644 index 71a61184ef32..000000000000 --- a/speech/docs/gapic/v1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Cloud Speech-to-Text API Client -========================================= - -.. automodule:: google.cloud.speech_v1.types - :members: \ No newline at end of file diff --git a/speech/docs/gapic/v1p1beta1/api.rst b/speech/docs/gapic/v1p1beta1/api.rst deleted file mode 100644 index 9493c970c2bc..000000000000 --- a/speech/docs/gapic/v1p1beta1/api.rst +++ /dev/null @@ -1,6 +0,0 @@ -Client for Cloud Speech-to-Text API -=================================== - -.. automodule:: google.cloud.speech_v1p1beta1 - :members: - :inherited-members: \ No newline at end of file diff --git a/speech/docs/gapic/v1p1beta1/types.rst b/speech/docs/gapic/v1p1beta1/types.rst deleted file mode 100644 index 6ce93d567607..000000000000 --- a/speech/docs/gapic/v1p1beta1/types.rst +++ /dev/null @@ -1,5 +0,0 @@ -Types for Cloud Speech-to-Text API Client -========================================= - -.. automodule:: google.cloud.speech_v1p1beta1.types - :members: \ No newline at end of file diff --git a/speech/docs/index.rst b/speech/docs/index.rst deleted file mode 100644 index 02f947a7e224..000000000000 --- a/speech/docs/index.rst +++ /dev/null @@ -1,282 +0,0 @@ -.. include:: README.rst - -Using the Library ------------------ - -Asynchronous Recognition -~~~~~~~~~~~~~~~~~~~~~~~~ - -The :meth:`~.speech_v1.SpeechClient.long_running_recognize` method -sends audio data to the Speech API and initiates a Long Running Operation. - -Using this operation, you can periodically poll for recognition results. -Use asynchronous requests for audio data of any duration up to 80 minutes. - -See: `Speech Asynchronous Recognize`_ - - -.. code-block:: python - - >>> from google.cloud import speech - >>> client = speech.SpeechClient() - >>> audio = speech.types.RecognitionAudio( - ... uri='gs://my-bucket/recording.flac') - >>> config = speech.types.RecognitionConfig( - ... encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, - ... language_code='en-US', - ... sample_rate_hertz=44100) - >>> operation = client.long_running_recognize(config=config, audio=audio) - >>> op_result = operation.result() - >>> for result in op_result.results: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print(alternative.transcript) - ... print(alternative.confidence) - ==================== - 'how old is the Brooklyn Bridge' - 0.98267895 - - -Synchronous Recognition -~~~~~~~~~~~~~~~~~~~~~~~ - -The :meth:`~.speech_v1.SpeechClient.recognize` method converts speech -data to text and returns alternative text transcriptions. - -This example uses ``language_code='en-GB'`` to better recognize a dialect from -Great Britain. - -.. code-block:: python - - >>> from google.cloud import speech - >>> client = speech.SpeechClient() - >>> audio = speech.types.RecognitionAudio( - ... uri='gs://my-bucket/recording.flac') - >>> config = speech.types.RecognitionConfig( - ... encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, - ... language_code='en-US', - ... sample_rate_hertz=44100) - >>> results = client.recognize(config=config, audio=audio) - >>> for result in results: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print('transcript: ' + alternative.transcript) - ... print('confidence: ' + str(alternative.confidence)) - ==================== - transcript: Hello, this is a test - confidence: 0.81 - ==================== - transcript: Hello, this is one test - confidence: 0 - -Example of using the profanity filter. - -.. code-block:: python - - >>> from google.cloud import speech - >>> client = speech.SpeechClient() - >>> audio = speech.types.RecognitionAudio( - ... uri='gs://my-bucket/recording.flac') - >>> config = speech.types.RecognitionConfig( - ... encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, - ... language_code='en-US', - ... sample_rate_hertz=44100, - ... profanity_filter=True) - >>> results = client.recognize(config=config, audio=audio) - >>> for result in results: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print('transcript: ' + alternative.transcript) - ... print('confidence: ' + str(alternative.confidence)) - ==================== - transcript: Hello, this is a f****** test - confidence: 0.81 - -Using speech context hints to get better results. This can be used to improve -the accuracy for specific words and phrases. This can also be used to add new -words to the vocabulary of the recognizer. - -.. code-block:: python - - >>> from google.cloud import speech - >>> from google.cloud import speech - >>> client = speech.SpeechClient() - >>> audio = speech.types.RecognitionAudio( - ... uri='gs://my-bucket/recording.flac') - >>> config = speech.types.RecognitionConfig( - ... encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, - ... language_code='en-US', - ... sample_rate_hertz=44100, - ... speech_contexts=[speech.types.SpeechContext( - ... phrases=['hi', 'good afternoon'], - ... )]) - >>> results = client.recognize(config=config, audio=audio) - >>> for result in results: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print('transcript: ' + alternative.transcript) - ... print('confidence: ' + str(alternative.confidence)) - ==================== - transcript: Hello, this is a test - confidence: 0.81 - - -Streaming Recognition -~~~~~~~~~~~~~~~~~~~~~ - -The :meth:`~speech_v1.SpeechClient.streaming_recognize` method converts -speech data to possible text alternatives on the fly. - -.. note:: - Streaming recognition requests are limited to 1 minute of audio. - - See: https://cloud.google.com/speech/limits#content - -.. code-block:: python - - >>> import io - >>> from google.cloud import speech - >>> client = speech.SpeechClient() - >>> config = speech.types.RecognitionConfig( - ... encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, - ... language_code='en-US', - ... sample_rate_hertz=44100, - ... ) - >>> with io.open('./hello.wav', 'rb') as stream: - ... requests = [speech.types.StreamingRecognizeRequest( - ... audio_content=stream.read(), - ... )] - >>> results = sample.streaming_recognize( - ... config=speech.types.StreamingRecognitionConfig(config=config), - ... requests, - ... ) - >>> for result in results: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print('transcript: ' + alternative.transcript) - ... print('confidence: ' + str(alternative.confidence)) - ==================== - transcript: hello thank you for using Google Cloud platform - confidence: 0.927983105183 - - -By default the API will perform continuous recognition -(continuing to process audio even if the speaker in the audio pauses speaking) -until the client closes the output stream or until the maximum time limit has -been reached. - -If you only want to recognize a single utterance you can set -``single_utterance`` to :data:`True` and only one result will be returned. - -See: `Single Utterance`_ - -.. code-block:: python - - >>> import io - >>> from google.cloud import speech - >>> client = speech.SpeechClient() - >>> config = speech.types.RecognitionConfig( - ... encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, - ... language_code='en-US', - ... sample_rate_hertz=44100, - ... ) - >>> with io.open('./hello-pause-goodbye.wav', 'rb') as stream: - ... requests = [speech.types.StreamingRecognizeRequest( - ... audio_content=stream.read(), - ... )] - >>> results = sample.streaming_recognize( - ... config=speech.types.StreamingRecognitionConfig( - ... config=config, - ... single_utterance=False, - ... ), - ... requests, - ... ) - >>> for result in results: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print('transcript: ' + alternative.transcript) - ... print('confidence: ' + str(alternative.confidence)) - ... for result in results: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print('transcript: ' + alternative.transcript) - ... print('confidence: ' + str(alternative.confidence)) - ==================== - transcript: testing a pause - confidence: 0.933770477772 - -If ``interim_results`` is set to :data:`True`, interim results -(tentative hypotheses) may be returned as they become available. - -.. code-block:: python - - >>> import io - >>> from google.cloud import speech - >>> client = speech.SpeechClient() - >>> config = speech.types.RecognitionConfig( - ... encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16, - ... language_code='en-US', - ... sample_rate_hertz=44100, - ... ) - >>> with io.open('./hello.wav', 'rb') as stream: - ... requests = [speech.types.StreamingRecognizeRequest( - ... audio_content=stream.read(), - ... )] - >>> config = speech.types.StreamingRecognitionConfig(config=config) - >>> responses = client.streaming_recognize(config,requests) - >>> for response in responses: - ... for result in response: - ... for alternative in result.alternatives: - ... print('=' * 20) - ... print('transcript: ' + alternative.transcript) - ... print('confidence: ' + str(alternative.confidence)) - ... print('is_final:' + str(result.is_final)) - ==================== - 'he' - None - False - ==================== - 'hell' - None - False - ==================== - 'hello' - 0.973458576 - True - - -.. _Single Utterance: https://cloud.google.com/speech/reference/rpc/google.cloud.speech.v1beta1#streamingrecognitionconfig -.. _sync_recognize: https://cloud.google.com/speech/reference/rest/v1beta1/speech/syncrecognize -.. _Speech Asynchronous Recognize: https://cloud.google.com/speech/reference/rest/v1beta1/speech/asyncrecognize - - -API Reference -------------- - -.. toctree:: - :maxdepth: 2 - - gapic/v1/api - gapic/v1/types - -A new beta release, spelled ``v1p1beta1``, is provided to provide for preview -of upcoming features. In order to use this, you will want to import from -``google.cloud.speech_v1p1beta1`` in lieu of ``google.cloud.speech``. - -An API and type reference is provided the first beta also: - -.. toctree:: - :maxdepth: 2 - - gapic/v1p1beta1/api - gapic/v1p1beta1/types - -Changelog ---------- - -For a list of all ``google-cloud-speech`` releases: - -.. toctree:: - :maxdepth: 2 - - changelog diff --git a/speech/google/__init__.py b/speech/google/__init__.py deleted file mode 100644 index dd3a9f485275..000000000000 --- a/speech/google/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/speech/google/cloud/__init__.py b/speech/google/cloud/__init__.py deleted file mode 100644 index dd3a9f485275..000000000000 --- a/speech/google/cloud/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import pkg_resources - - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - - __path__ = pkgutil.extend_path(__path__, __name__) diff --git a/speech/google/cloud/speech.py b/speech/google/cloud/speech.py deleted file mode 100644 index 792e3f6719de..000000000000 --- a/speech/google/cloud/speech.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import - -from google.cloud.speech_v1 import SpeechClient -from google.cloud.speech_v1 import enums -from google.cloud.speech_v1 import types - - -__all__ = ("enums", "types", "SpeechClient") diff --git a/speech/google/cloud/speech_v1/__init__.py b/speech/google/cloud/speech_v1/__init__.py deleted file mode 100644 index 81314685022a..000000000000 --- a/speech/google/cloud/speech_v1/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.cloud.speech_v1.gapic import speech_client -from google.cloud.speech_v1.gapic import enums - -from google.cloud.speech_v1.helpers import SpeechHelpers -from google.cloud.speech_v1 import types - - -class SpeechClient(SpeechHelpers, speech_client.SpeechClient): - __doc__ = speech_client.SpeechClient.__doc__ - enums = enums - types = types - - -__all__ = ("enums", "SpeechClient", "types") diff --git a/speech/google/cloud/speech_v1/gapic/__init__.py b/speech/google/cloud/speech_v1/gapic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/speech/google/cloud/speech_v1/gapic/enums.py b/speech/google/cloud/speech_v1/gapic/enums.py deleted file mode 100644 index fa6218ab83bd..000000000000 --- a/speech/google/cloud/speech_v1/gapic/enums.py +++ /dev/null @@ -1,196 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class RecognitionConfig(object): - class AudioEncoding(enum.IntEnum): - """ - The encoding of the audio data sent in the request. - - All encodings support only 1 channel (mono) audio, unless the - ``audio_channel_count`` and ``enable_separate_recognition_per_channel`` - fields are set. - - For best results, the audio source should be captured and transmitted - using a lossless encoding (``FLAC`` or ``LINEAR16``). The accuracy of - the speech recognition can be reduced if lossy codecs are used to - capture or transmit audio, particularly if background noise is present. - Lossy codecs include ``MULAW``, ``AMR``, ``AMR_WB``, ``OGG_OPUS``, - ``SPEEX_WITH_HEADER_BYTE``, and ``MP3``. - - The ``FLAC`` and ``WAV`` audio file formats include a header that - describes the included audio content. You can request recognition for - ``WAV`` files that contain either ``LINEAR16`` or ``MULAW`` encoded - audio. If you send ``FLAC`` or ``WAV`` audio file format in your - request, you do not need to specify an ``AudioEncoding``; the audio - encoding format is determined from the file header. If you specify an - ``AudioEncoding`` when you send send ``FLAC`` or ``WAV`` audio, the - encoding configuration must match the encoding described in the audio - header; otherwise the request returns an - ``google.rpc.Code.INVALID_ARGUMENT`` error code. - - Attributes: - ENCODING_UNSPECIFIED (int): Not specified. - LINEAR16 (int): Uncompressed 16-bit signed little-endian samples (Linear PCM). - FLAC (int): ``FLAC`` (Free Lossless Audio Codec) is the recommended encoding because - it is lossless--therefore recognition is not compromised--and requires - only about half the bandwidth of ``LINEAR16``. ``FLAC`` stream encoding - supports 16-bit and 24-bit samples, however, not all fields in - ``STREAMINFO`` are supported. - MULAW (int): 8-bit samples that compand 14-bit audio samples using G.711 PCMU/mu-law. - AMR (int): Adaptive Multi-Rate Narrowband codec. ``sample_rate_hertz`` must be - 8000. - AMR_WB (int): Adaptive Multi-Rate Wideband codec. ``sample_rate_hertz`` must be 16000. - OGG_OPUS (int): Opus encoded audio frames in Ogg container - (`OggOpus `__). ``sample_rate_hertz`` - must be one of 8000, 12000, 16000, 24000, or 48000. - SPEEX_WITH_HEADER_BYTE (int): Although the use of lossy encodings is not recommended, if a very low - bitrate encoding is required, ``OGG_OPUS`` is highly preferred over - Speex encoding. The `Speex `__ encoding supported by - Cloud Speech API has a header byte in each block, as in MIME type - ``audio/x-speex-with-header-byte``. It is a variant of the RTP Speex - encoding defined in `RFC 5574 `__. - The stream is a sequence of blocks, one block per RTP packet. Each block - starts with a byte containing the length of the block, in bytes, - followed by one or more frames of Speex data, padded to an integral - number of bytes (octets) as specified in RFC 5574. In other words, each - RTP header is replaced with a single byte containing the block length. - Only Speex wideband is supported. ``sample_rate_hertz`` must be 16000. - """ - - ENCODING_UNSPECIFIED = 0 - LINEAR16 = 1 - FLAC = 2 - MULAW = 3 - AMR = 4 - AMR_WB = 5 - OGG_OPUS = 6 - SPEEX_WITH_HEADER_BYTE = 7 - - -class RecognitionMetadata(object): - class InteractionType(enum.IntEnum): - """ - Use case categories that the audio recognition request can be described - by. - - Attributes: - INTERACTION_TYPE_UNSPECIFIED (int): Use case is either unknown or is something other than one of the other - values below. - DISCUSSION (int): Multiple people in a conversation or discussion. For example in a - meeting with two or more people actively participating. Typically all - the primary people speaking would be in the same room (if not, see - PHONE\_CALL) - PRESENTATION (int): One or more persons lecturing or presenting to others, mostly - uninterrupted. - PHONE_CALL (int): A phone-call or video-conference in which two or more people, who are - not in the same room, are actively participating. - VOICEMAIL (int): A recorded message intended for another person to listen to. - PROFESSIONALLY_PRODUCED (int): Professionally produced audio (eg. TV Show, Podcast). - VOICE_SEARCH (int): Transcribe spoken questions and queries into text. - VOICE_COMMAND (int): Transcribe voice commands, such as for controlling a device. - DICTATION (int): Transcribe speech to text to create a written document, such as a - text-message, email or report. - """ - - INTERACTION_TYPE_UNSPECIFIED = 0 - DISCUSSION = 1 - PRESENTATION = 2 - PHONE_CALL = 3 - VOICEMAIL = 4 - PROFESSIONALLY_PRODUCED = 5 - VOICE_SEARCH = 6 - VOICE_COMMAND = 7 - DICTATION = 8 - - class MicrophoneDistance(enum.IntEnum): - """ - Enumerates the types of capture settings describing an audio file. - - Attributes: - MICROPHONE_DISTANCE_UNSPECIFIED (int): Audio type is not known. - NEARFIELD (int): The audio was captured from a closely placed microphone. Eg. phone, - dictaphone, or handheld microphone. Generally if there speaker is within - 1 meter of the microphone. - MIDFIELD (int): The speaker if within 3 meters of the microphone. - FARFIELD (int): The speaker is more than 3 meters away from the microphone. - """ - - MICROPHONE_DISTANCE_UNSPECIFIED = 0 - NEARFIELD = 1 - MIDFIELD = 2 - FARFIELD = 3 - - class OriginalMediaType(enum.IntEnum): - """ - The original media the speech was recorded on. - - Attributes: - ORIGINAL_MEDIA_TYPE_UNSPECIFIED (int): Unknown original media type. - AUDIO (int): The speech data is an audio recording. - VIDEO (int): The speech data originally recorded on a video. - """ - - ORIGINAL_MEDIA_TYPE_UNSPECIFIED = 0 - AUDIO = 1 - VIDEO = 2 - - class RecordingDeviceType(enum.IntEnum): - """ - The type of device the speech was recorded with. - - Attributes: - RECORDING_DEVICE_TYPE_UNSPECIFIED (int): The recording device is unknown. - SMARTPHONE (int): Speech was recorded on a smartphone. - PC (int): Speech was recorded using a personal computer or tablet. - PHONE_LINE (int): Speech was recorded over a phone line. - VEHICLE (int): Speech was recorded in a vehicle. - OTHER_OUTDOOR_DEVICE (int): Speech was recorded outdoors. - OTHER_INDOOR_DEVICE (int): Speech was recorded indoors. - """ - - RECORDING_DEVICE_TYPE_UNSPECIFIED = 0 - SMARTPHONE = 1 - PC = 2 - PHONE_LINE = 3 - VEHICLE = 4 - OTHER_OUTDOOR_DEVICE = 5 - OTHER_INDOOR_DEVICE = 6 - - -class StreamingRecognizeResponse(object): - class SpeechEventType(enum.IntEnum): - """ - Indicates the type of speech event. - - Attributes: - SPEECH_EVENT_UNSPECIFIED (int): No speech event specified. - END_OF_SINGLE_UTTERANCE (int): This event indicates that the server has detected the end of the user's - speech utterance and expects no additional speech. Therefore, the server - will not process additional audio (although it may subsequently return - additional results). The client should stop sending additional audio - data, half-close the gRPC connection, and wait for any additional - results until the server closes the gRPC connection. This event is only - sent if ``single_utterance`` was set to ``true``, and is not used - otherwise. - """ - - SPEECH_EVENT_UNSPECIFIED = 0 - END_OF_SINGLE_UTTERANCE = 1 diff --git a/speech/google/cloud/speech_v1/gapic/speech_client.py b/speech/google/cloud/speech_v1/gapic/speech_client.py deleted file mode 100644 index 83cb7f4452ce..000000000000 --- a/speech/google/cloud/speech_v1/gapic/speech_client.py +++ /dev/null @@ -1,412 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.cloud.speech.v1 Speech API.""" - -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.grpc_helpers -import google.api_core.operation -import google.api_core.operations_v1 -import google.api_core.protobuf_helpers -import grpc - -from google.cloud.speech_v1.gapic import enums -from google.cloud.speech_v1.gapic import speech_client_config -from google.cloud.speech_v1.gapic.transports import speech_grpc_transport -from google.cloud.speech_v1.proto import cloud_speech_pb2 -from google.cloud.speech_v1.proto import cloud_speech_pb2_grpc -from google.longrunning import operations_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-speech").version - - -class SpeechClient(object): - """Service that implements Google Cloud Speech API.""" - - SERVICE_ADDRESS = "speech.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.speech.v1.Speech" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - SpeechClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.SpeechGrpcTransport, - Callable[[~.Credentials, type], ~.SpeechGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = speech_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=speech_grpc_transport.SpeechGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = speech_grpc_transport.SpeechGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def recognize( - self, - config, - audio, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Performs synchronous speech recognition: receive results after all audio - has been sent and processed. - - Example: - >>> from google.cloud import speech_v1 - >>> from google.cloud.speech_v1 import enums - >>> - >>> client = speech_v1.SpeechClient() - >>> - >>> encoding = enums.RecognitionConfig.AudioEncoding.FLAC - >>> sample_rate_hertz = 44100 - >>> language_code = 'en-US' - >>> config = {'encoding': encoding, 'sample_rate_hertz': sample_rate_hertz, 'language_code': language_code} - >>> uri = 'gs://bucket_name/file_name.flac' - >>> audio = {'uri': uri} - >>> - >>> response = client.recognize(config, audio) - - Args: - config (Union[dict, ~google.cloud.speech_v1.types.RecognitionConfig]): Required. Provides information to the recognizer that specifies how to - process the request. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1.types.RecognitionConfig` - audio (Union[dict, ~google.cloud.speech_v1.types.RecognitionAudio]): Required. The audio data to be recognized. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1.types.RecognitionAudio` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.speech_v1.types.RecognizeResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "recognize" not in self._inner_api_calls: - self._inner_api_calls[ - "recognize" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.recognize, - default_retry=self._method_configs["Recognize"].retry, - default_timeout=self._method_configs["Recognize"].timeout, - client_info=self._client_info, - ) - - request = cloud_speech_pb2.RecognizeRequest(config=config, audio=audio) - return self._inner_api_calls["recognize"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def long_running_recognize( - self, - config, - audio, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Performs asynchronous speech recognition: receive results via the - google.longrunning.Operations interface. Returns either an - ``Operation.error`` or an ``Operation.response`` which contains a - ``LongRunningRecognizeResponse`` message. For more information on - asynchronous speech recognition, see the - `how-to `__. - - Example: - >>> from google.cloud import speech_v1 - >>> from google.cloud.speech_v1 import enums - >>> - >>> client = speech_v1.SpeechClient() - >>> - >>> encoding = enums.RecognitionConfig.AudioEncoding.FLAC - >>> sample_rate_hertz = 44100 - >>> language_code = 'en-US' - >>> config = {'encoding': encoding, 'sample_rate_hertz': sample_rate_hertz, 'language_code': language_code} - >>> uri = 'gs://bucket_name/file_name.flac' - >>> audio = {'uri': uri} - >>> - >>> response = client.long_running_recognize(config, audio) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - config (Union[dict, ~google.cloud.speech_v1.types.RecognitionConfig]): Required. Provides information to the recognizer that specifies how to - process the request. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1.types.RecognitionConfig` - audio (Union[dict, ~google.cloud.speech_v1.types.RecognitionAudio]): Required. The audio data to be recognized. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1.types.RecognitionAudio` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.speech_v1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "long_running_recognize" not in self._inner_api_calls: - self._inner_api_calls[ - "long_running_recognize" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.long_running_recognize, - default_retry=self._method_configs["LongRunningRecognize"].retry, - default_timeout=self._method_configs["LongRunningRecognize"].timeout, - client_info=self._client_info, - ) - - request = cloud_speech_pb2.LongRunningRecognizeRequest( - config=config, audio=audio - ) - operation = self._inner_api_calls["long_running_recognize"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_speech_pb2.LongRunningRecognizeResponse, - metadata_type=cloud_speech_pb2.LongRunningRecognizeMetadata, - ) - - def streaming_recognize( - self, - requests, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Performs bidirectional streaming speech recognition: receive results while - sending audio. This method is only available via the gRPC API (not REST). - - EXPERIMENTAL: This method interface might change in the future. - - Example: - >>> from google.cloud import speech_v1 - >>> - >>> client = speech_v1.SpeechClient() - >>> - >>> request = {} - >>> - >>> requests = [request] - >>> for element in client.streaming_recognize(requests): - ... # process element - ... pass - - Args: - requests (iterator[dict|google.cloud.speech_v1.proto.cloud_speech_pb2.StreamingRecognizeRequest]): The input objects. If a dict is provided, it must be of the - same form as the protobuf message :class:`~google.cloud.speech_v1.types.StreamingRecognizeRequest` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - Iterable[~google.cloud.speech_v1.types.StreamingRecognizeResponse]. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "streaming_recognize" not in self._inner_api_calls: - self._inner_api_calls[ - "streaming_recognize" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.streaming_recognize, - default_retry=self._method_configs["StreamingRecognize"].retry, - default_timeout=self._method_configs["StreamingRecognize"].timeout, - client_info=self._client_info, - ) - - return self._inner_api_calls["streaming_recognize"]( - requests, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/speech/google/cloud/speech_v1/gapic/speech_client_config.py b/speech/google/cloud/speech_v1/gapic/speech_client_config.py deleted file mode 100644 index 555d3f2a7005..000000000000 --- a/speech/google/cloud/speech_v1/gapic/speech_client_config.py +++ /dev/null @@ -1,38 +0,0 @@ -config = { - "interfaces": { - "google.cloud.speech.v1.Speech": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 1000000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 1000000, - "total_timeout_millis": 5000000, - } - }, - "methods": { - "Recognize": { - "timeout_millis": 60000, - "retry_codes_name": "idempotent", - "retry_params_name": "default", - }, - "LongRunningRecognize": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "StreamingRecognize": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/speech/google/cloud/speech_v1/gapic/transports/__init__.py b/speech/google/cloud/speech_v1/gapic/transports/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/speech/google/cloud/speech_v1/gapic/transports/speech_grpc_transport.py b/speech/google/cloud/speech_v1/gapic/transports/speech_grpc_transport.py deleted file mode 100644 index c0d9c39d2d0c..000000000000 --- a/speech/google/cloud/speech_v1/gapic/transports/speech_grpc_transport.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers -import google.api_core.operations_v1 - -from google.cloud.speech_v1.proto import cloud_speech_pb2_grpc - - -class SpeechGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.speech.v1 Speech API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, channel=None, credentials=None, address="speech.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = {"speech_stub": cloud_speech_pb2_grpc.SpeechStub(channel)} - - # Because this API includes a method that returns a - # long-running operation (proto: google.longrunning.Operation), - # instantiate an LRO client. - self._operations_client = google.api_core.operations_v1.OperationsClient( - channel - ) - - @classmethod - def create_channel( - cls, address="speech.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def recognize(self): - """Return the gRPC stub for :meth:`SpeechClient.recognize`. - - Performs synchronous speech recognition: receive results after all audio - has been sent and processed. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["speech_stub"].Recognize - - @property - def long_running_recognize(self): - """Return the gRPC stub for :meth:`SpeechClient.long_running_recognize`. - - Performs asynchronous speech recognition: receive results via the - google.longrunning.Operations interface. Returns either an - ``Operation.error`` or an ``Operation.response`` which contains a - ``LongRunningRecognizeResponse`` message. For more information on - asynchronous speech recognition, see the - `how-to `__. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["speech_stub"].LongRunningRecognize - - @property - def streaming_recognize(self): - """Return the gRPC stub for :meth:`SpeechClient.streaming_recognize`. - - Performs bidirectional streaming speech recognition: receive results while - sending audio. This method is only available via the gRPC API (not REST). - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["speech_stub"].StreamingRecognize diff --git a/speech/google/cloud/speech_v1/helpers.py b/speech/google/cloud/speech_v1/helpers.py deleted file mode 100644 index 26f17dbe52d3..000000000000 --- a/speech/google/cloud/speech_v1/helpers.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2017, Google LLC All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -import google.api_core.gapic_v1.method - - -class SpeechHelpers(object): - """A set of convenience methods to make the Speech client easier to use. - - This class should be considered abstract; it is used as a superclass - in a multiple-inheritance construction alongside the applicable GAPIC. - See the :class:`~google.cloud.speech_v1.SpeechClient`. - """ - - def streaming_recognize( - self, - config, - requests, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - ): - """Perform bi-directional speech recognition. - - This method allows you to receive results while sending audio; - it is only available via. gRPC (not REST). - - .. warning:: - - This method is EXPERIMENTAL. Its interface might change in the - future. - - Example: - >>> from google.cloud.speech_v1 import enums - >>> from google.cloud.speech_v1 import SpeechClient - >>> from google.cloud.speech_v1 import types - >>> client = SpeechClient() - >>> config = types.StreamingRecognitionConfig( - ... config=types.RecognitionConfig( - ... encoding=enums.RecognitionConfig.AudioEncoding.FLAC, - ... ), - ... ) - >>> request = types.StreamingRecognizeRequest(audio_content=b'...') - >>> requests = [request] - >>> for element in client.streaming_recognize(config, requests): - ... # process element - ... pass - - Args: - config (:class:`~.types.StreamingRecognitionConfig`): The - configuration to use for the stream. - requests (Iterable[:class:`~.types.StreamingRecognizeRequest`]): - The input objects. - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will not - be retried. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - - Returns: - Iterable[:class:`~.types.StreamingRecognizeResponse`] - - Raises: - :exc:`google.gax.errors.GaxError` if the RPC is aborted. - :exc:`ValueError` if the parameters are invalid. - """ - return super(SpeechHelpers, self).streaming_recognize( - self._streaming_request_iterable(config, requests), - retry=retry, - timeout=timeout, - ) - - def _streaming_request_iterable(self, config, requests): - """A generator that yields the config followed by the requests. - - Args: - config (~.speech_v1.types.StreamingRecognitionConfig): The - configuration to use for the stream. - requests (Iterable[~.speech_v1.types.StreamingRecognizeRequest]): - The input objects. - - Returns: - Iterable[~.speech_v1.types.StreamingRecognizeRequest]): The - correctly formatted input for - :meth:`~.speech_v1.SpeechClient.streaming_recognize`. - """ - yield self.types.StreamingRecognizeRequest(streaming_config=config) - for request in requests: - yield request diff --git a/speech/google/cloud/speech_v1/proto/__init__.py b/speech/google/cloud/speech_v1/proto/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/speech/google/cloud/speech_v1/proto/cloud_speech.proto b/speech/google/cloud/speech_v1/proto/cloud_speech.proto deleted file mode 100644 index f343fa21da85..000000000000 --- a/speech/google/cloud/speech_v1/proto/cloud_speech.proto +++ /dev/null @@ -1,759 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.cloud.speech.v1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/longrunning/operations.proto"; -import "google/protobuf/any.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/timestamp.proto"; -import "google/rpc/status.proto"; - -option cc_enable_arenas = true; -option go_package = "google.golang.org/genproto/googleapis/cloud/speech/v1;speech"; -option java_multiple_files = true; -option java_outer_classname = "SpeechProto"; -option java_package = "com.google.cloud.speech.v1"; -option objc_class_prefix = "GCS"; - -// Service that implements Google Cloud Speech API. -service Speech { - option (google.api.default_host) = "speech.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Performs synchronous speech recognition: receive results after all audio - // has been sent and processed. - rpc Recognize(RecognizeRequest) returns (RecognizeResponse) { - option (google.api.http) = { - post: "/v1/speech:recognize" - body: "*" - }; - option (google.api.method_signature) = "config,audio"; - } - - // Performs asynchronous speech recognition: receive results via the - // google.longrunning.Operations interface. Returns either an - // `Operation.error` or an `Operation.response` which contains - // a `LongRunningRecognizeResponse` message. - // For more information on asynchronous speech recognition, see the - // [how-to](https://cloud.google.com/speech-to-text/docs/async-recognize). - rpc LongRunningRecognize(LongRunningRecognizeRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1/speech:longrunningrecognize" - body: "*" - }; - option (google.api.method_signature) = "config,audio"; - option (google.longrunning.operation_info) = { - response_type: "LongRunningRecognizeResponse" - metadata_type: "LongRunningRecognizeMetadata" - }; - } - - // Performs bidirectional streaming speech recognition: receive results while - // sending audio. This method is only available via the gRPC API (not REST). - rpc StreamingRecognize(stream StreamingRecognizeRequest) returns (stream StreamingRecognizeResponse) { - } -} - -// The top-level message sent by the client for the `Recognize` method. -message RecognizeRequest { - // Required. Provides information to the recognizer that specifies how to - // process the request. - RecognitionConfig config = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The audio data to be recognized. - RecognitionAudio audio = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// The top-level message sent by the client for the `LongRunningRecognize` -// method. -message LongRunningRecognizeRequest { - // Required. Provides information to the recognizer that specifies how to - // process the request. - RecognitionConfig config = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The audio data to be recognized. - RecognitionAudio audio = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// The top-level message sent by the client for the `StreamingRecognize` method. -// Multiple `StreamingRecognizeRequest` messages are sent. The first message -// must contain a `streaming_config` message and must not contain -// `audio_content`. All subsequent messages must contain `audio_content` and -// must not contain a `streaming_config` message. -message StreamingRecognizeRequest { - // The streaming request, which is either a streaming config or audio content. - oneof streaming_request { - // Provides information to the recognizer that specifies how to process the - // request. The first `StreamingRecognizeRequest` message must contain a - // `streaming_config` message. - StreamingRecognitionConfig streaming_config = 1; - - // The audio data to be recognized. Sequential chunks of audio data are sent - // in sequential `StreamingRecognizeRequest` messages. The first - // `StreamingRecognizeRequest` message must not contain `audio_content` data - // and all subsequent `StreamingRecognizeRequest` messages must contain - // `audio_content` data. The audio bytes must be encoded as specified in - // `RecognitionConfig`. Note: as with all bytes fields, proto buffers use a - // pure binary representation (not base64). See - // [content limits](https://cloud.google.com/speech-to-text/quotas#content). - bytes audio_content = 2; - } -} - -// Provides information to the recognizer that specifies how to process the -// request. -message StreamingRecognitionConfig { - // Required. Provides information to the recognizer that specifies how to - // process the request. - RecognitionConfig config = 1 [(google.api.field_behavior) = REQUIRED]; - - // If `false` or omitted, the recognizer will perform continuous - // recognition (continuing to wait for and process audio even if the user - // pauses speaking) until the client closes the input stream (gRPC API) or - // until the maximum time limit has been reached. May return multiple - // `StreamingRecognitionResult`s with the `is_final` flag set to `true`. - // - // If `true`, the recognizer will detect a single spoken utterance. When it - // detects that the user has paused or stopped speaking, it will return an - // `END_OF_SINGLE_UTTERANCE` event and cease recognition. It will return no - // more than one `StreamingRecognitionResult` with the `is_final` flag set to - // `true`. - bool single_utterance = 2; - - // If `true`, interim results (tentative hypotheses) may be - // returned as they become available (these interim results are indicated with - // the `is_final=false` flag). - // If `false` or omitted, only `is_final=true` result(s) are returned. - bool interim_results = 3; -} - -// Provides information to the recognizer that specifies how to process the -// request. -message RecognitionConfig { - // The encoding of the audio data sent in the request. - // - // All encodings support only 1 channel (mono) audio, unless the - // `audio_channel_count` and `enable_separate_recognition_per_channel` fields - // are set. - // - // For best results, the audio source should be captured and transmitted using - // a lossless encoding (`FLAC` or `LINEAR16`). The accuracy of the speech - // recognition can be reduced if lossy codecs are used to capture or transmit - // audio, particularly if background noise is present. Lossy codecs include - // `MULAW`, `AMR`, `AMR_WB`, `OGG_OPUS`, `SPEEX_WITH_HEADER_BYTE`, and `MP3`. - // - // The `FLAC` and `WAV` audio file formats include a header that describes the - // included audio content. You can request recognition for `WAV` files that - // contain either `LINEAR16` or `MULAW` encoded audio. - // If you send `FLAC` or `WAV` audio file format in - // your request, you do not need to specify an `AudioEncoding`; the audio - // encoding format is determined from the file header. If you specify - // an `AudioEncoding` when you send send `FLAC` or `WAV` audio, the - // encoding configuration must match the encoding described in the audio - // header; otherwise the request returns an - // [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT] error code. - enum AudioEncoding { - // Not specified. - ENCODING_UNSPECIFIED = 0; - - // Uncompressed 16-bit signed little-endian samples (Linear PCM). - LINEAR16 = 1; - - // `FLAC` (Free Lossless Audio - // Codec) is the recommended encoding because it is - // lossless--therefore recognition is not compromised--and - // requires only about half the bandwidth of `LINEAR16`. `FLAC` stream - // encoding supports 16-bit and 24-bit samples, however, not all fields in - // `STREAMINFO` are supported. - FLAC = 2; - - // 8-bit samples that compand 14-bit audio samples using G.711 PCMU/mu-law. - MULAW = 3; - - // Adaptive Multi-Rate Narrowband codec. `sample_rate_hertz` must be 8000. - AMR = 4; - - // Adaptive Multi-Rate Wideband codec. `sample_rate_hertz` must be 16000. - AMR_WB = 5; - - // Opus encoded audio frames in Ogg container - // ([OggOpus](https://wiki.xiph.org/OggOpus)). - // `sample_rate_hertz` must be one of 8000, 12000, 16000, 24000, or 48000. - OGG_OPUS = 6; - - // Although the use of lossy encodings is not recommended, if a very low - // bitrate encoding is required, `OGG_OPUS` is highly preferred over - // Speex encoding. The [Speex](https://speex.org/) encoding supported by - // Cloud Speech API has a header byte in each block, as in MIME type - // `audio/x-speex-with-header-byte`. - // It is a variant of the RTP Speex encoding defined in - // [RFC 5574](https://tools.ietf.org/html/rfc5574). - // The stream is a sequence of blocks, one block per RTP packet. Each block - // starts with a byte containing the length of the block, in bytes, followed - // by one or more frames of Speex data, padded to an integral number of - // bytes (octets) as specified in RFC 5574. In other words, each RTP header - // is replaced with a single byte containing the block length. Only Speex - // wideband is supported. `sample_rate_hertz` must be 16000. - SPEEX_WITH_HEADER_BYTE = 7; - } - - // Encoding of audio data sent in all `RecognitionAudio` messages. - // This field is optional for `FLAC` and `WAV` audio files and required - // for all other audio formats. For details, see [AudioEncoding][google.cloud.speech.v1.RecognitionConfig.AudioEncoding]. - AudioEncoding encoding = 1; - - // Sample rate in Hertz of the audio data sent in all - // `RecognitionAudio` messages. Valid values are: 8000-48000. - // 16000 is optimal. For best results, set the sampling rate of the audio - // source to 16000 Hz. If that's not possible, use the native sample rate of - // the audio source (instead of re-sampling). - // This field is optional for FLAC and WAV audio files, but is - // required for all other audio formats. For details, see [AudioEncoding][google.cloud.speech.v1.RecognitionConfig.AudioEncoding]. - int32 sample_rate_hertz = 2; - - // The number of channels in the input audio data. - // ONLY set this for MULTI-CHANNEL recognition. - // Valid values for LINEAR16 and FLAC are `1`-`8`. - // Valid values for OGG_OPUS are '1'-'254'. - // Valid value for MULAW, AMR, AMR_WB and SPEEX_WITH_HEADER_BYTE is only `1`. - // If `0` or omitted, defaults to one channel (mono). - // Note: We only recognize the first channel by default. - // To perform independent recognition on each channel set - // `enable_separate_recognition_per_channel` to 'true'. - int32 audio_channel_count = 7; - - // This needs to be set to `true` explicitly and `audio_channel_count` > 1 - // to get each channel recognized separately. The recognition result will - // contain a `channel_tag` field to state which channel that result belongs - // to. If this is not true, we will only recognize the first channel. The - // request is billed cumulatively for all channels recognized: - // `audio_channel_count` multiplied by the length of the audio. - bool enable_separate_recognition_per_channel = 12; - - // Required. The language of the supplied audio as a - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag. - // Example: "en-US". - // See [Language - // Support](https://cloud.google.com/speech-to-text/docs/languages) for a list - // of the currently supported language codes. - string language_code = 3 [(google.api.field_behavior) = REQUIRED]; - - // Maximum number of recognition hypotheses to be returned. - // Specifically, the maximum number of `SpeechRecognitionAlternative` messages - // within each `SpeechRecognitionResult`. - // The server may return fewer than `max_alternatives`. - // Valid values are `0`-`30`. A value of `0` or `1` will return a maximum of - // one. If omitted, will return a maximum of one. - int32 max_alternatives = 4; - - // If set to `true`, the server will attempt to filter out - // profanities, replacing all but the initial character in each filtered word - // with asterisks, e.g. "f***". If set to `false` or omitted, profanities - // won't be filtered out. - bool profanity_filter = 5; - - // Array of [SpeechContext][google.cloud.speech.v1.SpeechContext]. - // A means to provide context to assist the speech recognition. For more - // information, see - // [speech - // adaptation](https://cloud.google.com/speech-to-text/docs/context-strength). - repeated SpeechContext speech_contexts = 6; - - // If `true`, the top result includes a list of words and - // the start and end time offsets (timestamps) for those words. If - // `false`, no word-level time offset information is returned. The default is - // `false`. - bool enable_word_time_offsets = 8; - - // If 'true', adds punctuation to recognition result hypotheses. - // This feature is only available in select languages. Setting this for - // requests in other languages has no effect at all. - // The default 'false' value does not add punctuation to result hypotheses. - // Note: This is currently offered as an experimental service, complimentary - // to all users. In the future this may be exclusively available as a - // premium feature. - bool enable_automatic_punctuation = 11; - - // Config to enable speaker diarization and set additional - // parameters to make diarization better suited for your application. - // Note: When this is enabled, we send all the words from the beginning of the - // audio for the top alternative in every consecutive STREAMING responses. - // This is done in order to improve our speaker tags as our models learn to - // identify the speakers in the conversation over time. - // For non-streaming requests, the diarization results will be provided only - // in the top alternative of the FINAL SpeechRecognitionResult. - SpeakerDiarizationConfig diarization_config = 19; - - // Metadata regarding this request. - RecognitionMetadata metadata = 9; - - // Which model to select for the given request. Select the model - // best suited to your domain to get best results. If a model is not - // explicitly specified, then we auto-select a model based on the parameters - // in the RecognitionConfig. - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - //
ModelDescription
command_and_searchBest for short queries such as voice commands or voice search.
phone_callBest for audio that originated from a phone call (typically - // recorded at an 8khz sampling rate).
videoBest for audio that originated from from video or includes multiple - // speakers. Ideally the audio is recorded at a 16khz or greater - // sampling rate. This is a premium model that costs more than the - // standard rate.
defaultBest for audio that is not one of the specific audio models. - // For example, long-form audio. Ideally the audio is high-fidelity, - // recorded at a 16khz or greater sampling rate.
- string model = 13; - - // Set to true to use an enhanced model for speech recognition. - // If `use_enhanced` is set to true and the `model` field is not set, then - // an appropriate enhanced model is chosen if an enhanced model exists for - // the audio. - // - // If `use_enhanced` is true and an enhanced version of the specified model - // does not exist, then the speech is recognized using the standard version - // of the specified model. - bool use_enhanced = 14; -} - -// Config to enable speaker diarization. -message SpeakerDiarizationConfig { - // If 'true', enables speaker detection for each recognized word in - // the top alternative of the recognition result using a speaker_tag provided - // in the WordInfo. - bool enable_speaker_diarization = 1; - - // Minimum number of speakers in the conversation. This range gives you more - // flexibility by allowing the system to automatically determine the correct - // number of speakers. If not set, the default value is 2. - int32 min_speaker_count = 2; - - // Maximum number of speakers in the conversation. This range gives you more - // flexibility by allowing the system to automatically determine the correct - // number of speakers. If not set, the default value is 6. - int32 max_speaker_count = 3; - - // Unused. - int32 speaker_tag = 5 - [(google.api.field_behavior) = OUTPUT_ONLY, deprecated = true]; -} - -// Description of audio data to be recognized. -message RecognitionMetadata { - // Use case categories that the audio recognition request can be described - // by. - enum InteractionType { - // Use case is either unknown or is something other than one of the other - // values below. - INTERACTION_TYPE_UNSPECIFIED = 0; - - // Multiple people in a conversation or discussion. For example in a - // meeting with two or more people actively participating. Typically - // all the primary people speaking would be in the same room (if not, - // see PHONE_CALL) - DISCUSSION = 1; - - // One or more persons lecturing or presenting to others, mostly - // uninterrupted. - PRESENTATION = 2; - - // A phone-call or video-conference in which two or more people, who are - // not in the same room, are actively participating. - PHONE_CALL = 3; - - // A recorded message intended for another person to listen to. - VOICEMAIL = 4; - - // Professionally produced audio (eg. TV Show, Podcast). - PROFESSIONALLY_PRODUCED = 5; - - // Transcribe spoken questions and queries into text. - VOICE_SEARCH = 6; - - // Transcribe voice commands, such as for controlling a device. - VOICE_COMMAND = 7; - - // Transcribe speech to text to create a written document, such as a - // text-message, email or report. - DICTATION = 8; - } - - // Enumerates the types of capture settings describing an audio file. - enum MicrophoneDistance { - // Audio type is not known. - MICROPHONE_DISTANCE_UNSPECIFIED = 0; - - // The audio was captured from a closely placed microphone. Eg. phone, - // dictaphone, or handheld microphone. Generally if there speaker is within - // 1 meter of the microphone. - NEARFIELD = 1; - - // The speaker if within 3 meters of the microphone. - MIDFIELD = 2; - - // The speaker is more than 3 meters away from the microphone. - FARFIELD = 3; - } - - // The original media the speech was recorded on. - enum OriginalMediaType { - // Unknown original media type. - ORIGINAL_MEDIA_TYPE_UNSPECIFIED = 0; - - // The speech data is an audio recording. - AUDIO = 1; - - // The speech data originally recorded on a video. - VIDEO = 2; - } - - // The type of device the speech was recorded with. - enum RecordingDeviceType { - // The recording device is unknown. - RECORDING_DEVICE_TYPE_UNSPECIFIED = 0; - - // Speech was recorded on a smartphone. - SMARTPHONE = 1; - - // Speech was recorded using a personal computer or tablet. - PC = 2; - - // Speech was recorded over a phone line. - PHONE_LINE = 3; - - // Speech was recorded in a vehicle. - VEHICLE = 4; - - // Speech was recorded outdoors. - OTHER_OUTDOOR_DEVICE = 5; - - // Speech was recorded indoors. - OTHER_INDOOR_DEVICE = 6; - } - - // The use case most closely describing the audio content to be recognized. - InteractionType interaction_type = 1; - - // The industry vertical to which this speech recognition request most - // closely applies. This is most indicative of the topics contained - // in the audio. Use the 6-digit NAICS code to identify the industry - // vertical - see https://www.naics.com/search/. - uint32 industry_naics_code_of_audio = 3; - - // The audio type that most closely describes the audio being recognized. - MicrophoneDistance microphone_distance = 4; - - // The original media the speech was recorded on. - OriginalMediaType original_media_type = 5; - - // The type of device the speech was recorded with. - RecordingDeviceType recording_device_type = 6; - - // The device used to make the recording. Examples 'Nexus 5X' or - // 'Polycom SoundStation IP 6000' or 'POTS' or 'VoIP' or - // 'Cardioid Microphone'. - string recording_device_name = 7; - - // Mime type of the original audio file. For example `audio/m4a`, - // `audio/x-alaw-basic`, `audio/mp3`, `audio/3gpp`. - // A list of possible audio mime types is maintained at - // http://www.iana.org/assignments/media-types/media-types.xhtml#audio - string original_mime_type = 8; - - // Description of the content. Eg. "Recordings of federal supreme court - // hearings from 2012". - string audio_topic = 10; -} - -// Provides "hints" to the speech recognizer to favor specific words and phrases -// in the results. -message SpeechContext { - // A list of strings containing words and phrases "hints" so that - // the speech recognition is more likely to recognize them. This can be used - // to improve the accuracy for specific words and phrases, for example, if - // specific commands are typically spoken by the user. This can also be used - // to add additional words to the vocabulary of the recognizer. See - // [usage limits](https://cloud.google.com/speech-to-text/quotas#content). - // - // List items can also be set to classes for groups of words that represent - // common concepts that occur in natural language. For example, rather than - // providing phrase hints for every month of the year, using the $MONTH class - // improves the likelihood of correctly transcribing audio that includes - // months. - repeated string phrases = 1; -} - -// Contains audio data in the encoding specified in the `RecognitionConfig`. -// Either `content` or `uri` must be supplied. Supplying both or neither -// returns [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]. See -// [content limits](https://cloud.google.com/speech-to-text/quotas#content). -message RecognitionAudio { - // The audio source, which is either inline content or a Google Cloud - // Storage uri. - oneof audio_source { - // The audio data bytes encoded as specified in - // `RecognitionConfig`. Note: as with all bytes fields, proto buffers use a - // pure binary representation, whereas JSON representations use base64. - bytes content = 1; - - // URI that points to a file that contains audio data bytes as specified in - // `RecognitionConfig`. The file must not be compressed (for example, gzip). - // Currently, only Google Cloud Storage URIs are - // supported, which must be specified in the following format: - // `gs://bucket_name/object_name` (other URI formats return - // [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]). For more information, see - // [Request URIs](https://cloud.google.com/storage/docs/reference-uris). - string uri = 2; - } -} - -// The only message returned to the client by the `Recognize` method. It -// contains the result as zero or more sequential `SpeechRecognitionResult` -// messages. -message RecognizeResponse { - // Sequential list of transcription results corresponding to - // sequential portions of audio. - repeated SpeechRecognitionResult results = 2; -} - -// The only message returned to the client by the `LongRunningRecognize` method. -// It contains the result as zero or more sequential `SpeechRecognitionResult` -// messages. It is included in the `result.response` field of the `Operation` -// returned by the `GetOperation` call of the `google::longrunning::Operations` -// service. -message LongRunningRecognizeResponse { - // Sequential list of transcription results corresponding to - // sequential portions of audio. - repeated SpeechRecognitionResult results = 2; -} - -// Describes the progress of a long-running `LongRunningRecognize` call. It is -// included in the `metadata` field of the `Operation` returned by the -// `GetOperation` call of the `google::longrunning::Operations` service. -message LongRunningRecognizeMetadata { - // Approximate percentage of audio processed thus far. Guaranteed to be 100 - // when the audio is fully processed and the results are available. - int32 progress_percent = 1; - - // Time when the request was received. - google.protobuf.Timestamp start_time = 2; - - // Time of the most recent processing update. - google.protobuf.Timestamp last_update_time = 3; -} - -// `StreamingRecognizeResponse` is the only message returned to the client by -// `StreamingRecognize`. A series of zero or more `StreamingRecognizeResponse` -// messages are streamed back to the client. If there is no recognizable -// audio, and `single_utterance` is set to false, then no messages are streamed -// back to the client. -// -// Here's an example of a series of ten `StreamingRecognizeResponse`s that might -// be returned while processing audio: -// -// 1. results { alternatives { transcript: "tube" } stability: 0.01 } -// -// 2. results { alternatives { transcript: "to be a" } stability: 0.01 } -// -// 3. results { alternatives { transcript: "to be" } stability: 0.9 } -// results { alternatives { transcript: " or not to be" } stability: 0.01 } -// -// 4. results { alternatives { transcript: "to be or not to be" -// confidence: 0.92 } -// alternatives { transcript: "to bee or not to bee" } -// is_final: true } -// -// 5. results { alternatives { transcript: " that's" } stability: 0.01 } -// -// 6. results { alternatives { transcript: " that is" } stability: 0.9 } -// results { alternatives { transcript: " the question" } stability: 0.01 } -// -// 7. results { alternatives { transcript: " that is the question" -// confidence: 0.98 } -// alternatives { transcript: " that was the question" } -// is_final: true } -// -// Notes: -// -// - Only two of the above responses #4 and #7 contain final results; they are -// indicated by `is_final: true`. Concatenating these together generates the -// full transcript: "to be or not to be that is the question". -// -// - The others contain interim `results`. #3 and #6 contain two interim -// `results`: the first portion has a high stability and is less likely to -// change; the second portion has a low stability and is very likely to -// change. A UI designer might choose to show only high stability `results`. -// -// - The specific `stability` and `confidence` values shown above are only for -// illustrative purposes. Actual values may vary. -// -// - In each response, only one of these fields will be set: -// `error`, -// `speech_event_type`, or -// one or more (repeated) `results`. -message StreamingRecognizeResponse { - // Indicates the type of speech event. - enum SpeechEventType { - // No speech event specified. - SPEECH_EVENT_UNSPECIFIED = 0; - - // This event indicates that the server has detected the end of the user's - // speech utterance and expects no additional speech. Therefore, the server - // will not process additional audio (although it may subsequently return - // additional results). The client should stop sending additional audio - // data, half-close the gRPC connection, and wait for any additional results - // until the server closes the gRPC connection. This event is only sent if - // `single_utterance` was set to `true`, and is not used otherwise. - END_OF_SINGLE_UTTERANCE = 1; - } - - // If set, returns a [google.rpc.Status][google.rpc.Status] message that - // specifies the error for the operation. - google.rpc.Status error = 1; - - // This repeated list contains zero or more results that - // correspond to consecutive portions of the audio currently being processed. - // It contains zero or one `is_final=true` result (the newly settled portion), - // followed by zero or more `is_final=false` results (the interim results). - repeated StreamingRecognitionResult results = 2; - - // Indicates the type of speech event. - SpeechEventType speech_event_type = 4; -} - -// A streaming speech recognition result corresponding to a portion of the audio -// that is currently being processed. -message StreamingRecognitionResult { - // May contain one or more recognition hypotheses (up to the - // maximum specified in `max_alternatives`). - // These alternatives are ordered in terms of accuracy, with the top (first) - // alternative being the most probable, as ranked by the recognizer. - repeated SpeechRecognitionAlternative alternatives = 1; - - // If `false`, this `StreamingRecognitionResult` represents an - // interim result that may change. If `true`, this is the final time the - // speech service will return this particular `StreamingRecognitionResult`, - // the recognizer will not return any further hypotheses for this portion of - // the transcript and corresponding audio. - bool is_final = 2; - - // An estimate of the likelihood that the recognizer will not - // change its guess about this interim result. Values range from 0.0 - // (completely unstable) to 1.0 (completely stable). - // This field is only provided for interim results (`is_final=false`). - // The default of 0.0 is a sentinel value indicating `stability` was not set. - float stability = 3; - - // Time offset of the end of this result relative to the - // beginning of the audio. - google.protobuf.Duration result_end_time = 4; - - // For multi-channel audio, this is the channel number corresponding to the - // recognized result for the audio from that channel. - // For audio_channel_count = N, its output values can range from '1' to 'N'. - int32 channel_tag = 5; - - // The [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag of - // the language in this result. This language code was detected to have the - // most likelihood of being spoken in the audio. - string language_code = 6 - [(google.api.field_behavior) = OUTPUT_ONLY]; -} - -// A speech recognition result corresponding to a portion of the audio. -message SpeechRecognitionResult { - // May contain one or more recognition hypotheses (up to the - // maximum specified in `max_alternatives`). - // These alternatives are ordered in terms of accuracy, with the top (first) - // alternative being the most probable, as ranked by the recognizer. - repeated SpeechRecognitionAlternative alternatives = 1; - - // For multi-channel audio, this is the channel number corresponding to the - // recognized result for the audio from that channel. - // For audio_channel_count = N, its output values can range from '1' to 'N'. - int32 channel_tag = 2; -} - -// Alternative hypotheses (a.k.a. n-best list). -message SpeechRecognitionAlternative { - // Transcript text representing the words that the user spoke. - string transcript = 1; - - // The confidence estimate between 0.0 and 1.0. A higher number - // indicates an estimated greater likelihood that the recognized words are - // correct. This field is set only for the top alternative of a non-streaming - // result or, of a streaming result where `is_final=true`. - // This field is not guaranteed to be accurate and users should not rely on it - // to be always provided. - // The default of 0.0 is a sentinel value indicating `confidence` was not set. - float confidence = 2; - - // A list of word-specific information for each recognized word. - // Note: When `enable_speaker_diarization` is true, you will see all the words - // from the beginning of the audio. - repeated WordInfo words = 3; -} - -// Word-specific information for recognized words. -message WordInfo { - // Time offset relative to the beginning of the audio, - // and corresponding to the start of the spoken word. - // This field is only set if `enable_word_time_offsets=true` and only - // in the top hypothesis. - // This is an experimental feature and the accuracy of the time offset can - // vary. - google.protobuf.Duration start_time = 1; - - // Time offset relative to the beginning of the audio, - // and corresponding to the end of the spoken word. - // This field is only set if `enable_word_time_offsets=true` and only - // in the top hypothesis. - // This is an experimental feature and the accuracy of the time offset can - // vary. - google.protobuf.Duration end_time = 2; - - // The word corresponding to this set of information. - string word = 3; - - // A distinct integer value is assigned for every speaker within - // the audio. This field specifies which one of those speakers was detected to - // have spoken this word. Value ranges from '1' to diarization_speaker_count. - // speaker_tag is set if enable_speaker_diarization = 'true' and only in the - // top alternative. - int32 speaker_tag = 5 - [(google.api.field_behavior) = OUTPUT_ONLY]; -} diff --git a/speech/google/cloud/speech_v1/proto/cloud_speech_pb2.py b/speech/google/cloud/speech_v1/proto/cloud_speech_pb2.py deleted file mode 100644 index d73b7c0ed160..000000000000 --- a/speech/google/cloud/speech_v1/proto/cloud_speech_pb2.py +++ /dev/null @@ -1,2640 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/speech_v1/proto/cloud_speech.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) -from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 -from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 -from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from google.rpc import status_pb2 as google_dot_rpc_dot_status__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/speech_v1/proto/cloud_speech.proto", - package="google.cloud.speech.v1", - syntax="proto3", - serialized_options=_b( - "\n\032com.google.cloud.speech.v1B\013SpeechProtoP\001Z\n\x06\x63onfig\x18\x01 \x01(\x0b\x32).google.cloud.speech.v1.RecognitionConfigB\x03\xe0\x41\x02\x12<\n\x05\x61udio\x18\x02 \x01(\x0b\x32(.google.cloud.speech.v1.RecognitionAudioB\x03\xe0\x41\x02"\x9b\x01\n\x1bLongRunningRecognizeRequest\x12>\n\x06\x63onfig\x18\x01 \x01(\x0b\x32).google.cloud.speech.v1.RecognitionConfigB\x03\xe0\x41\x02\x12<\n\x05\x61udio\x18\x02 \x01(\x0b\x32(.google.cloud.speech.v1.RecognitionAudioB\x03\xe0\x41\x02"\x99\x01\n\x19StreamingRecognizeRequest\x12N\n\x10streaming_config\x18\x01 \x01(\x0b\x32\x32.google.cloud.speech.v1.StreamingRecognitionConfigH\x00\x12\x17\n\raudio_content\x18\x02 \x01(\x0cH\x00\x42\x13\n\x11streaming_request"\x8f\x01\n\x1aStreamingRecognitionConfig\x12>\n\x06\x63onfig\x18\x01 \x01(\x0b\x32).google.cloud.speech.v1.RecognitionConfigB\x03\xe0\x41\x02\x12\x18\n\x10single_utterance\x18\x02 \x01(\x08\x12\x17\n\x0finterim_results\x18\x03 \x01(\x08"\xdf\x05\n\x11RecognitionConfig\x12I\n\x08\x65ncoding\x18\x01 \x01(\x0e\x32\x37.google.cloud.speech.v1.RecognitionConfig.AudioEncoding\x12\x19\n\x11sample_rate_hertz\x18\x02 \x01(\x05\x12\x1b\n\x13\x61udio_channel_count\x18\x07 \x01(\x05\x12/\n\'enable_separate_recognition_per_channel\x18\x0c \x01(\x08\x12\x1a\n\rlanguage_code\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12\x18\n\x10max_alternatives\x18\x04 \x01(\x05\x12\x18\n\x10profanity_filter\x18\x05 \x01(\x08\x12>\n\x0fspeech_contexts\x18\x06 \x03(\x0b\x32%.google.cloud.speech.v1.SpeechContext\x12 \n\x18\x65nable_word_time_offsets\x18\x08 \x01(\x08\x12$\n\x1c\x65nable_automatic_punctuation\x18\x0b \x01(\x08\x12L\n\x12\x64iarization_config\x18\x13 \x01(\x0b\x32\x30.google.cloud.speech.v1.SpeakerDiarizationConfig\x12=\n\x08metadata\x18\t \x01(\x0b\x32+.google.cloud.speech.v1.RecognitionMetadata\x12\r\n\x05model\x18\r \x01(\t\x12\x14\n\x0cuse_enhanced\x18\x0e \x01(\x08"\x8b\x01\n\rAudioEncoding\x12\x18\n\x14\x45NCODING_UNSPECIFIED\x10\x00\x12\x0c\n\x08LINEAR16\x10\x01\x12\x08\n\x04\x46LAC\x10\x02\x12\t\n\x05MULAW\x10\x03\x12\x07\n\x03\x41MR\x10\x04\x12\n\n\x06\x41MR_WB\x10\x05\x12\x0c\n\x08OGG_OPUS\x10\x06\x12\x1a\n\x16SPEEX_WITH_HEADER_BYTE\x10\x07"\x90\x01\n\x18SpeakerDiarizationConfig\x12"\n\x1a\x65nable_speaker_diarization\x18\x01 \x01(\x08\x12\x19\n\x11min_speaker_count\x18\x02 \x01(\x05\x12\x19\n\x11max_speaker_count\x18\x03 \x01(\x05\x12\x1a\n\x0bspeaker_tag\x18\x05 \x01(\x05\x42\x05\x18\x01\xe0\x41\x03"\xa0\x08\n\x13RecognitionMetadata\x12U\n\x10interaction_type\x18\x01 \x01(\x0e\x32;.google.cloud.speech.v1.RecognitionMetadata.InteractionType\x12$\n\x1cindustry_naics_code_of_audio\x18\x03 \x01(\r\x12[\n\x13microphone_distance\x18\x04 \x01(\x0e\x32>.google.cloud.speech.v1.RecognitionMetadata.MicrophoneDistance\x12Z\n\x13original_media_type\x18\x05 \x01(\x0e\x32=.google.cloud.speech.v1.RecognitionMetadata.OriginalMediaType\x12^\n\x15recording_device_type\x18\x06 \x01(\x0e\x32?.google.cloud.speech.v1.RecognitionMetadata.RecordingDeviceType\x12\x1d\n\x15recording_device_name\x18\x07 \x01(\t\x12\x1a\n\x12original_mime_type\x18\x08 \x01(\t\x12\x13\n\x0b\x61udio_topic\x18\n \x01(\t"\xc5\x01\n\x0fInteractionType\x12 \n\x1cINTERACTION_TYPE_UNSPECIFIED\x10\x00\x12\x0e\n\nDISCUSSION\x10\x01\x12\x10\n\x0cPRESENTATION\x10\x02\x12\x0e\n\nPHONE_CALL\x10\x03\x12\r\n\tVOICEMAIL\x10\x04\x12\x1b\n\x17PROFESSIONALLY_PRODUCED\x10\x05\x12\x10\n\x0cVOICE_SEARCH\x10\x06\x12\x11\n\rVOICE_COMMAND\x10\x07\x12\r\n\tDICTATION\x10\x08"d\n\x12MicrophoneDistance\x12#\n\x1fMICROPHONE_DISTANCE_UNSPECIFIED\x10\x00\x12\r\n\tNEARFIELD\x10\x01\x12\x0c\n\x08MIDFIELD\x10\x02\x12\x0c\n\x08\x46\x41RFIELD\x10\x03"N\n\x11OriginalMediaType\x12#\n\x1fORIGINAL_MEDIA_TYPE_UNSPECIFIED\x10\x00\x12\t\n\x05\x41UDIO\x10\x01\x12\t\n\x05VIDEO\x10\x02"\xa4\x01\n\x13RecordingDeviceType\x12%\n!RECORDING_DEVICE_TYPE_UNSPECIFIED\x10\x00\x12\x0e\n\nSMARTPHONE\x10\x01\x12\x06\n\x02PC\x10\x02\x12\x0e\n\nPHONE_LINE\x10\x03\x12\x0b\n\x07VEHICLE\x10\x04\x12\x18\n\x14OTHER_OUTDOOR_DEVICE\x10\x05\x12\x17\n\x13OTHER_INDOOR_DEVICE\x10\x06" \n\rSpeechContext\x12\x0f\n\x07phrases\x18\x01 \x03(\t"D\n\x10RecognitionAudio\x12\x11\n\x07\x63ontent\x18\x01 \x01(\x0cH\x00\x12\r\n\x03uri\x18\x02 \x01(\tH\x00\x42\x0e\n\x0c\x61udio_source"U\n\x11RecognizeResponse\x12@\n\x07results\x18\x02 \x03(\x0b\x32/.google.cloud.speech.v1.SpeechRecognitionResult"`\n\x1cLongRunningRecognizeResponse\x12@\n\x07results\x18\x02 \x03(\x0b\x32/.google.cloud.speech.v1.SpeechRecognitionResult"\x9e\x01\n\x1cLongRunningRecognizeMetadata\x12\x18\n\x10progress_percent\x18\x01 \x01(\x05\x12.\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xb1\x02\n\x1aStreamingRecognizeResponse\x12!\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x12.google.rpc.Status\x12\x43\n\x07results\x18\x02 \x03(\x0b\x32\x32.google.cloud.speech.v1.StreamingRecognitionResult\x12]\n\x11speech_event_type\x18\x04 \x01(\x0e\x32\x42.google.cloud.speech.v1.StreamingRecognizeResponse.SpeechEventType"L\n\x0fSpeechEventType\x12\x1c\n\x18SPEECH_EVENT_UNSPECIFIED\x10\x00\x12\x1b\n\x17\x45ND_OF_SINGLE_UTTERANCE\x10\x01"\xf2\x01\n\x1aStreamingRecognitionResult\x12J\n\x0c\x61lternatives\x18\x01 \x03(\x0b\x32\x34.google.cloud.speech.v1.SpeechRecognitionAlternative\x12\x10\n\x08is_final\x18\x02 \x01(\x08\x12\x11\n\tstability\x18\x03 \x01(\x02\x12\x32\n\x0fresult_end_time\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0b\x63hannel_tag\x18\x05 \x01(\x05\x12\x1a\n\rlanguage_code\x18\x06 \x01(\tB\x03\xe0\x41\x03"z\n\x17SpeechRecognitionResult\x12J\n\x0c\x61lternatives\x18\x01 \x03(\x0b\x32\x34.google.cloud.speech.v1.SpeechRecognitionAlternative\x12\x13\n\x0b\x63hannel_tag\x18\x02 \x01(\x05"w\n\x1cSpeechRecognitionAlternative\x12\x12\n\ntranscript\x18\x01 \x01(\t\x12\x12\n\nconfidence\x18\x02 \x01(\x02\x12/\n\x05words\x18\x03 \x03(\x0b\x32 .google.cloud.speech.v1.WordInfo"\x8e\x01\n\x08WordInfo\x12-\n\nstart_time\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12+\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0c\n\x04word\x18\x03 \x01(\t\x12\x18\n\x0bspeaker_tag\x18\x05 \x01(\x05\x42\x03\xe0\x41\x03\x32\xd1\x04\n\x06Speech\x12\x90\x01\n\tRecognize\x12(.google.cloud.speech.v1.RecognizeRequest\x1a).google.cloud.speech.v1.RecognizeResponse".\x82\xd3\xe4\x93\x02\x19"\x14/v1/speech:recognize:\x01*\xda\x41\x0c\x63onfig,audio\x12\xe4\x01\n\x14LongRunningRecognize\x12\x33.google.cloud.speech.v1.LongRunningRecognizeRequest\x1a\x1d.google.longrunning.Operation"x\x82\xd3\xe4\x93\x02$"\x1f/v1/speech:longrunningrecognize:\x01*\xda\x41\x0c\x63onfig,audio\xca\x41<\n\x1cLongRunningRecognizeResponse\x12\x1cLongRunningRecognizeMetadata\x12\x81\x01\n\x12StreamingRecognize\x12\x31.google.cloud.speech.v1.StreamingRecognizeRequest\x1a\x32.google.cloud.speech.v1.StreamingRecognizeResponse"\x00(\x01\x30\x01\x1aI\xca\x41\x15speech.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformBr\n\x1a\x63om.google.cloud.speech.v1B\x0bSpeechProtoP\x01Z`__. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.StreamingRecognizeRequest) - ), -) -_sym_db.RegisterMessage(StreamingRecognizeRequest) - -StreamingRecognitionConfig = _reflection.GeneratedProtocolMessageType( - "StreamingRecognitionConfig", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGRECOGNITIONCONFIG, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Provides information to the recognizer that specifies how - to process the request. - - - Attributes: - config: - Required. Provides information to the recognizer that - specifies how to process the request. - single_utterance: - If ``false`` or omitted, the recognizer will perform - continuous recognition (continuing to wait for and process - audio even if the user pauses speaking) until the client - closes the input stream (gRPC API) or until the maximum time - limit has been reached. May return multiple - ``StreamingRecognitionResult``\ s with the ``is_final`` flag - set to ``true``. If ``true``, the recognizer will detect a - single spoken utterance. When it detects that the user has - paused or stopped speaking, it will return an - ``END_OF_SINGLE_UTTERANCE`` event and cease recognition. It - will return no more than one ``StreamingRecognitionResult`` - with the ``is_final`` flag set to ``true``. - interim_results: - If ``true``, interim results (tentative hypotheses) may be - returned as they become available (these interim results are - indicated with the ``is_final=false`` flag). If ``false`` or - omitted, only ``is_final=true`` result(s) are returned. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.StreamingRecognitionConfig) - ), -) -_sym_db.RegisterMessage(StreamingRecognitionConfig) - -RecognitionConfig = _reflection.GeneratedProtocolMessageType( - "RecognitionConfig", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNITIONCONFIG, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Provides information to the recognizer that specifies how - to process the request. - - - Attributes: - encoding: - Encoding of audio data sent in all ``RecognitionAudio`` - messages. This field is optional for ``FLAC`` and ``WAV`` - audio files and required for all other audio formats. For - details, see [AudioEncoding][google.cloud.speech.v1.Recognitio - nConfig.AudioEncoding]. - sample_rate_hertz: - Sample rate in Hertz of the audio data sent in all - ``RecognitionAudio`` messages. Valid values are: 8000-48000. - 16000 is optimal. For best results, set the sampling rate of - the audio source to 16000 Hz. If that's not possible, use the - native sample rate of the audio source (instead of re- - sampling). This field is optional for FLAC and WAV audio - files, but is required for all other audio formats. For - details, see [AudioEncoding][google.cloud.speech.v1.Recognitio - nConfig.AudioEncoding]. - audio_channel_count: - The number of channels in the input audio data. ONLY set this - for MULTI-CHANNEL recognition. Valid values for LINEAR16 and - FLAC are ``1``-``8``. Valid values for OGG\_OPUS are - '1'-'254'. Valid value for MULAW, AMR, AMR\_WB and - SPEEX\_WITH\_HEADER\_BYTE is only ``1``. If ``0`` or omitted, - defaults to one channel (mono). Note: We only recognize the - first channel by default. To perform independent recognition - on each channel set - ``enable_separate_recognition_per_channel`` to 'true'. - enable_separate_recognition_per_channel: - This needs to be set to ``true`` explicitly and - ``audio_channel_count`` > 1 to get each channel recognized - separately. The recognition result will contain a - ``channel_tag`` field to state which channel that result - belongs to. If this is not true, we will only recognize the - first channel. The request is billed cumulatively for all - channels recognized: ``audio_channel_count`` multiplied by the - length of the audio. - language_code: - Required. The language of the supplied audio as a `BCP-47 - `__ language - tag. Example: "en-US". See `Language Support - `__ - for a list of the currently supported language codes. - max_alternatives: - Maximum number of recognition hypotheses to be returned. - Specifically, the maximum number of - ``SpeechRecognitionAlternative`` messages within each - ``SpeechRecognitionResult``. The server may return fewer than - ``max_alternatives``. Valid values are ``0``-``30``. A value - of ``0`` or ``1`` will return a maximum of one. If omitted, - will return a maximum of one. - profanity_filter: - If set to ``true``, the server will attempt to filter out - profanities, replacing all but the initial character in each - filtered word with asterisks, e.g. "f\*\*\*". If set to - ``false`` or omitted, profanities won't be filtered out. - speech_contexts: - Array of - [SpeechContext][google.cloud.speech.v1.SpeechContext]. A means - to provide context to assist the speech recognition. For more - information, see `speech adaptation - `__. - enable_word_time_offsets: - If ``true``, the top result includes a list of words and the - start and end time offsets (timestamps) for those words. If - ``false``, no word-level time offset information is returned. - The default is ``false``. - enable_automatic_punctuation: - If 'true', adds punctuation to recognition result hypotheses. - This feature is only available in select languages. Setting - this for requests in other languages has no effect at all. The - default 'false' value does not add punctuation to result - hypotheses. Note: This is currently offered as an experimental - service, complimentary to all users. In the future this may be - exclusively available as a premium feature. - diarization_config: - Config to enable speaker diarization and set additional - parameters to make diarization better suited for your - application. Note: When this is enabled, we send all the words - from the beginning of the audio for the top alternative in - every consecutive STREAMING responses. This is done in order - to improve our speaker tags as our models learn to identify - the speakers in the conversation over time. For non-streaming - requests, the diarization results will be provided only in the - top alternative of the FINAL SpeechRecognitionResult. - metadata: - Metadata regarding this request. - model: - Which model to select for the given request. Select the model - best suited to your domain to get best results. If a model is - not explicitly specified, then we auto-select a model based on - the parameters in the RecognitionConfig. .. raw:: html - .. raw:: html :: - .. raw:: html .. raw:: - html :: - .. - raw:: html .. raw:: html :: - .. raw:: html .. raw:: - html :: - .. - raw:: html .. raw:: html :: - .. raw:: - html .. raw:: html
ModelDescription
command_and_search Best for - short queries such as voice commands or voice search.
phone_call Best for audio that - originated from a phone call (typically recorded at an - 8khz sampling rate).
videoBest for audio that originated from from video or includes - multiple speakers. Ideally the audio is recorded at a - 16khz or greater sampling rate. This is a premium - model that costs more than the standard rate.
default Best for audio that is - not one of the specific audio models. For example, - long-form audio. Ideally the audio is high-fidelity, - recorded at a 16khz or greater sampling rate.
- use_enhanced: - Set to true to use an enhanced model for speech recognition. - If ``use_enhanced`` is set to true and the ``model`` field is - not set, then an appropriate enhanced model is chosen if an - enhanced model exists for the audio. If ``use_enhanced`` is - true and an enhanced version of the specified model does not - exist, then the speech is recognized using the standard - version of the specified model. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.RecognitionConfig) - ), -) -_sym_db.RegisterMessage(RecognitionConfig) - -SpeakerDiarizationConfig = _reflection.GeneratedProtocolMessageType( - "SpeakerDiarizationConfig", - (_message.Message,), - dict( - DESCRIPTOR=_SPEAKERDIARIZATIONCONFIG, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Config to enable speaker diarization. - - - Attributes: - enable_speaker_diarization: - If 'true', enables speaker detection for each recognized word - in the top alternative of the recognition result using a - speaker\_tag provided in the WordInfo. - min_speaker_count: - Minimum number of speakers in the conversation. This range - gives you more flexibility by allowing the system to - automatically determine the correct number of speakers. If not - set, the default value is 2. - max_speaker_count: - Maximum number of speakers in the conversation. This range - gives you more flexibility by allowing the system to - automatically determine the correct number of speakers. If not - set, the default value is 6. - speaker_tag: - Unused. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.SpeakerDiarizationConfig) - ), -) -_sym_db.RegisterMessage(SpeakerDiarizationConfig) - -RecognitionMetadata = _reflection.GeneratedProtocolMessageType( - "RecognitionMetadata", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNITIONMETADATA, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Description of audio data to be recognized. - - - Attributes: - interaction_type: - The use case most closely describing the audio content to be - recognized. - industry_naics_code_of_audio: - The industry vertical to which this speech recognition request - most closely applies. This is most indicative of the topics - contained in the audio. Use the 6-digit NAICS code to identify - the industry vertical - see https://www.naics.com/search/. - microphone_distance: - The audio type that most closely describes the audio being - recognized. - original_media_type: - The original media the speech was recorded on. - recording_device_type: - The type of device the speech was recorded with. - recording_device_name: - The device used to make the recording. Examples 'Nexus 5X' or - 'Polycom SoundStation IP 6000' or 'POTS' or 'VoIP' or - 'Cardioid Microphone'. - original_mime_type: - Mime type of the original audio file. For example - ``audio/m4a``, ``audio/x-alaw-basic``, ``audio/mp3``, - ``audio/3gpp``. A list of possible audio mime types is - maintained at http://www.iana.org/assignments/media- - types/media-types.xhtml#audio - audio_topic: - Description of the content. Eg. "Recordings of federal supreme - court hearings from 2012". - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.RecognitionMetadata) - ), -) -_sym_db.RegisterMessage(RecognitionMetadata) - -SpeechContext = _reflection.GeneratedProtocolMessageType( - "SpeechContext", - (_message.Message,), - dict( - DESCRIPTOR=_SPEECHCONTEXT, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Provides "hints" to the speech recognizer to favor - specific words and phrases in the results. - - - Attributes: - phrases: - A list of strings containing words and phrases "hints" so that - the speech recognition is more likely to recognize them. This - can be used to improve the accuracy for specific words and - phrases, for example, if specific commands are typically - spoken by the user. This can also be used to add additional - words to the vocabulary of the recognizer. See `usage limits - `__. - List items can also be set to classes for groups of words that - represent common concepts that occur in natural language. For - example, rather than providing phrase hints for every month of - the year, using the $MONTH class improves the likelihood of - correctly transcribing audio that includes months. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.SpeechContext) - ), -) -_sym_db.RegisterMessage(SpeechContext) - -RecognitionAudio = _reflection.GeneratedProtocolMessageType( - "RecognitionAudio", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNITIONAUDIO, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Contains audio data in the encoding specified in the - ``RecognitionConfig``. Either ``content`` or ``uri`` must be supplied. - Supplying both or neither returns - [google.rpc.Code.INVALID\_ARGUMENT][google.rpc.Code.INVALID\_ARGUMENT]. - See `content - limits `__. - - - Attributes: - audio_source: - The audio source, which is either inline content or a Google - Cloud Storage uri. - content: - The audio data bytes encoded as specified in - ``RecognitionConfig``. Note: as with all bytes fields, proto - buffers use a pure binary representation, whereas JSON - representations use base64. - uri: - URI that points to a file that contains audio data bytes as - specified in ``RecognitionConfig``. The file must not be - compressed (for example, gzip). Currently, only Google Cloud - Storage URIs are supported, which must be specified in the - following format: ``gs://bucket_name/object_name`` (other URI - formats return [google.rpc.Code.INVALID\_ARGUMENT][google.rpc. - Code.INVALID\_ARGUMENT]). For more information, see `Request - URIs `__. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.RecognitionAudio) - ), -) -_sym_db.RegisterMessage(RecognitionAudio) - -RecognizeResponse = _reflection.GeneratedProtocolMessageType( - "RecognizeResponse", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNIZERESPONSE, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""The only message returned to the client by the - ``Recognize`` method. It contains the result as zero or more sequential - ``SpeechRecognitionResult`` messages. - - - Attributes: - results: - Sequential list of transcription results corresponding to - sequential portions of audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.RecognizeResponse) - ), -) -_sym_db.RegisterMessage(RecognizeResponse) - -LongRunningRecognizeResponse = _reflection.GeneratedProtocolMessageType( - "LongRunningRecognizeResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LONGRUNNINGRECOGNIZERESPONSE, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""The only message returned to the client by the - ``LongRunningRecognize`` method. It contains the result as zero or more - sequential ``SpeechRecognitionResult`` messages. It is included in the - ``result.response`` field of the ``Operation`` returned by the - ``GetOperation`` call of the ``google::longrunning::Operations`` - service. - - - Attributes: - results: - Sequential list of transcription results corresponding to - sequential portions of audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.LongRunningRecognizeResponse) - ), -) -_sym_db.RegisterMessage(LongRunningRecognizeResponse) - -LongRunningRecognizeMetadata = _reflection.GeneratedProtocolMessageType( - "LongRunningRecognizeMetadata", - (_message.Message,), - dict( - DESCRIPTOR=_LONGRUNNINGRECOGNIZEMETADATA, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Describes the progress of a long-running - ``LongRunningRecognize`` call. It is included in the ``metadata`` field - of the ``Operation`` returned by the ``GetOperation`` call of the - ``google::longrunning::Operations`` service. - - - Attributes: - progress_percent: - Approximate percentage of audio processed thus far. Guaranteed - to be 100 when the audio is fully processed and the results - are available. - start_time: - Time when the request was received. - last_update_time: - Time of the most recent processing update. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.LongRunningRecognizeMetadata) - ), -) -_sym_db.RegisterMessage(LongRunningRecognizeMetadata) - -StreamingRecognizeResponse = _reflection.GeneratedProtocolMessageType( - "StreamingRecognizeResponse", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGRECOGNIZERESPONSE, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""\ ``StreamingRecognizeResponse`` is the only message - returned to the client by ``StreamingRecognize``. A series of zero or - more ``StreamingRecognizeResponse`` messages are streamed back to the - client. If there is no recognizable audio, and ``single_utterance`` is - set to false, then no messages are streamed back to the client. - - Here's an example of a series of ten ``StreamingRecognizeResponse``\ s - that might be returned while processing audio: - - 1. results { alternatives { transcript: "tube" } stability: 0.01 } - - 2. results { alternatives { transcript: "to be a" } stability: 0.01 } - - 3. results { alternatives { transcript: "to be" } stability: 0.9 } - results { alternatives { transcript: " or not to be" } stability: - 0.01 } - - 4. results { alternatives { transcript: "to be or not to be" confidence: - 0.92 } alternatives { transcript: "to bee or not to bee" } is\_final: - true } - - 5. results { alternatives { transcript: " that's" } stability: 0.01 } - - 6. results { alternatives { transcript: " that is" } stability: 0.9 } - results { alternatives { transcript: " the question" } stability: - 0.01 } - - 7. results { alternatives { transcript: " that is the question" - confidence: 0.98 } alternatives { transcript: " that was the - question" } is\_final: true } - - Notes: - - - Only two of the above responses #4 and #7 contain final results; they - are indicated by ``is_final: true``. Concatenating these together - generates the full transcript: "to be or not to be that is the - question". - - - The others contain interim ``results``. #3 and #6 contain two interim - ``results``: the first portion has a high stability and is less - likely to change; the second portion has a low stability and is very - likely to change. A UI designer might choose to show only high - stability ``results``. - - - The specific ``stability`` and ``confidence`` values shown above are - only for illustrative purposes. Actual values may vary. - - - In each response, only one of these fields will be set: ``error``, - ``speech_event_type``, or one or more (repeated) ``results``. - - - Attributes: - error: - If set, returns a [google.rpc.Status][google.rpc.Status] - message that specifies the error for the operation. - results: - This repeated list contains zero or more results that - correspond to consecutive portions of the audio currently - being processed. It contains zero or one ``is_final=true`` - result (the newly settled portion), followed by zero or more - ``is_final=false`` results (the interim results). - speech_event_type: - Indicates the type of speech event. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.StreamingRecognizeResponse) - ), -) -_sym_db.RegisterMessage(StreamingRecognizeResponse) - -StreamingRecognitionResult = _reflection.GeneratedProtocolMessageType( - "StreamingRecognitionResult", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGRECOGNITIONRESULT, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""A streaming speech recognition result corresponding to a - portion of the audio that is currently being processed. - - - Attributes: - alternatives: - May contain one or more recognition hypotheses (up to the - maximum specified in ``max_alternatives``). These alternatives - are ordered in terms of accuracy, with the top (first) - alternative being the most probable, as ranked by the - recognizer. - is_final: - If ``false``, this ``StreamingRecognitionResult`` represents - an interim result that may change. If ``true``, this is the - final time the speech service will return this particular - ``StreamingRecognitionResult``, the recognizer will not return - any further hypotheses for this portion of the transcript and - corresponding audio. - stability: - An estimate of the likelihood that the recognizer will not - change its guess about this interim result. Values range from - 0.0 (completely unstable) to 1.0 (completely stable). This - field is only provided for interim results - (``is_final=false``). The default of 0.0 is a sentinel value - indicating ``stability`` was not set. - result_end_time: - Time offset of the end of this result relative to the - beginning of the audio. - channel_tag: - For multi-channel audio, this is the channel number - corresponding to the recognized result for the audio from that - channel. For audio\_channel\_count = N, its output values can - range from '1' to 'N'. - language_code: - The `BCP-47 `__ - language tag of the language in this result. This language - code was detected to have the most likelihood of being spoken - in the audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.StreamingRecognitionResult) - ), -) -_sym_db.RegisterMessage(StreamingRecognitionResult) - -SpeechRecognitionResult = _reflection.GeneratedProtocolMessageType( - "SpeechRecognitionResult", - (_message.Message,), - dict( - DESCRIPTOR=_SPEECHRECOGNITIONRESULT, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""A speech recognition result corresponding to a portion of - the audio. - - - Attributes: - alternatives: - May contain one or more recognition hypotheses (up to the - maximum specified in ``max_alternatives``). These alternatives - are ordered in terms of accuracy, with the top (first) - alternative being the most probable, as ranked by the - recognizer. - channel_tag: - For multi-channel audio, this is the channel number - corresponding to the recognized result for the audio from that - channel. For audio\_channel\_count = N, its output values can - range from '1' to 'N'. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.SpeechRecognitionResult) - ), -) -_sym_db.RegisterMessage(SpeechRecognitionResult) - -SpeechRecognitionAlternative = _reflection.GeneratedProtocolMessageType( - "SpeechRecognitionAlternative", - (_message.Message,), - dict( - DESCRIPTOR=_SPEECHRECOGNITIONALTERNATIVE, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Alternative hypotheses (a.k.a. n-best list). - - - Attributes: - transcript: - Transcript text representing the words that the user spoke. - confidence: - The confidence estimate between 0.0 and 1.0. A higher number - indicates an estimated greater likelihood that the recognized - words are correct. This field is set only for the top - alternative of a non-streaming result or, of a streaming - result where ``is_final=true``. This field is not guaranteed - to be accurate and users should not rely on it to be always - provided. The default of 0.0 is a sentinel value indicating - ``confidence`` was not set. - words: - A list of word-specific information for each recognized word. - Note: When ``enable_speaker_diarization`` is true, you will - see all the words from the beginning of the audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.SpeechRecognitionAlternative) - ), -) -_sym_db.RegisterMessage(SpeechRecognitionAlternative) - -WordInfo = _reflection.GeneratedProtocolMessageType( - "WordInfo", - (_message.Message,), - dict( - DESCRIPTOR=_WORDINFO, - __module__="google.cloud.speech_v1.proto.cloud_speech_pb2", - __doc__="""Word-specific information for recognized words. - - - Attributes: - start_time: - Time offset relative to the beginning of the audio, and - corresponding to the start of the spoken word. This field is - only set if ``enable_word_time_offsets=true`` and only in the - top hypothesis. This is an experimental feature and the - accuracy of the time offset can vary. - end_time: - Time offset relative to the beginning of the audio, and - corresponding to the end of the spoken word. This field is - only set if ``enable_word_time_offsets=true`` and only in the - top hypothesis. This is an experimental feature and the - accuracy of the time offset can vary. - word: - The word corresponding to this set of information. - speaker_tag: - A distinct integer value is assigned for every speaker within - the audio. This field specifies which one of those speakers - was detected to have spoken this word. Value ranges from '1' - to diarization\_speaker\_count. speaker\_tag is set if - enable\_speaker\_diarization = 'true' and only in the top - alternative. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1.WordInfo) - ), -) -_sym_db.RegisterMessage(WordInfo) - - -DESCRIPTOR._options = None -_RECOGNIZEREQUEST.fields_by_name["config"]._options = None -_RECOGNIZEREQUEST.fields_by_name["audio"]._options = None -_LONGRUNNINGRECOGNIZEREQUEST.fields_by_name["config"]._options = None -_LONGRUNNINGRECOGNIZEREQUEST.fields_by_name["audio"]._options = None -_STREAMINGRECOGNITIONCONFIG.fields_by_name["config"]._options = None -_RECOGNITIONCONFIG.fields_by_name["language_code"]._options = None -_SPEAKERDIARIZATIONCONFIG.fields_by_name["speaker_tag"]._options = None -_STREAMINGRECOGNITIONRESULT.fields_by_name["language_code"]._options = None -_WORDINFO.fields_by_name["speaker_tag"]._options = None - -_SPEECH = _descriptor.ServiceDescriptor( - name="Speech", - full_name="google.cloud.speech.v1.Speech", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\025speech.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=4262, - serialized_end=4855, - methods=[ - _descriptor.MethodDescriptor( - name="Recognize", - full_name="google.cloud.speech.v1.Speech.Recognize", - index=0, - containing_service=None, - input_type=_RECOGNIZEREQUEST, - output_type=_RECOGNIZERESPONSE, - serialized_options=_b( - '\202\323\344\223\002\031"\024/v1/speech:recognize:\001*\332A\014config,audio' - ), - ), - _descriptor.MethodDescriptor( - name="LongRunningRecognize", - full_name="google.cloud.speech.v1.Speech.LongRunningRecognize", - index=1, - containing_service=None, - input_type=_LONGRUNNINGRECOGNIZEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - '\202\323\344\223\002$"\037/v1/speech:longrunningrecognize:\001*\332A\014config,audio\312A<\n\034LongRunningRecognizeResponse\022\034LongRunningRecognizeMetadata' - ), - ), - _descriptor.MethodDescriptor( - name="StreamingRecognize", - full_name="google.cloud.speech.v1.Speech.StreamingRecognize", - index=2, - containing_service=None, - input_type=_STREAMINGRECOGNIZEREQUEST, - output_type=_STREAMINGRECOGNIZERESPONSE, - serialized_options=None, - ), - ], -) -_sym_db.RegisterServiceDescriptor(_SPEECH) - -DESCRIPTOR.services_by_name["Speech"] = _SPEECH - -# @@protoc_insertion_point(module_scope) diff --git a/speech/google/cloud/speech_v1/proto/cloud_speech_pb2_grpc.py b/speech/google/cloud/speech_v1/proto/cloud_speech_pb2_grpc.py deleted file mode 100644 index a7ddcb9c8865..000000000000 --- a/speech/google/cloud/speech_v1/proto/cloud_speech_pb2_grpc.py +++ /dev/null @@ -1,93 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.speech_v1.proto import ( - cloud_speech_pb2 as google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2, -) -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) - - -class SpeechStub(object): - """Service that implements Google Cloud Speech API. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.Recognize = channel.unary_unary( - "/google.cloud.speech.v1.Speech/Recognize", - request_serializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.RecognizeRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.RecognizeResponse.FromString, - ) - self.LongRunningRecognize = channel.unary_unary( - "/google.cloud.speech.v1.Speech/LongRunningRecognize", - request_serializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.LongRunningRecognizeRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.StreamingRecognize = channel.stream_stream( - "/google.cloud.speech.v1.Speech/StreamingRecognize", - request_serializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeResponse.FromString, - ) - - -class SpeechServicer(object): - """Service that implements Google Cloud Speech API. - """ - - def Recognize(self, request, context): - """Performs synchronous speech recognition: receive results after all audio - has been sent and processed. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def LongRunningRecognize(self, request, context): - """Performs asynchronous speech recognition: receive results via the - google.longrunning.Operations interface. Returns either an - `Operation.error` or an `Operation.response` which contains - a `LongRunningRecognizeResponse` message. - For more information on asynchronous speech recognition, see the - [how-to](https://cloud.google.com/speech-to-text/docs/async-recognize). - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def StreamingRecognize(self, request_iterator, context): - """Performs bidirectional streaming speech recognition: receive results while - sending audio. This method is only available via the gRPC API (not REST). - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_SpeechServicer_to_server(servicer, server): - rpc_method_handlers = { - "Recognize": grpc.unary_unary_rpc_method_handler( - servicer.Recognize, - request_deserializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.RecognizeRequest.FromString, - response_serializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.RecognizeResponse.SerializeToString, - ), - "LongRunningRecognize": grpc.unary_unary_rpc_method_handler( - servicer.LongRunningRecognize, - request_deserializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.LongRunningRecognizeRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "StreamingRecognize": grpc.stream_stream_rpc_method_handler( - servicer.StreamingRecognize, - request_deserializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeRequest.FromString, - response_serializer=google_dot_cloud_dot_speech__v1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.speech.v1.Speech", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/speech/google/cloud/speech_v1/types.py b/speech/google/cloud/speech_v1/types.py deleted file mode 100644 index f2bd717a7a06..000000000000 --- a/speech/google/cloud/speech_v1/types.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.speech_v1.proto import cloud_speech_pb2 -from google.longrunning import operations_pb2 -from google.protobuf import any_pb2 -from google.protobuf import duration_pb2 -from google.protobuf import timestamp_pb2 -from google.rpc import status_pb2 - - -_shared_modules = [operations_pb2, any_pb2, duration_pb2, timestamp_pb2, status_pb2] - -_local_modules = [cloud_speech_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.speech_v1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/speech/google/cloud/speech_v1p1beta1/__init__.py b/speech/google/cloud/speech_v1p1beta1/__init__.py deleted file mode 100644 index b68a395372f9..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import absolute_import - -from google.cloud.speech_v1p1beta1 import types -from google.cloud.speech_v1p1beta1.gapic import enums -from google.cloud.speech_v1p1beta1.gapic import speech_client - -from google.cloud.speech_v1.helpers import SpeechHelpers - - -class SpeechClient(SpeechHelpers, speech_client.SpeechClient): - __doc__ = speech_client.SpeechClient.__doc__ - enums = enums - types = types - - -__all__ = ("enums", "types", "SpeechClient") diff --git a/speech/google/cloud/speech_v1p1beta1/gapic/__init__.py b/speech/google/cloud/speech_v1p1beta1/gapic/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/speech/google/cloud/speech_v1p1beta1/gapic/enums.py b/speech/google/cloud/speech_v1p1beta1/gapic/enums.py deleted file mode 100644 index 3616356fa51d..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/gapic/enums.py +++ /dev/null @@ -1,200 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Wrappers for protocol buffer enum types.""" - -import enum - - -class RecognitionConfig(object): - class AudioEncoding(enum.IntEnum): - """ - The encoding of the audio data sent in the request. - - All encodings support only 1 channel (mono) audio, unless the - ``audio_channel_count`` and ``enable_separate_recognition_per_channel`` - fields are set. - - For best results, the audio source should be captured and transmitted - using a lossless encoding (``FLAC`` or ``LINEAR16``). The accuracy of - the speech recognition can be reduced if lossy codecs are used to - capture or transmit audio, particularly if background noise is present. - Lossy codecs include ``MULAW``, ``AMR``, ``AMR_WB``, ``OGG_OPUS``, - ``SPEEX_WITH_HEADER_BYTE``, and ``MP3``. - - The ``FLAC`` and ``WAV`` audio file formats include a header that - describes the included audio content. You can request recognition for - ``WAV`` files that contain either ``LINEAR16`` or ``MULAW`` encoded - audio. If you send ``FLAC`` or ``WAV`` audio file format in your - request, you do not need to specify an ``AudioEncoding``; the audio - encoding format is determined from the file header. If you specify an - ``AudioEncoding`` when you send send ``FLAC`` or ``WAV`` audio, the - encoding configuration must match the encoding described in the audio - header; otherwise the request returns an - ``google.rpc.Code.INVALID_ARGUMENT`` error code. - - Attributes: - ENCODING_UNSPECIFIED (int): Not specified. - LINEAR16 (int): Uncompressed 16-bit signed little-endian samples (Linear PCM). - FLAC (int): ``FLAC`` (Free Lossless Audio Codec) is the recommended encoding because - it is lossless--therefore recognition is not compromised--and requires - only about half the bandwidth of ``LINEAR16``. ``FLAC`` stream encoding - supports 16-bit and 24-bit samples, however, not all fields in - ``STREAMINFO`` are supported. - MULAW (int): 8-bit samples that compand 14-bit audio samples using G.711 PCMU/mu-law. - AMR (int): Adaptive Multi-Rate Narrowband codec. ``sample_rate_hertz`` must be - 8000. - AMR_WB (int): Adaptive Multi-Rate Wideband codec. ``sample_rate_hertz`` must be 16000. - OGG_OPUS (int): Opus encoded audio frames in Ogg container - (`OggOpus `__). ``sample_rate_hertz`` - must be one of 8000, 12000, 16000, 24000, or 48000. - SPEEX_WITH_HEADER_BYTE (int): Although the use of lossy encodings is not recommended, if a very low - bitrate encoding is required, ``OGG_OPUS`` is highly preferred over - Speex encoding. The `Speex `__ encoding supported by - Cloud Speech API has a header byte in each block, as in MIME type - ``audio/x-speex-with-header-byte``. It is a variant of the RTP Speex - encoding defined in `RFC 5574 `__. - The stream is a sequence of blocks, one block per RTP packet. Each block - starts with a byte containing the length of the block, in bytes, - followed by one or more frames of Speex data, padded to an integral - number of bytes (octets) as specified in RFC 5574. In other words, each - RTP header is replaced with a single byte containing the block length. - Only Speex wideband is supported. ``sample_rate_hertz`` must be 16000. - MP3 (int): MP3 audio. Support all standard MP3 bitrates (which range from 32-320 - kbps). When using this encoding, ``sample_rate_hertz`` can be optionally - unset if not known. - """ - - ENCODING_UNSPECIFIED = 0 - LINEAR16 = 1 - FLAC = 2 - MULAW = 3 - AMR = 4 - AMR_WB = 5 - OGG_OPUS = 6 - SPEEX_WITH_HEADER_BYTE = 7 - MP3 = 8 - - -class RecognitionMetadata(object): - class InteractionType(enum.IntEnum): - """ - Use case categories that the audio recognition request can be described - by. - - Attributes: - INTERACTION_TYPE_UNSPECIFIED (int): Use case is either unknown or is something other than one of the other - values below. - DISCUSSION (int): Multiple people in a conversation or discussion. For example in a - meeting with two or more people actively participating. Typically all - the primary people speaking would be in the same room (if not, see - PHONE\_CALL) - PRESENTATION (int): One or more persons lecturing or presenting to others, mostly - uninterrupted. - PHONE_CALL (int): A phone-call or video-conference in which two or more people, who are - not in the same room, are actively participating. - VOICEMAIL (int): A recorded message intended for another person to listen to. - PROFESSIONALLY_PRODUCED (int): Professionally produced audio (eg. TV Show, Podcast). - VOICE_SEARCH (int): Transcribe spoken questions and queries into text. - VOICE_COMMAND (int): Transcribe voice commands, such as for controlling a device. - DICTATION (int): Transcribe speech to text to create a written document, such as a - text-message, email or report. - """ - - INTERACTION_TYPE_UNSPECIFIED = 0 - DISCUSSION = 1 - PRESENTATION = 2 - PHONE_CALL = 3 - VOICEMAIL = 4 - PROFESSIONALLY_PRODUCED = 5 - VOICE_SEARCH = 6 - VOICE_COMMAND = 7 - DICTATION = 8 - - class MicrophoneDistance(enum.IntEnum): - """ - Enumerates the types of capture settings describing an audio file. - - Attributes: - MICROPHONE_DISTANCE_UNSPECIFIED (int): Audio type is not known. - NEARFIELD (int): The audio was captured from a closely placed microphone. Eg. phone, - dictaphone, or handheld microphone. Generally if there speaker is within - 1 meter of the microphone. - MIDFIELD (int): The speaker if within 3 meters of the microphone. - FARFIELD (int): The speaker is more than 3 meters away from the microphone. - """ - - MICROPHONE_DISTANCE_UNSPECIFIED = 0 - NEARFIELD = 1 - MIDFIELD = 2 - FARFIELD = 3 - - class OriginalMediaType(enum.IntEnum): - """ - The original media the speech was recorded on. - - Attributes: - ORIGINAL_MEDIA_TYPE_UNSPECIFIED (int): Unknown original media type. - AUDIO (int): The speech data is an audio recording. - VIDEO (int): The speech data originally recorded on a video. - """ - - ORIGINAL_MEDIA_TYPE_UNSPECIFIED = 0 - AUDIO = 1 - VIDEO = 2 - - class RecordingDeviceType(enum.IntEnum): - """ - The type of device the speech was recorded with. - - Attributes: - RECORDING_DEVICE_TYPE_UNSPECIFIED (int): The recording device is unknown. - SMARTPHONE (int): Speech was recorded on a smartphone. - PC (int): Speech was recorded using a personal computer or tablet. - PHONE_LINE (int): Speech was recorded over a phone line. - VEHICLE (int): Speech was recorded in a vehicle. - OTHER_OUTDOOR_DEVICE (int): Speech was recorded outdoors. - OTHER_INDOOR_DEVICE (int): Speech was recorded indoors. - """ - - RECORDING_DEVICE_TYPE_UNSPECIFIED = 0 - SMARTPHONE = 1 - PC = 2 - PHONE_LINE = 3 - VEHICLE = 4 - OTHER_OUTDOOR_DEVICE = 5 - OTHER_INDOOR_DEVICE = 6 - - -class StreamingRecognizeResponse(object): - class SpeechEventType(enum.IntEnum): - """ - Indicates the type of speech event. - - Attributes: - SPEECH_EVENT_UNSPECIFIED (int): No speech event specified. - END_OF_SINGLE_UTTERANCE (int): This event indicates that the server has detected the end of the user's - speech utterance and expects no additional speech. Therefore, the server - will not process additional audio (although it may subsequently return - additional results). The client should stop sending additional audio - data, half-close the gRPC connection, and wait for any additional - results until the server closes the gRPC connection. This event is only - sent if ``single_utterance`` was set to ``true``, and is not used - otherwise. - """ - - SPEECH_EVENT_UNSPECIFIED = 0 - END_OF_SINGLE_UTTERANCE = 1 diff --git a/speech/google/cloud/speech_v1p1beta1/gapic/speech_client.py b/speech/google/cloud/speech_v1p1beta1/gapic/speech_client.py deleted file mode 100644 index 5703df5b84a0..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/gapic/speech_client.py +++ /dev/null @@ -1,412 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Accesses the google.cloud.speech.v1p1beta1 Speech API.""" - -import pkg_resources -import warnings - -from google.oauth2 import service_account -import google.api_core.client_options -import google.api_core.gapic_v1.client_info -import google.api_core.gapic_v1.config -import google.api_core.gapic_v1.method -import google.api_core.grpc_helpers -import google.api_core.operation -import google.api_core.operations_v1 -import google.api_core.protobuf_helpers -import grpc - -from google.cloud.speech_v1p1beta1.gapic import enums -from google.cloud.speech_v1p1beta1.gapic import speech_client_config -from google.cloud.speech_v1p1beta1.gapic.transports import speech_grpc_transport -from google.cloud.speech_v1p1beta1.proto import cloud_speech_pb2 -from google.cloud.speech_v1p1beta1.proto import cloud_speech_pb2_grpc -from google.longrunning import operations_pb2 - - -_GAPIC_LIBRARY_VERSION = pkg_resources.get_distribution("google-cloud-speech").version - - -class SpeechClient(object): - """Service that implements Google Cloud Speech API.""" - - SERVICE_ADDRESS = "speech.googleapis.com:443" - """The default address of the service.""" - - # The name of the interface for this client. This is the key used to - # find the method configuration in the client_config dictionary. - _INTERFACE_NAME = "google.cloud.speech.v1p1beta1.Speech" - - @classmethod - def from_service_account_file(cls, filename, *args, **kwargs): - """Creates an instance of this client using the provided credentials - file. - - Args: - filename (str): The path to the service account private key json - file. - args: Additional arguments to pass to the constructor. - kwargs: Additional arguments to pass to the constructor. - - Returns: - SpeechClient: The constructed client. - """ - credentials = service_account.Credentials.from_service_account_file(filename) - kwargs["credentials"] = credentials - return cls(*args, **kwargs) - - from_service_account_json = from_service_account_file - - def __init__( - self, - transport=None, - channel=None, - credentials=None, - client_config=None, - client_info=None, - client_options=None, - ): - """Constructor. - - Args: - transport (Union[~.SpeechGrpcTransport, - Callable[[~.Credentials, type], ~.SpeechGrpcTransport]): A transport - instance, responsible for actually making the API calls. - The default transport uses the gRPC protocol. - This argument may also be a callable which returns a - transport instance. Callables will be sent the credentials - as the first argument and the default transport class as - the second argument. - channel (grpc.Channel): DEPRECATED. A ``Channel`` instance - through which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - This argument is mutually exclusive with providing a - transport instance to ``transport``; doing so will raise - an exception. - client_config (dict): DEPRECATED. A dictionary of call options for - each method. If not specified, the default configuration is used. - client_info (google.api_core.gapic_v1.client_info.ClientInfo): - The client info used to send a user-agent string along with - API requests. If ``None``, then default info will be used. - Generally, you only need to set this if you're developing - your own client library. - client_options (Union[dict, google.api_core.client_options.ClientOptions]): - Client options used to set user options on the client. API Endpoint - should be set through client_options. - """ - # Raise deprecation warnings for things we want to go away. - if client_config is not None: - warnings.warn( - "The `client_config` argument is deprecated.", - PendingDeprecationWarning, - stacklevel=2, - ) - else: - client_config = speech_client_config.config - - if channel: - warnings.warn( - "The `channel` argument is deprecated; use " "`transport` instead.", - PendingDeprecationWarning, - stacklevel=2, - ) - - api_endpoint = self.SERVICE_ADDRESS - if client_options: - if type(client_options) == dict: - client_options = google.api_core.client_options.from_dict( - client_options - ) - if client_options.api_endpoint: - api_endpoint = client_options.api_endpoint - - # Instantiate the transport. - # The transport is responsible for handling serialization and - # deserialization and actually sending data to the service. - if transport: - if callable(transport): - self.transport = transport( - credentials=credentials, - default_class=speech_grpc_transport.SpeechGrpcTransport, - address=api_endpoint, - ) - else: - if credentials: - raise ValueError( - "Received both a transport instance and " - "credentials; these are mutually exclusive." - ) - self.transport = transport - else: - self.transport = speech_grpc_transport.SpeechGrpcTransport( - address=api_endpoint, channel=channel, credentials=credentials - ) - - if client_info is None: - client_info = google.api_core.gapic_v1.client_info.ClientInfo( - gapic_version=_GAPIC_LIBRARY_VERSION - ) - else: - client_info.gapic_version = _GAPIC_LIBRARY_VERSION - self._client_info = client_info - - # Parse out the default settings for retry and timeout for each RPC - # from the client configuration. - # (Ordinarily, these are the defaults specified in the `*_config.py` - # file next to this one.) - self._method_configs = google.api_core.gapic_v1.config.parse_method_configs( - client_config["interfaces"][self._INTERFACE_NAME] - ) - - # Save a dictionary of cached API call functions. - # These are the actual callables which invoke the proper - # transport methods, wrapped with `wrap_method` to add retry, - # timeout, and the like. - self._inner_api_calls = {} - - # Service calls - def recognize( - self, - config, - audio, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Performs synchronous speech recognition: receive results after all audio - has been sent and processed. - - Example: - >>> from google.cloud import speech_v1p1beta1 - >>> from google.cloud.speech_v1p1beta1 import enums - >>> - >>> client = speech_v1p1beta1.SpeechClient() - >>> - >>> encoding = enums.RecognitionConfig.AudioEncoding.FLAC - >>> sample_rate_hertz = 44100 - >>> language_code = 'en-US' - >>> config = {'encoding': encoding, 'sample_rate_hertz': sample_rate_hertz, 'language_code': language_code} - >>> uri = 'gs://bucket_name/file_name.flac' - >>> audio = {'uri': uri} - >>> - >>> response = client.recognize(config, audio) - - Args: - config (Union[dict, ~google.cloud.speech_v1p1beta1.types.RecognitionConfig]): Required. Provides information to the recognizer that specifies how to - process the request. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1p1beta1.types.RecognitionConfig` - audio (Union[dict, ~google.cloud.speech_v1p1beta1.types.RecognitionAudio]): Required. The audio data to be recognized. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1p1beta1.types.RecognitionAudio` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.speech_v1p1beta1.types.RecognizeResponse` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "recognize" not in self._inner_api_calls: - self._inner_api_calls[ - "recognize" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.recognize, - default_retry=self._method_configs["Recognize"].retry, - default_timeout=self._method_configs["Recognize"].timeout, - client_info=self._client_info, - ) - - request = cloud_speech_pb2.RecognizeRequest(config=config, audio=audio) - return self._inner_api_calls["recognize"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - - def long_running_recognize( - self, - config, - audio, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Performs asynchronous speech recognition: receive results via the - google.longrunning.Operations interface. Returns either an - ``Operation.error`` or an ``Operation.response`` which contains a - ``LongRunningRecognizeResponse`` message. For more information on - asynchronous speech recognition, see the - `how-to `__. - - Example: - >>> from google.cloud import speech_v1p1beta1 - >>> from google.cloud.speech_v1p1beta1 import enums - >>> - >>> client = speech_v1p1beta1.SpeechClient() - >>> - >>> encoding = enums.RecognitionConfig.AudioEncoding.FLAC - >>> sample_rate_hertz = 44100 - >>> language_code = 'en-US' - >>> config = {'encoding': encoding, 'sample_rate_hertz': sample_rate_hertz, 'language_code': language_code} - >>> uri = 'gs://bucket_name/file_name.flac' - >>> audio = {'uri': uri} - >>> - >>> response = client.long_running_recognize(config, audio) - >>> - >>> def callback(operation_future): - ... # Handle result. - ... result = operation_future.result() - >>> - >>> response.add_done_callback(callback) - >>> - >>> # Handle metadata. - >>> metadata = response.metadata() - - Args: - config (Union[dict, ~google.cloud.speech_v1p1beta1.types.RecognitionConfig]): Required. Provides information to the recognizer that specifies how to - process the request. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1p1beta1.types.RecognitionConfig` - audio (Union[dict, ~google.cloud.speech_v1p1beta1.types.RecognitionAudio]): Required. The audio data to be recognized. - - If a dict is provided, it must be of the same form as the protobuf - message :class:`~google.cloud.speech_v1p1beta1.types.RecognitionAudio` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - A :class:`~google.cloud.speech_v1p1beta1.types._OperationFuture` instance. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "long_running_recognize" not in self._inner_api_calls: - self._inner_api_calls[ - "long_running_recognize" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.long_running_recognize, - default_retry=self._method_configs["LongRunningRecognize"].retry, - default_timeout=self._method_configs["LongRunningRecognize"].timeout, - client_info=self._client_info, - ) - - request = cloud_speech_pb2.LongRunningRecognizeRequest( - config=config, audio=audio - ) - operation = self._inner_api_calls["long_running_recognize"]( - request, retry=retry, timeout=timeout, metadata=metadata - ) - return google.api_core.operation.from_gapic( - operation, - self.transport._operations_client, - cloud_speech_pb2.LongRunningRecognizeResponse, - metadata_type=cloud_speech_pb2.LongRunningRecognizeMetadata, - ) - - def streaming_recognize( - self, - requests, - retry=google.api_core.gapic_v1.method.DEFAULT, - timeout=google.api_core.gapic_v1.method.DEFAULT, - metadata=None, - ): - """ - Performs bidirectional streaming speech recognition: receive results while - sending audio. This method is only available via the gRPC API (not REST). - - EXPERIMENTAL: This method interface might change in the future. - - Example: - >>> from google.cloud import speech_v1p1beta1 - >>> - >>> client = speech_v1p1beta1.SpeechClient() - >>> - >>> request = {} - >>> - >>> requests = [request] - >>> for element in client.streaming_recognize(requests): - ... # process element - ... pass - - Args: - requests (iterator[dict|google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2.StreamingRecognizeRequest]): The input objects. If a dict is provided, it must be of the - same form as the protobuf message :class:`~google.cloud.speech_v1p1beta1.types.StreamingRecognizeRequest` - retry (Optional[google.api_core.retry.Retry]): A retry object used - to retry requests. If ``None`` is specified, requests will - be retried using a default configuration. - timeout (Optional[float]): The amount of time, in seconds, to wait - for the request to complete. Note that if ``retry`` is - specified, the timeout applies to each individual attempt. - metadata (Optional[Sequence[Tuple[str, str]]]): Additional metadata - that is provided to the method. - - Returns: - Iterable[~google.cloud.speech_v1p1beta1.types.StreamingRecognizeResponse]. - - Raises: - google.api_core.exceptions.GoogleAPICallError: If the request - failed for any reason. - google.api_core.exceptions.RetryError: If the request failed due - to a retryable error and retry attempts failed. - ValueError: If the parameters are invalid. - """ - # Wrap the transport method to add retry and timeout logic. - if "streaming_recognize" not in self._inner_api_calls: - self._inner_api_calls[ - "streaming_recognize" - ] = google.api_core.gapic_v1.method.wrap_method( - self.transport.streaming_recognize, - default_retry=self._method_configs["StreamingRecognize"].retry, - default_timeout=self._method_configs["StreamingRecognize"].timeout, - client_info=self._client_info, - ) - - return self._inner_api_calls["streaming_recognize"]( - requests, retry=retry, timeout=timeout, metadata=metadata - ) diff --git a/speech/google/cloud/speech_v1p1beta1/gapic/speech_client_config.py b/speech/google/cloud/speech_v1p1beta1/gapic/speech_client_config.py deleted file mode 100644 index c405dd03f430..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/gapic/speech_client_config.py +++ /dev/null @@ -1,38 +0,0 @@ -config = { - "interfaces": { - "google.cloud.speech.v1p1beta1.Speech": { - "retry_codes": { - "idempotent": ["DEADLINE_EXCEEDED", "UNAVAILABLE"], - "non_idempotent": [], - }, - "retry_params": { - "default": { - "initial_retry_delay_millis": 100, - "retry_delay_multiplier": 1.3, - "max_retry_delay_millis": 60000, - "initial_rpc_timeout_millis": 1000000, - "rpc_timeout_multiplier": 1.0, - "max_rpc_timeout_millis": 1000000, - "total_timeout_millis": 5000000, - } - }, - "methods": { - "Recognize": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "LongRunningRecognize": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - "StreamingRecognize": { - "timeout_millis": 60000, - "retry_codes_name": "non_idempotent", - "retry_params_name": "default", - }, - }, - } - } -} diff --git a/speech/google/cloud/speech_v1p1beta1/gapic/transports/__init__.py b/speech/google/cloud/speech_v1p1beta1/gapic/transports/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/speech/google/cloud/speech_v1p1beta1/gapic/transports/speech_grpc_transport.py b/speech/google/cloud/speech_v1p1beta1/gapic/transports/speech_grpc_transport.py deleted file mode 100644 index a8e42b09157f..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/gapic/transports/speech_grpc_transport.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import google.api_core.grpc_helpers -import google.api_core.operations_v1 - -from google.cloud.speech_v1p1beta1.proto import cloud_speech_pb2_grpc - - -class SpeechGrpcTransport(object): - """gRPC transport class providing stubs for - google.cloud.speech.v1p1beta1 Speech API. - - The transport provides access to the raw gRPC stubs, - which can be used to take advantage of advanced - features of gRPC. - """ - - # The scopes needed to make gRPC calls to all of the methods defined - # in this service. - _OAUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) - - def __init__( - self, channel=None, credentials=None, address="speech.googleapis.com:443" - ): - """Instantiate the transport class. - - Args: - channel (grpc.Channel): A ``Channel`` instance through - which to make calls. This argument is mutually exclusive - with ``credentials``; providing both will raise an exception. - credentials (google.auth.credentials.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If none - are specified, the client will attempt to ascertain the - credentials from the environment. - address (str): The address where the service is hosted. - """ - # If both `channel` and `credentials` are specified, raise an - # exception (channels come with credentials baked in already). - if channel is not None and credentials is not None: - raise ValueError( - "The `channel` and `credentials` arguments are mutually " "exclusive." - ) - - # Create the channel. - if channel is None: - channel = self.create_channel( - address=address, - credentials=credentials, - options={ - "grpc.max_send_message_length": -1, - "grpc.max_receive_message_length": -1, - }.items(), - ) - - self._channel = channel - - # gRPC uses objects called "stubs" that are bound to the - # channel and provide a basic method for each RPC. - self._stubs = {"speech_stub": cloud_speech_pb2_grpc.SpeechStub(channel)} - - # Because this API includes a method that returns a - # long-running operation (proto: google.longrunning.Operation), - # instantiate an LRO client. - self._operations_client = google.api_core.operations_v1.OperationsClient( - channel - ) - - @classmethod - def create_channel( - cls, address="speech.googleapis.com:443", credentials=None, **kwargs - ): - """Create and return a gRPC channel object. - - Args: - address (str): The host for the channel to use. - credentials (~.Credentials): The - authorization credentials to attach to requests. These - credentials identify this application to the service. If - none are specified, the client will attempt to ascertain - the credentials from the environment. - kwargs (dict): Keyword arguments, which are passed to the - channel creation. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return google.api_core.grpc_helpers.create_channel( - address, credentials=credentials, scopes=cls._OAUTH_SCOPES, **kwargs - ) - - @property - def channel(self): - """The gRPC channel used by the transport. - - Returns: - grpc.Channel: A gRPC channel object. - """ - return self._channel - - @property - def recognize(self): - """Return the gRPC stub for :meth:`SpeechClient.recognize`. - - Performs synchronous speech recognition: receive results after all audio - has been sent and processed. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["speech_stub"].Recognize - - @property - def long_running_recognize(self): - """Return the gRPC stub for :meth:`SpeechClient.long_running_recognize`. - - Performs asynchronous speech recognition: receive results via the - google.longrunning.Operations interface. Returns either an - ``Operation.error`` or an ``Operation.response`` which contains a - ``LongRunningRecognizeResponse`` message. For more information on - asynchronous speech recognition, see the - `how-to `__. - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["speech_stub"].LongRunningRecognize - - @property - def streaming_recognize(self): - """Return the gRPC stub for :meth:`SpeechClient.streaming_recognize`. - - Performs bidirectional streaming speech recognition: receive results while - sending audio. This method is only available via the gRPC API (not REST). - - Returns: - Callable: A callable which accepts the appropriate - deserialized request object and returns a - deserialized response object. - """ - return self._stubs["speech_stub"].StreamingRecognize diff --git a/speech/google/cloud/speech_v1p1beta1/proto/__init__.py b/speech/google/cloud/speech_v1p1beta1/proto/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech.proto b/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech.proto deleted file mode 100644 index 7718b0eb3cf2..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech.proto +++ /dev/null @@ -1,816 +0,0 @@ -// Copyright 2019 Google LLC. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -syntax = "proto3"; - -package google.cloud.speech.v1p1beta1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/longrunning/operations.proto"; -import "google/protobuf/any.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/timestamp.proto"; -import "google/rpc/status.proto"; - -option cc_enable_arenas = true; -option go_package = "google.golang.org/genproto/googleapis/cloud/speech/v1p1beta1;speech"; -option java_multiple_files = true; -option java_outer_classname = "SpeechProto"; -option java_package = "com.google.cloud.speech.v1p1beta1"; -option objc_class_prefix = "GCS"; - -// Service that implements Google Cloud Speech API. -service Speech { - option (google.api.default_host) = "speech.googleapis.com"; - option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform"; - - // Performs synchronous speech recognition: receive results after all audio - // has been sent and processed. - rpc Recognize(RecognizeRequest) returns (RecognizeResponse) { - option (google.api.http) = { - post: "/v1p1beta1/speech:recognize" - body: "*" - }; - option (google.api.method_signature) = "config,audio"; - } - - // Performs asynchronous speech recognition: receive results via the - // google.longrunning.Operations interface. Returns either an - // `Operation.error` or an `Operation.response` which contains - // a `LongRunningRecognizeResponse` message. - // For more information on asynchronous speech recognition, see the - // [how-to](https://cloud.google.com/speech-to-text/docs/async-recognize). - rpc LongRunningRecognize(LongRunningRecognizeRequest) returns (google.longrunning.Operation) { - option (google.api.http) = { - post: "/v1p1beta1/speech:longrunningrecognize" - body: "*" - }; - option (google.api.method_signature) = "config,audio"; - option (google.longrunning.operation_info) = { - response_type: "LongRunningRecognizeResponse" - metadata_type: "LongRunningRecognizeMetadata" - }; - } - - // Performs bidirectional streaming speech recognition: receive results while - // sending audio. This method is only available via the gRPC API (not REST). - rpc StreamingRecognize(stream StreamingRecognizeRequest) returns (stream StreamingRecognizeResponse) { - } -} - -// The top-level message sent by the client for the `Recognize` method. -message RecognizeRequest { - // Required. Provides information to the recognizer that specifies how to - // process the request. - RecognitionConfig config = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The audio data to be recognized. - RecognitionAudio audio = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// The top-level message sent by the client for the `LongRunningRecognize` -// method. -message LongRunningRecognizeRequest { - // Required. Provides information to the recognizer that specifies how to - // process the request. - RecognitionConfig config = 1 [(google.api.field_behavior) = REQUIRED]; - - // Required. The audio data to be recognized. - RecognitionAudio audio = 2 [(google.api.field_behavior) = REQUIRED]; -} - -// The top-level message sent by the client for the `StreamingRecognize` method. -// Multiple `StreamingRecognizeRequest` messages are sent. The first message -// must contain a `streaming_config` message and must not contain -// `audio_content`. All subsequent messages must contain `audio_content` and -// must not contain a `streaming_config` message. -message StreamingRecognizeRequest { - // The streaming request, which is either a streaming config or audio content. - oneof streaming_request { - // Provides information to the recognizer that specifies how to process the - // request. The first `StreamingRecognizeRequest` message must contain a - // `streaming_config` message. - StreamingRecognitionConfig streaming_config = 1; - - // The audio data to be recognized. Sequential chunks of audio data are sent - // in sequential `StreamingRecognizeRequest` messages. The first - // `StreamingRecognizeRequest` message must not contain `audio_content` data - // and all subsequent `StreamingRecognizeRequest` messages must contain - // `audio_content` data. The audio bytes must be encoded as specified in - // `RecognitionConfig`. Note: as with all bytes fields, proto buffers use a - // pure binary representation (not base64). See - // [content limits](https://cloud.google.com/speech-to-text/quotas#content). - bytes audio_content = 2; - } -} - -// Provides information to the recognizer that specifies how to process the -// request. -message StreamingRecognitionConfig { - // Required. Provides information to the recognizer that specifies how to - // process the request. - RecognitionConfig config = 1 [(google.api.field_behavior) = REQUIRED]; - - // If `false` or omitted, the recognizer will perform continuous - // recognition (continuing to wait for and process audio even if the user - // pauses speaking) until the client closes the input stream (gRPC API) or - // until the maximum time limit has been reached. May return multiple - // `StreamingRecognitionResult`s with the `is_final` flag set to `true`. - // - // If `true`, the recognizer will detect a single spoken utterance. When it - // detects that the user has paused or stopped speaking, it will return an - // `END_OF_SINGLE_UTTERANCE` event and cease recognition. It will return no - // more than one `StreamingRecognitionResult` with the `is_final` flag set to - // `true`. - bool single_utterance = 2; - - // If `true`, interim results (tentative hypotheses) may be - // returned as they become available (these interim results are indicated with - // the `is_final=false` flag). - // If `false` or omitted, only `is_final=true` result(s) are returned. - bool interim_results = 3; -} - -// Provides information to the recognizer that specifies how to process the -// request. -message RecognitionConfig { - // The encoding of the audio data sent in the request. - // - // All encodings support only 1 channel (mono) audio, unless the - // `audio_channel_count` and `enable_separate_recognition_per_channel` fields - // are set. - // - // For best results, the audio source should be captured and transmitted using - // a lossless encoding (`FLAC` or `LINEAR16`). The accuracy of the speech - // recognition can be reduced if lossy codecs are used to capture or transmit - // audio, particularly if background noise is present. Lossy codecs include - // `MULAW`, `AMR`, `AMR_WB`, `OGG_OPUS`, `SPEEX_WITH_HEADER_BYTE`, and `MP3`. - // - // The `FLAC` and `WAV` audio file formats include a header that describes the - // included audio content. You can request recognition for `WAV` files that - // contain either `LINEAR16` or `MULAW` encoded audio. - // If you send `FLAC` or `WAV` audio file format in - // your request, you do not need to specify an `AudioEncoding`; the audio - // encoding format is determined from the file header. If you specify - // an `AudioEncoding` when you send send `FLAC` or `WAV` audio, the - // encoding configuration must match the encoding described in the audio - // header; otherwise the request returns an - // [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT] error code. - enum AudioEncoding { - // Not specified. - ENCODING_UNSPECIFIED = 0; - - // Uncompressed 16-bit signed little-endian samples (Linear PCM). - LINEAR16 = 1; - - // `FLAC` (Free Lossless Audio - // Codec) is the recommended encoding because it is - // lossless--therefore recognition is not compromised--and - // requires only about half the bandwidth of `LINEAR16`. `FLAC` stream - // encoding supports 16-bit and 24-bit samples, however, not all fields in - // `STREAMINFO` are supported. - FLAC = 2; - - // 8-bit samples that compand 14-bit audio samples using G.711 PCMU/mu-law. - MULAW = 3; - - // Adaptive Multi-Rate Narrowband codec. `sample_rate_hertz` must be 8000. - AMR = 4; - - // Adaptive Multi-Rate Wideband codec. `sample_rate_hertz` must be 16000. - AMR_WB = 5; - - // Opus encoded audio frames in Ogg container - // ([OggOpus](https://wiki.xiph.org/OggOpus)). - // `sample_rate_hertz` must be one of 8000, 12000, 16000, 24000, or 48000. - OGG_OPUS = 6; - - // Although the use of lossy encodings is not recommended, if a very low - // bitrate encoding is required, `OGG_OPUS` is highly preferred over - // Speex encoding. The [Speex](https://speex.org/) encoding supported by - // Cloud Speech API has a header byte in each block, as in MIME type - // `audio/x-speex-with-header-byte`. - // It is a variant of the RTP Speex encoding defined in - // [RFC 5574](https://tools.ietf.org/html/rfc5574). - // The stream is a sequence of blocks, one block per RTP packet. Each block - // starts with a byte containing the length of the block, in bytes, followed - // by one or more frames of Speex data, padded to an integral number of - // bytes (octets) as specified in RFC 5574. In other words, each RTP header - // is replaced with a single byte containing the block length. Only Speex - // wideband is supported. `sample_rate_hertz` must be 16000. - SPEEX_WITH_HEADER_BYTE = 7; - - // MP3 audio. Support all standard MP3 bitrates (which range from 32-320 - // kbps). When using this encoding, `sample_rate_hertz` can be optionally - // unset if not known. - MP3 = 8; - } - - // Encoding of audio data sent in all `RecognitionAudio` messages. - // This field is optional for `FLAC` and `WAV` audio files and required - // for all other audio formats. For details, see [AudioEncoding][google.cloud.speech.v1p1beta1.RecognitionConfig.AudioEncoding]. - AudioEncoding encoding = 1; - - // Sample rate in Hertz of the audio data sent in all - // `RecognitionAudio` messages. Valid values are: 8000-48000. - // 16000 is optimal. For best results, set the sampling rate of the audio - // source to 16000 Hz. If that's not possible, use the native sample rate of - // the audio source (instead of re-sampling). - // This field is optional for FLAC and WAV audio files, but is - // required for all other audio formats. For details, see [AudioEncoding][google.cloud.speech.v1p1beta1.RecognitionConfig.AudioEncoding]. - int32 sample_rate_hertz = 2; - - // The number of channels in the input audio data. - // ONLY set this for MULTI-CHANNEL recognition. - // Valid values for LINEAR16 and FLAC are `1`-`8`. - // Valid values for OGG_OPUS are '1'-'254'. - // Valid value for MULAW, AMR, AMR_WB and SPEEX_WITH_HEADER_BYTE is only `1`. - // If `0` or omitted, defaults to one channel (mono). - // Note: We only recognize the first channel by default. - // To perform independent recognition on each channel set - // `enable_separate_recognition_per_channel` to 'true'. - int32 audio_channel_count = 7; - - // This needs to be set to `true` explicitly and `audio_channel_count` > 1 - // to get each channel recognized separately. The recognition result will - // contain a `channel_tag` field to state which channel that result belongs - // to. If this is not true, we will only recognize the first channel. The - // request is billed cumulatively for all channels recognized: - // `audio_channel_count` multiplied by the length of the audio. - bool enable_separate_recognition_per_channel = 12; - - // Required. The language of the supplied audio as a - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag. - // Example: "en-US". - // See [Language - // Support](https://cloud.google.com/speech-to-text/docs/languages) for a list - // of the currently supported language codes. - string language_code = 3 [(google.api.field_behavior) = REQUIRED]; - - // A list of up to 3 additional - // [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tags, - // listing possible alternative languages of the supplied audio. - // See [Language - // Support](https://cloud.google.com/speech-to-text/docs/languages) for a list - // of the currently supported language codes. If alternative languages are - // listed, recognition result will contain recognition in the most likely - // language detected including the main language_code. The recognition result - // will include the language tag of the language detected in the audio. Note: - // This feature is only supported for Voice Command and Voice Search use cases - // and performance may vary for other use cases (e.g., phone call - // transcription). - repeated string alternative_language_codes = 18; - - // Maximum number of recognition hypotheses to be returned. - // Specifically, the maximum number of `SpeechRecognitionAlternative` messages - // within each `SpeechRecognitionResult`. - // The server may return fewer than `max_alternatives`. - // Valid values are `0`-`30`. A value of `0` or `1` will return a maximum of - // one. If omitted, will return a maximum of one. - int32 max_alternatives = 4; - - // If set to `true`, the server will attempt to filter out - // profanities, replacing all but the initial character in each filtered word - // with asterisks, e.g. "f***". If set to `false` or omitted, profanities - // won't be filtered out. - bool profanity_filter = 5; - - // Array of [SpeechContext][google.cloud.speech.v1p1beta1.SpeechContext]. - // A means to provide context to assist the speech recognition. For more - // information, see - // [speech - // adaptation](https://cloud.google.com/speech-to-text/docs/context-strength). - repeated SpeechContext speech_contexts = 6; - - // If `true`, the top result includes a list of words and - // the start and end time offsets (timestamps) for those words. If - // `false`, no word-level time offset information is returned. The default is - // `false`. - bool enable_word_time_offsets = 8; - - // If `true`, the top result includes a list of words and the - // confidence for those words. If `false`, no word-level confidence - // information is returned. The default is `false`. - bool enable_word_confidence = 15; - - // If 'true', adds punctuation to recognition result hypotheses. - // This feature is only available in select languages. Setting this for - // requests in other languages has no effect at all. - // The default 'false' value does not add punctuation to result hypotheses. - // Note: This is currently offered as an experimental service, complimentary - // to all users. In the future this may be exclusively available as a - // premium feature. - bool enable_automatic_punctuation = 11; - - // If 'true', enables speaker detection for each recognized word in - // the top alternative of the recognition result using a speaker_tag provided - // in the WordInfo. - // Note: Use diarization_config instead. - bool enable_speaker_diarization = 16 [deprecated = true]; - - // If set, specifies the estimated number of speakers in the conversation. - // Defaults to '2'. Ignored unless enable_speaker_diarization is set to true. - // Note: Use diarization_config instead. - int32 diarization_speaker_count = 17 [deprecated = true]; - - // Config to enable speaker diarization and set additional - // parameters to make diarization better suited for your application. - // Note: When this is enabled, we send all the words from the beginning of the - // audio for the top alternative in every consecutive STREAMING responses. - // This is done in order to improve our speaker tags as our models learn to - // identify the speakers in the conversation over time. - // For non-streaming requests, the diarization results will be provided only - // in the top alternative of the FINAL SpeechRecognitionResult. - SpeakerDiarizationConfig diarization_config = 19; - - // Metadata regarding this request. - RecognitionMetadata metadata = 9; - - // Which model to select for the given request. Select the model - // best suited to your domain to get best results. If a model is not - // explicitly specified, then we auto-select a model based on the parameters - // in the RecognitionConfig. - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - // - //
ModelDescription
command_and_searchBest for short queries such as voice commands or voice search.
phone_callBest for audio that originated from a phone call (typically - // recorded at an 8khz sampling rate).
videoBest for audio that originated from from video or includes multiple - // speakers. Ideally the audio is recorded at a 16khz or greater - // sampling rate. This is a premium model that costs more than the - // standard rate.
defaultBest for audio that is not one of the specific audio models. - // For example, long-form audio. Ideally the audio is high-fidelity, - // recorded at a 16khz or greater sampling rate.
- string model = 13; - - // Set to true to use an enhanced model for speech recognition. - // If `use_enhanced` is set to true and the `model` field is not set, then - // an appropriate enhanced model is chosen if an enhanced model exists for - // the audio. - // - // If `use_enhanced` is true and an enhanced version of the specified model - // does not exist, then the speech is recognized using the standard version - // of the specified model. - bool use_enhanced = 14; -} - -// Config to enable speaker diarization. -message SpeakerDiarizationConfig { - // If 'true', enables speaker detection for each recognized word in - // the top alternative of the recognition result using a speaker_tag provided - // in the WordInfo. - bool enable_speaker_diarization = 1; - - // Minimum number of speakers in the conversation. This range gives you more - // flexibility by allowing the system to automatically determine the correct - // number of speakers. If not set, the default value is 2. - int32 min_speaker_count = 2; - - // Maximum number of speakers in the conversation. This range gives you more - // flexibility by allowing the system to automatically determine the correct - // number of speakers. If not set, the default value is 6. - int32 max_speaker_count = 3; -} - -// Description of audio data to be recognized. -message RecognitionMetadata { - // Use case categories that the audio recognition request can be described - // by. - enum InteractionType { - // Use case is either unknown or is something other than one of the other - // values below. - INTERACTION_TYPE_UNSPECIFIED = 0; - - // Multiple people in a conversation or discussion. For example in a - // meeting with two or more people actively participating. Typically - // all the primary people speaking would be in the same room (if not, - // see PHONE_CALL) - DISCUSSION = 1; - - // One or more persons lecturing or presenting to others, mostly - // uninterrupted. - PRESENTATION = 2; - - // A phone-call or video-conference in which two or more people, who are - // not in the same room, are actively participating. - PHONE_CALL = 3; - - // A recorded message intended for another person to listen to. - VOICEMAIL = 4; - - // Professionally produced audio (eg. TV Show, Podcast). - PROFESSIONALLY_PRODUCED = 5; - - // Transcribe spoken questions and queries into text. - VOICE_SEARCH = 6; - - // Transcribe voice commands, such as for controlling a device. - VOICE_COMMAND = 7; - - // Transcribe speech to text to create a written document, such as a - // text-message, email or report. - DICTATION = 8; - } - - // Enumerates the types of capture settings describing an audio file. - enum MicrophoneDistance { - // Audio type is not known. - MICROPHONE_DISTANCE_UNSPECIFIED = 0; - - // The audio was captured from a closely placed microphone. Eg. phone, - // dictaphone, or handheld microphone. Generally if there speaker is within - // 1 meter of the microphone. - NEARFIELD = 1; - - // The speaker if within 3 meters of the microphone. - MIDFIELD = 2; - - // The speaker is more than 3 meters away from the microphone. - FARFIELD = 3; - } - - // The original media the speech was recorded on. - enum OriginalMediaType { - // Unknown original media type. - ORIGINAL_MEDIA_TYPE_UNSPECIFIED = 0; - - // The speech data is an audio recording. - AUDIO = 1; - - // The speech data originally recorded on a video. - VIDEO = 2; - } - - // The type of device the speech was recorded with. - enum RecordingDeviceType { - // The recording device is unknown. - RECORDING_DEVICE_TYPE_UNSPECIFIED = 0; - - // Speech was recorded on a smartphone. - SMARTPHONE = 1; - - // Speech was recorded using a personal computer or tablet. - PC = 2; - - // Speech was recorded over a phone line. - PHONE_LINE = 3; - - // Speech was recorded in a vehicle. - VEHICLE = 4; - - // Speech was recorded outdoors. - OTHER_OUTDOOR_DEVICE = 5; - - // Speech was recorded indoors. - OTHER_INDOOR_DEVICE = 6; - } - - // The use case most closely describing the audio content to be recognized. - InteractionType interaction_type = 1; - - // The industry vertical to which this speech recognition request most - // closely applies. This is most indicative of the topics contained - // in the audio. Use the 6-digit NAICS code to identify the industry - // vertical - see https://www.naics.com/search/. - uint32 industry_naics_code_of_audio = 3; - - // The audio type that most closely describes the audio being recognized. - MicrophoneDistance microphone_distance = 4; - - // The original media the speech was recorded on. - OriginalMediaType original_media_type = 5; - - // The type of device the speech was recorded with. - RecordingDeviceType recording_device_type = 6; - - // The device used to make the recording. Examples 'Nexus 5X' or - // 'Polycom SoundStation IP 6000' or 'POTS' or 'VoIP' or - // 'Cardioid Microphone'. - string recording_device_name = 7; - - // Mime type of the original audio file. For example `audio/m4a`, - // `audio/x-alaw-basic`, `audio/mp3`, `audio/3gpp`. - // A list of possible audio mime types is maintained at - // http://www.iana.org/assignments/media-types/media-types.xhtml#audio - string original_mime_type = 8; - - // Obfuscated (privacy-protected) ID of the user, to identify number of - // unique users using the service. - int64 obfuscated_id = 9 [deprecated = true]; - - // Description of the content. Eg. "Recordings of federal supreme court - // hearings from 2012". - string audio_topic = 10; -} - -// Provides "hints" to the speech recognizer to favor specific words and phrases -// in the results. -message SpeechContext { - // A list of strings containing words and phrases "hints" so that - // the speech recognition is more likely to recognize them. This can be used - // to improve the accuracy for specific words and phrases, for example, if - // specific commands are typically spoken by the user. This can also be used - // to add additional words to the vocabulary of the recognizer. See - // [usage limits](https://cloud.google.com/speech-to-text/quotas#content). - // - // List items can also be set to classes for groups of words that represent - // common concepts that occur in natural language. For example, rather than - // providing phrase hints for every month of the year, using the $MONTH class - // improves the likelihood of correctly transcribing audio that includes - // months. - repeated string phrases = 1; - - // Hint Boost. Positive value will increase the probability that a specific - // phrase will be recognized over other similar sounding phrases. The higher - // the boost, the higher the chance of false positive recognition as well. - // Negative boost values would correspond to anti-biasing. Anti-biasing is not - // enabled, so negative boost will simply be ignored. Though `boost` can - // accept a wide range of positive values, most use cases are best served with - // values between 0 and 20. We recommend using a binary search approach to - // finding the optimal value for your use case. - float boost = 4; -} - -// Contains audio data in the encoding specified in the `RecognitionConfig`. -// Either `content` or `uri` must be supplied. Supplying both or neither -// returns [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]. See -// [content limits](https://cloud.google.com/speech-to-text/quotas#content). -message RecognitionAudio { - // The audio source, which is either inline content or a Google Cloud - // Storage uri. - oneof audio_source { - // The audio data bytes encoded as specified in - // `RecognitionConfig`. Note: as with all bytes fields, proto buffers use a - // pure binary representation, whereas JSON representations use base64. - bytes content = 1; - - // URI that points to a file that contains audio data bytes as specified in - // `RecognitionConfig`. The file must not be compressed (for example, gzip). - // Currently, only Google Cloud Storage URIs are - // supported, which must be specified in the following format: - // `gs://bucket_name/object_name` (other URI formats return - // [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]). For more information, see - // [Request URIs](https://cloud.google.com/storage/docs/reference-uris). - string uri = 2; - } -} - -// The only message returned to the client by the `Recognize` method. It -// contains the result as zero or more sequential `SpeechRecognitionResult` -// messages. -message RecognizeResponse { - // Sequential list of transcription results corresponding to - // sequential portions of audio. - repeated SpeechRecognitionResult results = 2; -} - -// The only message returned to the client by the `LongRunningRecognize` method. -// It contains the result as zero or more sequential `SpeechRecognitionResult` -// messages. It is included in the `result.response` field of the `Operation` -// returned by the `GetOperation` call of the `google::longrunning::Operations` -// service. -message LongRunningRecognizeResponse { - // Sequential list of transcription results corresponding to - // sequential portions of audio. - repeated SpeechRecognitionResult results = 2; -} - -// Describes the progress of a long-running `LongRunningRecognize` call. It is -// included in the `metadata` field of the `Operation` returned by the -// `GetOperation` call of the `google::longrunning::Operations` service. -message LongRunningRecognizeMetadata { - // Approximate percentage of audio processed thus far. Guaranteed to be 100 - // when the audio is fully processed and the results are available. - int32 progress_percent = 1; - - // Time when the request was received. - google.protobuf.Timestamp start_time = 2; - - // Time of the most recent processing update. - google.protobuf.Timestamp last_update_time = 3; -} - -// `StreamingRecognizeResponse` is the only message returned to the client by -// `StreamingRecognize`. A series of zero or more `StreamingRecognizeResponse` -// messages are streamed back to the client. If there is no recognizable -// audio, and `single_utterance` is set to false, then no messages are streamed -// back to the client. -// -// Here's an example of a series of ten `StreamingRecognizeResponse`s that might -// be returned while processing audio: -// -// 1. results { alternatives { transcript: "tube" } stability: 0.01 } -// -// 2. results { alternatives { transcript: "to be a" } stability: 0.01 } -// -// 3. results { alternatives { transcript: "to be" } stability: 0.9 } -// results { alternatives { transcript: " or not to be" } stability: 0.01 } -// -// 4. results { alternatives { transcript: "to be or not to be" -// confidence: 0.92 } -// alternatives { transcript: "to bee or not to bee" } -// is_final: true } -// -// 5. results { alternatives { transcript: " that's" } stability: 0.01 } -// -// 6. results { alternatives { transcript: " that is" } stability: 0.9 } -// results { alternatives { transcript: " the question" } stability: 0.01 } -// -// 7. results { alternatives { transcript: " that is the question" -// confidence: 0.98 } -// alternatives { transcript: " that was the question" } -// is_final: true } -// -// Notes: -// -// - Only two of the above responses #4 and #7 contain final results; they are -// indicated by `is_final: true`. Concatenating these together generates the -// full transcript: "to be or not to be that is the question". -// -// - The others contain interim `results`. #3 and #6 contain two interim -// `results`: the first portion has a high stability and is less likely to -// change; the second portion has a low stability and is very likely to -// change. A UI designer might choose to show only high stability `results`. -// -// - The specific `stability` and `confidence` values shown above are only for -// illustrative purposes. Actual values may vary. -// -// - In each response, only one of these fields will be set: -// `error`, -// `speech_event_type`, or -// one or more (repeated) `results`. -message StreamingRecognizeResponse { - // Indicates the type of speech event. - enum SpeechEventType { - // No speech event specified. - SPEECH_EVENT_UNSPECIFIED = 0; - - // This event indicates that the server has detected the end of the user's - // speech utterance and expects no additional speech. Therefore, the server - // will not process additional audio (although it may subsequently return - // additional results). The client should stop sending additional audio - // data, half-close the gRPC connection, and wait for any additional results - // until the server closes the gRPC connection. This event is only sent if - // `single_utterance` was set to `true`, and is not used otherwise. - END_OF_SINGLE_UTTERANCE = 1; - } - - // If set, returns a [google.rpc.Status][google.rpc.Status] message that - // specifies the error for the operation. - google.rpc.Status error = 1; - - // This repeated list contains zero or more results that - // correspond to consecutive portions of the audio currently being processed. - // It contains zero or one `is_final=true` result (the newly settled portion), - // followed by zero or more `is_final=false` results (the interim results). - repeated StreamingRecognitionResult results = 2; - - // Indicates the type of speech event. - SpeechEventType speech_event_type = 4; -} - -// A streaming speech recognition result corresponding to a portion of the audio -// that is currently being processed. -message StreamingRecognitionResult { - // May contain one or more recognition hypotheses (up to the - // maximum specified in `max_alternatives`). - // These alternatives are ordered in terms of accuracy, with the top (first) - // alternative being the most probable, as ranked by the recognizer. - repeated SpeechRecognitionAlternative alternatives = 1; - - // If `false`, this `StreamingRecognitionResult` represents an - // interim result that may change. If `true`, this is the final time the - // speech service will return this particular `StreamingRecognitionResult`, - // the recognizer will not return any further hypotheses for this portion of - // the transcript and corresponding audio. - bool is_final = 2; - - // An estimate of the likelihood that the recognizer will not - // change its guess about this interim result. Values range from 0.0 - // (completely unstable) to 1.0 (completely stable). - // This field is only provided for interim results (`is_final=false`). - // The default of 0.0 is a sentinel value indicating `stability` was not set. - float stability = 3; - - // Time offset of the end of this result relative to the - // beginning of the audio. - google.protobuf.Duration result_end_time = 4; - - // For multi-channel audio, this is the channel number corresponding to the - // recognized result for the audio from that channel. - // For audio_channel_count = N, its output values can range from '1' to 'N'. - int32 channel_tag = 5; - - // The [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag - // of the language in this result. This language code was detected to have - // the most likelihood of being spoken in the audio. - string language_code = 6; -} - -// A speech recognition result corresponding to a portion of the audio. -message SpeechRecognitionResult { - // May contain one or more recognition hypotheses (up to the - // maximum specified in `max_alternatives`). - // These alternatives are ordered in terms of accuracy, with the top (first) - // alternative being the most probable, as ranked by the recognizer. - repeated SpeechRecognitionAlternative alternatives = 1; - - // For multi-channel audio, this is the channel number corresponding to the - // recognized result for the audio from that channel. - // For audio_channel_count = N, its output values can range from '1' to 'N'. - int32 channel_tag = 2; - - // The [BCP-47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt) language tag - // of the language in this result. This language code was detected to have - // the most likelihood of being spoken in the audio. - string language_code = 5; -} - -// Alternative hypotheses (a.k.a. n-best list). -message SpeechRecognitionAlternative { - // Transcript text representing the words that the user spoke. - string transcript = 1; - - // The confidence estimate between 0.0 and 1.0. A higher number - // indicates an estimated greater likelihood that the recognized words are - // correct. This field is set only for the top alternative of a non-streaming - // result or, of a streaming result where `is_final=true`. - // This field is not guaranteed to be accurate and users should not rely on it - // to be always provided. - // The default of 0.0 is a sentinel value indicating `confidence` was not set. - float confidence = 2; - - // A list of word-specific information for each recognized word. - // Note: When `enable_speaker_diarization` is true, you will see all the words - // from the beginning of the audio. - repeated WordInfo words = 3; -} - -// Word-specific information for recognized words. -message WordInfo { - // Time offset relative to the beginning of the audio, - // and corresponding to the start of the spoken word. - // This field is only set if `enable_word_time_offsets=true` and only - // in the top hypothesis. - // This is an experimental feature and the accuracy of the time offset can - // vary. - google.protobuf.Duration start_time = 1; - - // Time offset relative to the beginning of the audio, - // and corresponding to the end of the spoken word. - // This field is only set if `enable_word_time_offsets=true` and only - // in the top hypothesis. - // This is an experimental feature and the accuracy of the time offset can - // vary. - google.protobuf.Duration end_time = 2; - - // The word corresponding to this set of information. - string word = 3; - - // The confidence estimate between 0.0 and 1.0. A higher number - // indicates an estimated greater likelihood that the recognized words are - // correct. This field is set only for the top alternative of a non-streaming - // result or, of a streaming result where `is_final=true`. - // This field is not guaranteed to be accurate and users should not rely on it - // to be always provided. - // The default of 0.0 is a sentinel value indicating `confidence` was not set. - float confidence = 4; - - // A distinct integer value is assigned for every speaker within - // the audio. This field specifies which one of those speakers was detected to - // have spoken this word. Value ranges from '1' to diarization_speaker_count. - // speaker_tag is set if enable_speaker_diarization = 'true' and only in the - // top alternative. - int32 speaker_tag = 5; -} diff --git a/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2.py b/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2.py deleted file mode 100644 index 1fd8de4ffbe8..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2.py +++ /dev/null @@ -1,2823 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: google/cloud/speech_v1p1beta1/proto/cloud_speech.proto - -import sys - -_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database - -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - -from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2 -from google.api import client_pb2 as google_dot_api_dot_client__pb2 -from google.api import field_behavior_pb2 as google_dot_api_dot_field__behavior__pb2 -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) -from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 -from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 -from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -from google.rpc import status_pb2 as google_dot_rpc_dot_status__pb2 - - -DESCRIPTOR = _descriptor.FileDescriptor( - name="google/cloud/speech_v1p1beta1/proto/cloud_speech.proto", - package="google.cloud.speech.v1p1beta1", - syntax="proto3", - serialized_options=_b( - "\n!com.google.cloud.speech.v1p1beta1B\013SpeechProtoP\001ZCgoogle.golang.org/genproto/googleapis/cloud/speech/v1p1beta1;speech\370\001\001\242\002\003GCS" - ), - serialized_pb=_b( - '\n6google/cloud/speech_v1p1beta1/proto/cloud_speech.proto\x12\x1dgoogle.cloud.speech.v1p1beta1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a#google/longrunning/operations.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17google/rpc/status.proto"\x9e\x01\n\x10RecognizeRequest\x12\x45\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x30.google.cloud.speech.v1p1beta1.RecognitionConfigB\x03\xe0\x41\x02\x12\x43\n\x05\x61udio\x18\x02 \x01(\x0b\x32/.google.cloud.speech.v1p1beta1.RecognitionAudioB\x03\xe0\x41\x02"\xa9\x01\n\x1bLongRunningRecognizeRequest\x12\x45\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x30.google.cloud.speech.v1p1beta1.RecognitionConfigB\x03\xe0\x41\x02\x12\x43\n\x05\x61udio\x18\x02 \x01(\x0b\x32/.google.cloud.speech.v1p1beta1.RecognitionAudioB\x03\xe0\x41\x02"\xa0\x01\n\x19StreamingRecognizeRequest\x12U\n\x10streaming_config\x18\x01 \x01(\x0b\x32\x39.google.cloud.speech.v1p1beta1.StreamingRecognitionConfigH\x00\x12\x17\n\raudio_content\x18\x02 \x01(\x0cH\x00\x42\x13\n\x11streaming_request"\x96\x01\n\x1aStreamingRecognitionConfig\x12\x45\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x30.google.cloud.speech.v1p1beta1.RecognitionConfigB\x03\xe0\x41\x02\x12\x18\n\x10single_utterance\x18\x02 \x01(\x08\x12\x17\n\x0finterim_results\x18\x03 \x01(\x08"\x97\x07\n\x11RecognitionConfig\x12P\n\x08\x65ncoding\x18\x01 \x01(\x0e\x32>.google.cloud.speech.v1p1beta1.RecognitionConfig.AudioEncoding\x12\x19\n\x11sample_rate_hertz\x18\x02 \x01(\x05\x12\x1b\n\x13\x61udio_channel_count\x18\x07 \x01(\x05\x12/\n\'enable_separate_recognition_per_channel\x18\x0c \x01(\x08\x12\x1a\n\rlanguage_code\x18\x03 \x01(\tB\x03\xe0\x41\x02\x12"\n\x1a\x61lternative_language_codes\x18\x12 \x03(\t\x12\x18\n\x10max_alternatives\x18\x04 \x01(\x05\x12\x18\n\x10profanity_filter\x18\x05 \x01(\x08\x12\x45\n\x0fspeech_contexts\x18\x06 \x03(\x0b\x32,.google.cloud.speech.v1p1beta1.SpeechContext\x12 \n\x18\x65nable_word_time_offsets\x18\x08 \x01(\x08\x12\x1e\n\x16\x65nable_word_confidence\x18\x0f \x01(\x08\x12$\n\x1c\x65nable_automatic_punctuation\x18\x0b \x01(\x08\x12&\n\x1a\x65nable_speaker_diarization\x18\x10 \x01(\x08\x42\x02\x18\x01\x12%\n\x19\x64iarization_speaker_count\x18\x11 \x01(\x05\x42\x02\x18\x01\x12S\n\x12\x64iarization_config\x18\x13 \x01(\x0b\x32\x37.google.cloud.speech.v1p1beta1.SpeakerDiarizationConfig\x12\x44\n\x08metadata\x18\t \x01(\x0b\x32\x32.google.cloud.speech.v1p1beta1.RecognitionMetadata\x12\r\n\x05model\x18\r \x01(\t\x12\x14\n\x0cuse_enhanced\x18\x0e \x01(\x08"\x94\x01\n\rAudioEncoding\x12\x18\n\x14\x45NCODING_UNSPECIFIED\x10\x00\x12\x0c\n\x08LINEAR16\x10\x01\x12\x08\n\x04\x46LAC\x10\x02\x12\t\n\x05MULAW\x10\x03\x12\x07\n\x03\x41MR\x10\x04\x12\n\n\x06\x41MR_WB\x10\x05\x12\x0c\n\x08OGG_OPUS\x10\x06\x12\x1a\n\x16SPEEX_WITH_HEADER_BYTE\x10\x07\x12\x07\n\x03MP3\x10\x08"t\n\x18SpeakerDiarizationConfig\x12"\n\x1a\x65nable_speaker_diarization\x18\x01 \x01(\x08\x12\x19\n\x11min_speaker_count\x18\x02 \x01(\x05\x12\x19\n\x11max_speaker_count\x18\x03 \x01(\x05"\xd7\x08\n\x13RecognitionMetadata\x12\\\n\x10interaction_type\x18\x01 \x01(\x0e\x32\x42.google.cloud.speech.v1p1beta1.RecognitionMetadata.InteractionType\x12$\n\x1cindustry_naics_code_of_audio\x18\x03 \x01(\r\x12\x62\n\x13microphone_distance\x18\x04 \x01(\x0e\x32\x45.google.cloud.speech.v1p1beta1.RecognitionMetadata.MicrophoneDistance\x12\x61\n\x13original_media_type\x18\x05 \x01(\x0e\x32\x44.google.cloud.speech.v1p1beta1.RecognitionMetadata.OriginalMediaType\x12\x65\n\x15recording_device_type\x18\x06 \x01(\x0e\x32\x46.google.cloud.speech.v1p1beta1.RecognitionMetadata.RecordingDeviceType\x12\x1d\n\x15recording_device_name\x18\x07 \x01(\t\x12\x1a\n\x12original_mime_type\x18\x08 \x01(\t\x12\x19\n\robfuscated_id\x18\t \x01(\x03\x42\x02\x18\x01\x12\x13\n\x0b\x61udio_topic\x18\n \x01(\t"\xc5\x01\n\x0fInteractionType\x12 \n\x1cINTERACTION_TYPE_UNSPECIFIED\x10\x00\x12\x0e\n\nDISCUSSION\x10\x01\x12\x10\n\x0cPRESENTATION\x10\x02\x12\x0e\n\nPHONE_CALL\x10\x03\x12\r\n\tVOICEMAIL\x10\x04\x12\x1b\n\x17PROFESSIONALLY_PRODUCED\x10\x05\x12\x10\n\x0cVOICE_SEARCH\x10\x06\x12\x11\n\rVOICE_COMMAND\x10\x07\x12\r\n\tDICTATION\x10\x08"d\n\x12MicrophoneDistance\x12#\n\x1fMICROPHONE_DISTANCE_UNSPECIFIED\x10\x00\x12\r\n\tNEARFIELD\x10\x01\x12\x0c\n\x08MIDFIELD\x10\x02\x12\x0c\n\x08\x46\x41RFIELD\x10\x03"N\n\x11OriginalMediaType\x12#\n\x1fORIGINAL_MEDIA_TYPE_UNSPECIFIED\x10\x00\x12\t\n\x05\x41UDIO\x10\x01\x12\t\n\x05VIDEO\x10\x02"\xa4\x01\n\x13RecordingDeviceType\x12%\n!RECORDING_DEVICE_TYPE_UNSPECIFIED\x10\x00\x12\x0e\n\nSMARTPHONE\x10\x01\x12\x06\n\x02PC\x10\x02\x12\x0e\n\nPHONE_LINE\x10\x03\x12\x0b\n\x07VEHICLE\x10\x04\x12\x18\n\x14OTHER_OUTDOOR_DEVICE\x10\x05\x12\x17\n\x13OTHER_INDOOR_DEVICE\x10\x06"/\n\rSpeechContext\x12\x0f\n\x07phrases\x18\x01 \x03(\t\x12\r\n\x05\x62oost\x18\x04 \x01(\x02"D\n\x10RecognitionAudio\x12\x11\n\x07\x63ontent\x18\x01 \x01(\x0cH\x00\x12\r\n\x03uri\x18\x02 \x01(\tH\x00\x42\x0e\n\x0c\x61udio_source"\\\n\x11RecognizeResponse\x12G\n\x07results\x18\x02 \x03(\x0b\x32\x36.google.cloud.speech.v1p1beta1.SpeechRecognitionResult"g\n\x1cLongRunningRecognizeResponse\x12G\n\x07results\x18\x02 \x03(\x0b\x32\x36.google.cloud.speech.v1p1beta1.SpeechRecognitionResult"\x9e\x01\n\x1cLongRunningRecognizeMetadata\x12\x18\n\x10progress_percent\x18\x01 \x01(\x05\x12.\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x34\n\x10last_update_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp"\xbf\x02\n\x1aStreamingRecognizeResponse\x12!\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x12.google.rpc.Status\x12J\n\x07results\x18\x02 \x03(\x0b\x32\x39.google.cloud.speech.v1p1beta1.StreamingRecognitionResult\x12\x64\n\x11speech_event_type\x18\x04 \x01(\x0e\x32I.google.cloud.speech.v1p1beta1.StreamingRecognizeResponse.SpeechEventType"L\n\x0fSpeechEventType\x12\x1c\n\x18SPEECH_EVENT_UNSPECIFIED\x10\x00\x12\x1b\n\x17\x45ND_OF_SINGLE_UTTERANCE\x10\x01"\xf4\x01\n\x1aStreamingRecognitionResult\x12Q\n\x0c\x61lternatives\x18\x01 \x03(\x0b\x32;.google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative\x12\x10\n\x08is_final\x18\x02 \x01(\x08\x12\x11\n\tstability\x18\x03 \x01(\x02\x12\x32\n\x0fresult_end_time\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x13\n\x0b\x63hannel_tag\x18\x05 \x01(\x05\x12\x15\n\rlanguage_code\x18\x06 \x01(\t"\x98\x01\n\x17SpeechRecognitionResult\x12Q\n\x0c\x61lternatives\x18\x01 \x03(\x0b\x32;.google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative\x12\x13\n\x0b\x63hannel_tag\x18\x02 \x01(\x05\x12\x15\n\rlanguage_code\x18\x05 \x01(\t"~\n\x1cSpeechRecognitionAlternative\x12\x12\n\ntranscript\x18\x01 \x01(\t\x12\x12\n\nconfidence\x18\x02 \x01(\x02\x12\x36\n\x05words\x18\x03 \x03(\x0b\x32\'.google.cloud.speech.v1p1beta1.WordInfo"\x9d\x01\n\x08WordInfo\x12-\n\nstart_time\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12+\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0c\n\x04word\x18\x03 \x01(\t\x12\x12\n\nconfidence\x18\x04 \x01(\x02\x12\x13\n\x0bspeaker_tag\x18\x05 \x01(\x05\x32\x82\x05\n\x06Speech\x12\xa5\x01\n\tRecognize\x12/.google.cloud.speech.v1p1beta1.RecognizeRequest\x1a\x30.google.cloud.speech.v1p1beta1.RecognizeResponse"5\x82\xd3\xe4\x93\x02 "\x1b/v1p1beta1/speech:recognize:\x01*\xda\x41\x0c\x63onfig,audio\x12\xf2\x01\n\x14LongRunningRecognize\x12:.google.cloud.speech.v1p1beta1.LongRunningRecognizeRequest\x1a\x1d.google.longrunning.Operation"\x7f\x82\xd3\xe4\x93\x02+"&/v1p1beta1/speech:longrunningrecognize:\x01*\xda\x41\x0c\x63onfig,audio\xca\x41<\n\x1cLongRunningRecognizeResponse\x12\x1cLongRunningRecognizeMetadata\x12\x8f\x01\n\x12StreamingRecognize\x12\x38.google.cloud.speech.v1p1beta1.StreamingRecognizeRequest\x1a\x39.google.cloud.speech.v1p1beta1.StreamingRecognizeResponse"\x00(\x01\x30\x01\x1aI\xca\x41\x15speech.googleapis.com\xd2\x41.https://www.googleapis.com/auth/cloud-platformB\x80\x01\n!com.google.cloud.speech.v1p1beta1B\x0bSpeechProtoP\x01ZCgoogle.golang.org/genproto/googleapis/cloud/speech/v1p1beta1;speech\xf8\x01\x01\xa2\x02\x03GCSb\x06proto3' - ), - dependencies=[ - google_dot_api_dot_annotations__pb2.DESCRIPTOR, - google_dot_api_dot_client__pb2.DESCRIPTOR, - google_dot_api_dot_field__behavior__pb2.DESCRIPTOR, - google_dot_longrunning_dot_operations__pb2.DESCRIPTOR, - google_dot_protobuf_dot_any__pb2.DESCRIPTOR, - google_dot_protobuf_dot_duration__pb2.DESCRIPTOR, - google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR, - google_dot_rpc_dot_status__pb2.DESCRIPTOR, - ], -) - - -_RECOGNITIONCONFIG_AUDIOENCODING = _descriptor.EnumDescriptor( - name="AudioEncoding", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.AudioEncoding", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="ENCODING_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="LINEAR16", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="FLAC", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="MULAW", index=3, number=3, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="AMR", index=4, number=4, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="AMR_WB", index=5, number=5, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="OGG_OPUS", index=6, number=6, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="SPEEX_WITH_HEADER_BYTE", - index=7, - number=7, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="MP3", index=8, number=8, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=1752, - serialized_end=1900, -) -_sym_db.RegisterEnumDescriptor(_RECOGNITIONCONFIG_AUDIOENCODING) - -_RECOGNITIONMETADATA_INTERACTIONTYPE = _descriptor.EnumDescriptor( - name="InteractionType", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.InteractionType", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="INTERACTION_TYPE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="DISCUSSION", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="PRESENTATION", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="PHONE_CALL", index=3, number=3, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="VOICEMAIL", index=4, number=4, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="PROFESSIONALLY_PRODUCED", - index=5, - number=5, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="VOICE_SEARCH", index=6, number=6, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="VOICE_COMMAND", index=7, number=7, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="DICTATION", index=8, number=8, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=2586, - serialized_end=2783, -) -_sym_db.RegisterEnumDescriptor(_RECOGNITIONMETADATA_INTERACTIONTYPE) - -_RECOGNITIONMETADATA_MICROPHONEDISTANCE = _descriptor.EnumDescriptor( - name="MicrophoneDistance", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.MicrophoneDistance", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="MICROPHONE_DISTANCE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="NEARFIELD", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="MIDFIELD", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="FARFIELD", index=3, number=3, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=2785, - serialized_end=2885, -) -_sym_db.RegisterEnumDescriptor(_RECOGNITIONMETADATA_MICROPHONEDISTANCE) - -_RECOGNITIONMETADATA_ORIGINALMEDIATYPE = _descriptor.EnumDescriptor( - name="OriginalMediaType", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.OriginalMediaType", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="ORIGINAL_MEDIA_TYPE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="AUDIO", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="VIDEO", index=2, number=2, serialized_options=None, type=None - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=2887, - serialized_end=2965, -) -_sym_db.RegisterEnumDescriptor(_RECOGNITIONMETADATA_ORIGINALMEDIATYPE) - -_RECOGNITIONMETADATA_RECORDINGDEVICETYPE = _descriptor.EnumDescriptor( - name="RecordingDeviceType", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.RecordingDeviceType", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="RECORDING_DEVICE_TYPE_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="SMARTPHONE", index=1, number=1, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="PC", index=2, number=2, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="PHONE_LINE", index=3, number=3, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="VEHICLE", index=4, number=4, serialized_options=None, type=None - ), - _descriptor.EnumValueDescriptor( - name="OTHER_OUTDOOR_DEVICE", - index=5, - number=5, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="OTHER_INDOOR_DEVICE", - index=6, - number=6, - serialized_options=None, - type=None, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=2968, - serialized_end=3132, -) -_sym_db.RegisterEnumDescriptor(_RECOGNITIONMETADATA_RECORDINGDEVICETYPE) - -_STREAMINGRECOGNIZERESPONSE_SPEECHEVENTTYPE = _descriptor.EnumDescriptor( - name="SpeechEventType", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeResponse.SpeechEventType", - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name="SPEECH_EVENT_UNSPECIFIED", - index=0, - number=0, - serialized_options=None, - type=None, - ), - _descriptor.EnumValueDescriptor( - name="END_OF_SINGLE_UTTERANCE", - index=1, - number=1, - serialized_options=None, - type=None, - ), - ], - containing_type=None, - serialized_options=None, - serialized_start=3857, - serialized_end=3933, -) -_sym_db.RegisterEnumDescriptor(_STREAMINGRECOGNIZERESPONSE_SPEECHEVENTTYPE) - - -_RECOGNIZEREQUEST = _descriptor.Descriptor( - name="RecognizeRequest", - full_name="google.cloud.speech.v1p1beta1.RecognizeRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="config", - full_name="google.cloud.speech.v1p1beta1.RecognizeRequest.config", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audio", - full_name="google.cloud.speech.v1p1beta1.RecognizeRequest.audio", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=332, - serialized_end=490, -) - - -_LONGRUNNINGRECOGNIZEREQUEST = _descriptor.Descriptor( - name="LongRunningRecognizeRequest", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="config", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeRequest.config", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audio", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeRequest.audio", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=493, - serialized_end=662, -) - - -_STREAMINGRECOGNIZEREQUEST = _descriptor.Descriptor( - name="StreamingRecognizeRequest", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeRequest", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="streaming_config", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeRequest.streaming_config", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audio_content", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeRequest.audio_content", - index=1, - number=2, - type=12, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b(""), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="streaming_request", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeRequest.streaming_request", - index=0, - containing_type=None, - fields=[], - ) - ], - serialized_start=665, - serialized_end=825, -) - - -_STREAMINGRECOGNITIONCONFIG = _descriptor.Descriptor( - name="StreamingRecognitionConfig", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionConfig", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="config", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionConfig.config", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="single_utterance", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionConfig.single_utterance", - index=1, - number=2, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="interim_results", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionConfig.interim_results", - index=2, - number=3, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=828, - serialized_end=978, -) - - -_RECOGNITIONCONFIG = _descriptor.Descriptor( - name="RecognitionConfig", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="encoding", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.encoding", - index=0, - number=1, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="sample_rate_hertz", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.sample_rate_hertz", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audio_channel_count", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.audio_channel_count", - index=2, - number=7, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="enable_separate_recognition_per_channel", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.enable_separate_recognition_per_channel", - index=3, - number=12, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="language_code", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.language_code", - index=4, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\340A\002"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="alternative_language_codes", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.alternative_language_codes", - index=5, - number=18, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="max_alternatives", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.max_alternatives", - index=6, - number=4, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="profanity_filter", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.profanity_filter", - index=7, - number=5, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="speech_contexts", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.speech_contexts", - index=8, - number=6, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="enable_word_time_offsets", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.enable_word_time_offsets", - index=9, - number=8, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="enable_word_confidence", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.enable_word_confidence", - index=10, - number=15, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="enable_automatic_punctuation", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.enable_automatic_punctuation", - index=11, - number=11, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="enable_speaker_diarization", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.enable_speaker_diarization", - index=12, - number=16, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\030\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="diarization_speaker_count", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.diarization_speaker_count", - index=13, - number=17, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\030\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="diarization_config", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.diarization_config", - index=14, - number=19, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="metadata", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.metadata", - index=15, - number=9, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="model", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.model", - index=16, - number=13, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="use_enhanced", - full_name="google.cloud.speech.v1p1beta1.RecognitionConfig.use_enhanced", - index=17, - number=14, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[_RECOGNITIONCONFIG_AUDIOENCODING], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=981, - serialized_end=1900, -) - - -_SPEAKERDIARIZATIONCONFIG = _descriptor.Descriptor( - name="SpeakerDiarizationConfig", - full_name="google.cloud.speech.v1p1beta1.SpeakerDiarizationConfig", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="enable_speaker_diarization", - full_name="google.cloud.speech.v1p1beta1.SpeakerDiarizationConfig.enable_speaker_diarization", - index=0, - number=1, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="min_speaker_count", - full_name="google.cloud.speech.v1p1beta1.SpeakerDiarizationConfig.min_speaker_count", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="max_speaker_count", - full_name="google.cloud.speech.v1p1beta1.SpeakerDiarizationConfig.max_speaker_count", - index=2, - number=3, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=1902, - serialized_end=2018, -) - - -_RECOGNITIONMETADATA = _descriptor.Descriptor( - name="RecognitionMetadata", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="interaction_type", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.interaction_type", - index=0, - number=1, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="industry_naics_code_of_audio", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.industry_naics_code_of_audio", - index=1, - number=3, - type=13, - cpp_type=3, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="microphone_distance", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.microphone_distance", - index=2, - number=4, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="original_media_type", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.original_media_type", - index=3, - number=5, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="recording_device_type", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.recording_device_type", - index=4, - number=6, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="recording_device_name", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.recording_device_name", - index=5, - number=7, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="original_mime_type", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.original_mime_type", - index=6, - number=8, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="obfuscated_id", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.obfuscated_id", - index=7, - number=9, - type=3, - cpp_type=2, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=_b("\030\001"), - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="audio_topic", - full_name="google.cloud.speech.v1p1beta1.RecognitionMetadata.audio_topic", - index=8, - number=10, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[ - _RECOGNITIONMETADATA_INTERACTIONTYPE, - _RECOGNITIONMETADATA_MICROPHONEDISTANCE, - _RECOGNITIONMETADATA_ORIGINALMEDIATYPE, - _RECOGNITIONMETADATA_RECORDINGDEVICETYPE, - ], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=2021, - serialized_end=3132, -) - - -_SPEECHCONTEXT = _descriptor.Descriptor( - name="SpeechContext", - full_name="google.cloud.speech.v1p1beta1.SpeechContext", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="phrases", - full_name="google.cloud.speech.v1p1beta1.SpeechContext.phrases", - index=0, - number=1, - type=9, - cpp_type=9, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="boost", - full_name="google.cloud.speech.v1p1beta1.SpeechContext.boost", - index=1, - number=4, - type=2, - cpp_type=6, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3134, - serialized_end=3181, -) - - -_RECOGNITIONAUDIO = _descriptor.Descriptor( - name="RecognitionAudio", - full_name="google.cloud.speech.v1p1beta1.RecognitionAudio", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="content", - full_name="google.cloud.speech.v1p1beta1.RecognitionAudio.content", - index=0, - number=1, - type=12, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b(""), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="uri", - full_name="google.cloud.speech.v1p1beta1.RecognitionAudio.uri", - index=1, - number=2, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name="audio_source", - full_name="google.cloud.speech.v1p1beta1.RecognitionAudio.audio_source", - index=0, - containing_type=None, - fields=[], - ) - ], - serialized_start=3183, - serialized_end=3251, -) - - -_RECOGNIZERESPONSE = _descriptor.Descriptor( - name="RecognizeResponse", - full_name="google.cloud.speech.v1p1beta1.RecognizeResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="results", - full_name="google.cloud.speech.v1p1beta1.RecognizeResponse.results", - index=0, - number=2, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3253, - serialized_end=3345, -) - - -_LONGRUNNINGRECOGNIZERESPONSE = _descriptor.Descriptor( - name="LongRunningRecognizeResponse", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="results", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeResponse.results", - index=0, - number=2, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ) - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3347, - serialized_end=3450, -) - - -_LONGRUNNINGRECOGNIZEMETADATA = _descriptor.Descriptor( - name="LongRunningRecognizeMetadata", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeMetadata", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="progress_percent", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeMetadata.progress_percent", - index=0, - number=1, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="start_time", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeMetadata.start_time", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="last_update_time", - full_name="google.cloud.speech.v1p1beta1.LongRunningRecognizeMetadata.last_update_time", - index=2, - number=3, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3453, - serialized_end=3611, -) - - -_STREAMINGRECOGNIZERESPONSE = _descriptor.Descriptor( - name="StreamingRecognizeResponse", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeResponse", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="error", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeResponse.error", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="results", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeResponse.results", - index=1, - number=2, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="speech_event_type", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognizeResponse.speech_event_type", - index=2, - number=4, - type=14, - cpp_type=8, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[_STREAMINGRECOGNIZERESPONSE_SPEECHEVENTTYPE], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3614, - serialized_end=3933, -) - - -_STREAMINGRECOGNITIONRESULT = _descriptor.Descriptor( - name="StreamingRecognitionResult", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionResult", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="alternatives", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionResult.alternatives", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="is_final", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionResult.is_final", - index=1, - number=2, - type=8, - cpp_type=7, - label=1, - has_default_value=False, - default_value=False, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="stability", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionResult.stability", - index=2, - number=3, - type=2, - cpp_type=6, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="result_end_time", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionResult.result_end_time", - index=3, - number=4, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="channel_tag", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionResult.channel_tag", - index=4, - number=5, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="language_code", - full_name="google.cloud.speech.v1p1beta1.StreamingRecognitionResult.language_code", - index=5, - number=6, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=3936, - serialized_end=4180, -) - - -_SPEECHRECOGNITIONRESULT = _descriptor.Descriptor( - name="SpeechRecognitionResult", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionResult", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="alternatives", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionResult.alternatives", - index=0, - number=1, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="channel_tag", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionResult.channel_tag", - index=1, - number=2, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="language_code", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionResult.language_code", - index=2, - number=5, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4183, - serialized_end=4335, -) - - -_SPEECHRECOGNITIONALTERNATIVE = _descriptor.Descriptor( - name="SpeechRecognitionAlternative", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="transcript", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative.transcript", - index=0, - number=1, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="confidence", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative.confidence", - index=1, - number=2, - type=2, - cpp_type=6, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="words", - full_name="google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative.words", - index=2, - number=3, - type=11, - cpp_type=10, - label=3, - has_default_value=False, - default_value=[], - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4337, - serialized_end=4463, -) - - -_WORDINFO = _descriptor.Descriptor( - name="WordInfo", - full_name="google.cloud.speech.v1p1beta1.WordInfo", - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name="start_time", - full_name="google.cloud.speech.v1p1beta1.WordInfo.start_time", - index=0, - number=1, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="end_time", - full_name="google.cloud.speech.v1p1beta1.WordInfo.end_time", - index=1, - number=2, - type=11, - cpp_type=10, - label=1, - has_default_value=False, - default_value=None, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="word", - full_name="google.cloud.speech.v1p1beta1.WordInfo.word", - index=2, - number=3, - type=9, - cpp_type=9, - label=1, - has_default_value=False, - default_value=_b("").decode("utf-8"), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="confidence", - full_name="google.cloud.speech.v1p1beta1.WordInfo.confidence", - index=3, - number=4, - type=2, - cpp_type=6, - label=1, - has_default_value=False, - default_value=float(0), - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - _descriptor.FieldDescriptor( - name="speaker_tag", - full_name="google.cloud.speech.v1p1beta1.WordInfo.speaker_tag", - index=4, - number=5, - type=5, - cpp_type=1, - label=1, - has_default_value=False, - default_value=0, - message_type=None, - enum_type=None, - containing_type=None, - is_extension=False, - extension_scope=None, - serialized_options=None, - file=DESCRIPTOR, - ), - ], - extensions=[], - nested_types=[], - enum_types=[], - serialized_options=None, - is_extendable=False, - syntax="proto3", - extension_ranges=[], - oneofs=[], - serialized_start=4466, - serialized_end=4623, -) - -_RECOGNIZEREQUEST.fields_by_name["config"].message_type = _RECOGNITIONCONFIG -_RECOGNIZEREQUEST.fields_by_name["audio"].message_type = _RECOGNITIONAUDIO -_LONGRUNNINGRECOGNIZEREQUEST.fields_by_name["config"].message_type = _RECOGNITIONCONFIG -_LONGRUNNINGRECOGNIZEREQUEST.fields_by_name["audio"].message_type = _RECOGNITIONAUDIO -_STREAMINGRECOGNIZEREQUEST.fields_by_name[ - "streaming_config" -].message_type = _STREAMINGRECOGNITIONCONFIG -_STREAMINGRECOGNIZEREQUEST.oneofs_by_name["streaming_request"].fields.append( - _STREAMINGRECOGNIZEREQUEST.fields_by_name["streaming_config"] -) -_STREAMINGRECOGNIZEREQUEST.fields_by_name[ - "streaming_config" -].containing_oneof = _STREAMINGRECOGNIZEREQUEST.oneofs_by_name["streaming_request"] -_STREAMINGRECOGNIZEREQUEST.oneofs_by_name["streaming_request"].fields.append( - _STREAMINGRECOGNIZEREQUEST.fields_by_name["audio_content"] -) -_STREAMINGRECOGNIZEREQUEST.fields_by_name[ - "audio_content" -].containing_oneof = _STREAMINGRECOGNIZEREQUEST.oneofs_by_name["streaming_request"] -_STREAMINGRECOGNITIONCONFIG.fields_by_name["config"].message_type = _RECOGNITIONCONFIG -_RECOGNITIONCONFIG.fields_by_name[ - "encoding" -].enum_type = _RECOGNITIONCONFIG_AUDIOENCODING -_RECOGNITIONCONFIG.fields_by_name["speech_contexts"].message_type = _SPEECHCONTEXT -_RECOGNITIONCONFIG.fields_by_name[ - "diarization_config" -].message_type = _SPEAKERDIARIZATIONCONFIG -_RECOGNITIONCONFIG.fields_by_name["metadata"].message_type = _RECOGNITIONMETADATA -_RECOGNITIONCONFIG_AUDIOENCODING.containing_type = _RECOGNITIONCONFIG -_RECOGNITIONMETADATA.fields_by_name[ - "interaction_type" -].enum_type = _RECOGNITIONMETADATA_INTERACTIONTYPE -_RECOGNITIONMETADATA.fields_by_name[ - "microphone_distance" -].enum_type = _RECOGNITIONMETADATA_MICROPHONEDISTANCE -_RECOGNITIONMETADATA.fields_by_name[ - "original_media_type" -].enum_type = _RECOGNITIONMETADATA_ORIGINALMEDIATYPE -_RECOGNITIONMETADATA.fields_by_name[ - "recording_device_type" -].enum_type = _RECOGNITIONMETADATA_RECORDINGDEVICETYPE -_RECOGNITIONMETADATA_INTERACTIONTYPE.containing_type = _RECOGNITIONMETADATA -_RECOGNITIONMETADATA_MICROPHONEDISTANCE.containing_type = _RECOGNITIONMETADATA -_RECOGNITIONMETADATA_ORIGINALMEDIATYPE.containing_type = _RECOGNITIONMETADATA -_RECOGNITIONMETADATA_RECORDINGDEVICETYPE.containing_type = _RECOGNITIONMETADATA -_RECOGNITIONAUDIO.oneofs_by_name["audio_source"].fields.append( - _RECOGNITIONAUDIO.fields_by_name["content"] -) -_RECOGNITIONAUDIO.fields_by_name[ - "content" -].containing_oneof = _RECOGNITIONAUDIO.oneofs_by_name["audio_source"] -_RECOGNITIONAUDIO.oneofs_by_name["audio_source"].fields.append( - _RECOGNITIONAUDIO.fields_by_name["uri"] -) -_RECOGNITIONAUDIO.fields_by_name[ - "uri" -].containing_oneof = _RECOGNITIONAUDIO.oneofs_by_name["audio_source"] -_RECOGNIZERESPONSE.fields_by_name["results"].message_type = _SPEECHRECOGNITIONRESULT -_LONGRUNNINGRECOGNIZERESPONSE.fields_by_name[ - "results" -].message_type = _SPEECHRECOGNITIONRESULT -_LONGRUNNINGRECOGNIZEMETADATA.fields_by_name[ - "start_time" -].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP -_LONGRUNNINGRECOGNIZEMETADATA.fields_by_name[ - "last_update_time" -].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP -_STREAMINGRECOGNIZERESPONSE.fields_by_name[ - "error" -].message_type = google_dot_rpc_dot_status__pb2._STATUS -_STREAMINGRECOGNIZERESPONSE.fields_by_name[ - "results" -].message_type = _STREAMINGRECOGNITIONRESULT -_STREAMINGRECOGNIZERESPONSE.fields_by_name[ - "speech_event_type" -].enum_type = _STREAMINGRECOGNIZERESPONSE_SPEECHEVENTTYPE -_STREAMINGRECOGNIZERESPONSE_SPEECHEVENTTYPE.containing_type = ( - _STREAMINGRECOGNIZERESPONSE -) -_STREAMINGRECOGNITIONRESULT.fields_by_name[ - "alternatives" -].message_type = _SPEECHRECOGNITIONALTERNATIVE -_STREAMINGRECOGNITIONRESULT.fields_by_name[ - "result_end_time" -].message_type = google_dot_protobuf_dot_duration__pb2._DURATION -_SPEECHRECOGNITIONRESULT.fields_by_name[ - "alternatives" -].message_type = _SPEECHRECOGNITIONALTERNATIVE -_SPEECHRECOGNITIONALTERNATIVE.fields_by_name["words"].message_type = _WORDINFO -_WORDINFO.fields_by_name[ - "start_time" -].message_type = google_dot_protobuf_dot_duration__pb2._DURATION -_WORDINFO.fields_by_name[ - "end_time" -].message_type = google_dot_protobuf_dot_duration__pb2._DURATION -DESCRIPTOR.message_types_by_name["RecognizeRequest"] = _RECOGNIZEREQUEST -DESCRIPTOR.message_types_by_name[ - "LongRunningRecognizeRequest" -] = _LONGRUNNINGRECOGNIZEREQUEST -DESCRIPTOR.message_types_by_name[ - "StreamingRecognizeRequest" -] = _STREAMINGRECOGNIZEREQUEST -DESCRIPTOR.message_types_by_name[ - "StreamingRecognitionConfig" -] = _STREAMINGRECOGNITIONCONFIG -DESCRIPTOR.message_types_by_name["RecognitionConfig"] = _RECOGNITIONCONFIG -DESCRIPTOR.message_types_by_name["SpeakerDiarizationConfig"] = _SPEAKERDIARIZATIONCONFIG -DESCRIPTOR.message_types_by_name["RecognitionMetadata"] = _RECOGNITIONMETADATA -DESCRIPTOR.message_types_by_name["SpeechContext"] = _SPEECHCONTEXT -DESCRIPTOR.message_types_by_name["RecognitionAudio"] = _RECOGNITIONAUDIO -DESCRIPTOR.message_types_by_name["RecognizeResponse"] = _RECOGNIZERESPONSE -DESCRIPTOR.message_types_by_name[ - "LongRunningRecognizeResponse" -] = _LONGRUNNINGRECOGNIZERESPONSE -DESCRIPTOR.message_types_by_name[ - "LongRunningRecognizeMetadata" -] = _LONGRUNNINGRECOGNIZEMETADATA -DESCRIPTOR.message_types_by_name[ - "StreamingRecognizeResponse" -] = _STREAMINGRECOGNIZERESPONSE -DESCRIPTOR.message_types_by_name[ - "StreamingRecognitionResult" -] = _STREAMINGRECOGNITIONRESULT -DESCRIPTOR.message_types_by_name["SpeechRecognitionResult"] = _SPEECHRECOGNITIONRESULT -DESCRIPTOR.message_types_by_name[ - "SpeechRecognitionAlternative" -] = _SPEECHRECOGNITIONALTERNATIVE -DESCRIPTOR.message_types_by_name["WordInfo"] = _WORDINFO -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -RecognizeRequest = _reflection.GeneratedProtocolMessageType( - "RecognizeRequest", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNIZEREQUEST, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""The top-level message sent by the client for the - ``Recognize`` method. - - - Attributes: - config: - Required. Provides information to the recognizer that - specifies how to process the request. - audio: - Required. The audio data to be recognized. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.RecognizeRequest) - ), -) -_sym_db.RegisterMessage(RecognizeRequest) - -LongRunningRecognizeRequest = _reflection.GeneratedProtocolMessageType( - "LongRunningRecognizeRequest", - (_message.Message,), - dict( - DESCRIPTOR=_LONGRUNNINGRECOGNIZEREQUEST, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""The top-level message sent by the client for the - ``LongRunningRecognize`` method. - - - Attributes: - config: - Required. Provides information to the recognizer that - specifies how to process the request. - audio: - Required. The audio data to be recognized. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.LongRunningRecognizeRequest) - ), -) -_sym_db.RegisterMessage(LongRunningRecognizeRequest) - -StreamingRecognizeRequest = _reflection.GeneratedProtocolMessageType( - "StreamingRecognizeRequest", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGRECOGNIZEREQUEST, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""The top-level message sent by the client for the - ``StreamingRecognize`` method. Multiple ``StreamingRecognizeRequest`` - messages are sent. The first message must contain a ``streaming_config`` - message and must not contain ``audio_content``. All subsequent messages - must contain ``audio_content`` and must not contain a - ``streaming_config`` message. - - - Attributes: - streaming_request: - The streaming request, which is either a streaming config or - audio content. - streaming_config: - Provides information to the recognizer that specifies how to - process the request. The first ``StreamingRecognizeRequest`` - message must contain a ``streaming_config`` message. - audio_content: - The audio data to be recognized. Sequential chunks of audio - data are sent in sequential ``StreamingRecognizeRequest`` - messages. The first ``StreamingRecognizeRequest`` message must - not contain ``audio_content`` data and all subsequent - ``StreamingRecognizeRequest`` messages must contain - ``audio_content`` data. The audio bytes must be encoded as - specified in ``RecognitionConfig``. Note: as with all bytes - fields, proto buffers use a pure binary representation (not - base64). See `content limits `__. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.StreamingRecognizeRequest) - ), -) -_sym_db.RegisterMessage(StreamingRecognizeRequest) - -StreamingRecognitionConfig = _reflection.GeneratedProtocolMessageType( - "StreamingRecognitionConfig", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGRECOGNITIONCONFIG, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Provides information to the recognizer that specifies how - to process the request. - - - Attributes: - config: - Required. Provides information to the recognizer that - specifies how to process the request. - single_utterance: - If ``false`` or omitted, the recognizer will perform - continuous recognition (continuing to wait for and process - audio even if the user pauses speaking) until the client - closes the input stream (gRPC API) or until the maximum time - limit has been reached. May return multiple - ``StreamingRecognitionResult``\ s with the ``is_final`` flag - set to ``true``. If ``true``, the recognizer will detect a - single spoken utterance. When it detects that the user has - paused or stopped speaking, it will return an - ``END_OF_SINGLE_UTTERANCE`` event and cease recognition. It - will return no more than one ``StreamingRecognitionResult`` - with the ``is_final`` flag set to ``true``. - interim_results: - If ``true``, interim results (tentative hypotheses) may be - returned as they become available (these interim results are - indicated with the ``is_final=false`` flag). If ``false`` or - omitted, only ``is_final=true`` result(s) are returned. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.StreamingRecognitionConfig) - ), -) -_sym_db.RegisterMessage(StreamingRecognitionConfig) - -RecognitionConfig = _reflection.GeneratedProtocolMessageType( - "RecognitionConfig", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNITIONCONFIG, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Provides information to the recognizer that specifies how - to process the request. - - - Attributes: - encoding: - Encoding of audio data sent in all ``RecognitionAudio`` - messages. This field is optional for ``FLAC`` and ``WAV`` - audio files and required for all other audio formats. For - details, see [AudioEncoding][google.cloud.speech.v1p1beta1.Rec - ognitionConfig.AudioEncoding]. - sample_rate_hertz: - Sample rate in Hertz of the audio data sent in all - ``RecognitionAudio`` messages. Valid values are: 8000-48000. - 16000 is optimal. For best results, set the sampling rate of - the audio source to 16000 Hz. If that's not possible, use the - native sample rate of the audio source (instead of re- - sampling). This field is optional for FLAC and WAV audio - files, but is required for all other audio formats. For - details, see [AudioEncoding][google.cloud.speech.v1p1beta1.Rec - ognitionConfig.AudioEncoding]. - audio_channel_count: - The number of channels in the input audio data. ONLY set this - for MULTI-CHANNEL recognition. Valid values for LINEAR16 and - FLAC are ``1``-``8``. Valid values for OGG\_OPUS are - '1'-'254'. Valid value for MULAW, AMR, AMR\_WB and - SPEEX\_WITH\_HEADER\_BYTE is only ``1``. If ``0`` or omitted, - defaults to one channel (mono). Note: We only recognize the - first channel by default. To perform independent recognition - on each channel set - ``enable_separate_recognition_per_channel`` to 'true'. - enable_separate_recognition_per_channel: - This needs to be set to ``true`` explicitly and - ``audio_channel_count`` > 1 to get each channel recognized - separately. The recognition result will contain a - ``channel_tag`` field to state which channel that result - belongs to. If this is not true, we will only recognize the - first channel. The request is billed cumulatively for all - channels recognized: ``audio_channel_count`` multiplied by the - length of the audio. - language_code: - Required. The language of the supplied audio as a `BCP-47 - `__ language - tag. Example: "en-US". See `Language Support - `__ - for a list of the currently supported language codes. - alternative_language_codes: - A list of up to 3 additional `BCP-47 `__ language tags, listing - possible alternative languages of the supplied audio. See - `Language Support `__ for a list of the currently supported - language codes. If alternative languages are listed, - recognition result will contain recognition in the most likely - language detected including the main language\_code. The - recognition result will include the language tag of the - language detected in the audio. Note: This feature is only - supported for Voice Command and Voice Search use cases and - performance may vary for other use cases (e.g., phone call - transcription). - max_alternatives: - Maximum number of recognition hypotheses to be returned. - Specifically, the maximum number of - ``SpeechRecognitionAlternative`` messages within each - ``SpeechRecognitionResult``. The server may return fewer than - ``max_alternatives``. Valid values are ``0``-``30``. A value - of ``0`` or ``1`` will return a maximum of one. If omitted, - will return a maximum of one. - profanity_filter: - If set to ``true``, the server will attempt to filter out - profanities, replacing all but the initial character in each - filtered word with asterisks, e.g. "f\*\*\*". If set to - ``false`` or omitted, profanities won't be filtered out. - speech_contexts: - Array of - [SpeechContext][google.cloud.speech.v1p1beta1.SpeechContext]. - A means to provide context to assist the speech recognition. - For more information, see `speech adaptation - `__. - enable_word_time_offsets: - If ``true``, the top result includes a list of words and the - start and end time offsets (timestamps) for those words. If - ``false``, no word-level time offset information is returned. - The default is ``false``. - enable_word_confidence: - If ``true``, the top result includes a list of words and the - confidence for those words. If ``false``, no word-level - confidence information is returned. The default is ``false``. - enable_automatic_punctuation: - If 'true', adds punctuation to recognition result hypotheses. - This feature is only available in select languages. Setting - this for requests in other languages has no effect at all. The - default 'false' value does not add punctuation to result - hypotheses. Note: This is currently offered as an experimental - service, complimentary to all users. In the future this may be - exclusively available as a premium feature. - enable_speaker_diarization: - If 'true', enables speaker detection for each recognized word - in the top alternative of the recognition result using a - speaker\_tag provided in the WordInfo. Note: Use - diarization\_config instead. - diarization_speaker_count: - If set, specifies the estimated number of speakers in the - conversation. Defaults to '2'. Ignored unless - enable\_speaker\_diarization is set to true. Note: Use - diarization\_config instead. - diarization_config: - Config to enable speaker diarization and set additional - parameters to make diarization better suited for your - application. Note: When this is enabled, we send all the words - from the beginning of the audio for the top alternative in - every consecutive STREAMING responses. This is done in order - to improve our speaker tags as our models learn to identify - the speakers in the conversation over time. For non-streaming - requests, the diarization results will be provided only in the - top alternative of the FINAL SpeechRecognitionResult. - metadata: - Metadata regarding this request. - model: - Which model to select for the given request. Select the model - best suited to your domain to get best results. If a model is - not explicitly specified, then we auto-select a model based on - the parameters in the RecognitionConfig. .. raw:: html - .. raw:: html :: - .. raw:: html .. raw:: - html :: - .. - raw:: html .. raw:: html :: - .. raw:: html .. raw:: - html :: - .. - raw:: html .. raw:: html :: - .. raw:: - html .. raw:: html
ModelDescription
command_and_search Best for - short queries such as voice commands or voice search.
phone_call Best for audio that - originated from a phone call (typically recorded at an - 8khz sampling rate).
videoBest for audio that originated from from video or includes - multiple speakers. Ideally the audio is recorded at a - 16khz or greater sampling rate. This is a premium - model that costs more than the standard rate.
default Best for audio that is - not one of the specific audio models. For example, - long-form audio. Ideally the audio is high-fidelity, - recorded at a 16khz or greater sampling rate.
- use_enhanced: - Set to true to use an enhanced model for speech recognition. - If ``use_enhanced`` is set to true and the ``model`` field is - not set, then an appropriate enhanced model is chosen if an - enhanced model exists for the audio. If ``use_enhanced`` is - true and an enhanced version of the specified model does not - exist, then the speech is recognized using the standard - version of the specified model. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.RecognitionConfig) - ), -) -_sym_db.RegisterMessage(RecognitionConfig) - -SpeakerDiarizationConfig = _reflection.GeneratedProtocolMessageType( - "SpeakerDiarizationConfig", - (_message.Message,), - dict( - DESCRIPTOR=_SPEAKERDIARIZATIONCONFIG, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Config to enable speaker diarization. - - - Attributes: - enable_speaker_diarization: - If 'true', enables speaker detection for each recognized word - in the top alternative of the recognition result using a - speaker\_tag provided in the WordInfo. - min_speaker_count: - Minimum number of speakers in the conversation. This range - gives you more flexibility by allowing the system to - automatically determine the correct number of speakers. If not - set, the default value is 2. - max_speaker_count: - Maximum number of speakers in the conversation. This range - gives you more flexibility by allowing the system to - automatically determine the correct number of speakers. If not - set, the default value is 6. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.SpeakerDiarizationConfig) - ), -) -_sym_db.RegisterMessage(SpeakerDiarizationConfig) - -RecognitionMetadata = _reflection.GeneratedProtocolMessageType( - "RecognitionMetadata", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNITIONMETADATA, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Description of audio data to be recognized. - - - Attributes: - interaction_type: - The use case most closely describing the audio content to be - recognized. - industry_naics_code_of_audio: - The industry vertical to which this speech recognition request - most closely applies. This is most indicative of the topics - contained in the audio. Use the 6-digit NAICS code to identify - the industry vertical - see https://www.naics.com/search/. - microphone_distance: - The audio type that most closely describes the audio being - recognized. - original_media_type: - The original media the speech was recorded on. - recording_device_type: - The type of device the speech was recorded with. - recording_device_name: - The device used to make the recording. Examples 'Nexus 5X' or - 'Polycom SoundStation IP 6000' or 'POTS' or 'VoIP' or - 'Cardioid Microphone'. - original_mime_type: - Mime type of the original audio file. For example - ``audio/m4a``, ``audio/x-alaw-basic``, ``audio/mp3``, - ``audio/3gpp``. A list of possible audio mime types is - maintained at http://www.iana.org/assignments/media- - types/media-types.xhtml#audio - obfuscated_id: - Obfuscated (privacy-protected) ID of the user, to identify - number of unique users using the service. - audio_topic: - Description of the content. Eg. "Recordings of federal supreme - court hearings from 2012". - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.RecognitionMetadata) - ), -) -_sym_db.RegisterMessage(RecognitionMetadata) - -SpeechContext = _reflection.GeneratedProtocolMessageType( - "SpeechContext", - (_message.Message,), - dict( - DESCRIPTOR=_SPEECHCONTEXT, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Provides "hints" to the speech recognizer to favor - specific words and phrases in the results. - - - Attributes: - phrases: - A list of strings containing words and phrases "hints" so that - the speech recognition is more likely to recognize them. This - can be used to improve the accuracy for specific words and - phrases, for example, if specific commands are typically - spoken by the user. This can also be used to add additional - words to the vocabulary of the recognizer. See `usage limits - `__. - List items can also be set to classes for groups of words that - represent common concepts that occur in natural language. For - example, rather than providing phrase hints for every month of - the year, using the $MONTH class improves the likelihood of - correctly transcribing audio that includes months. - boost: - Hint Boost. Positive value will increase the probability that - a specific phrase will be recognized over other similar - sounding phrases. The higher the boost, the higher the chance - of false positive recognition as well. Negative boost values - would correspond to anti-biasing. Anti-biasing is not enabled, - so negative boost will simply be ignored. Though ``boost`` can - accept a wide range of positive values, most use cases are - best served with values between 0 and 20. We recommend using a - binary search approach to finding the optimal value for your - use case. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.SpeechContext) - ), -) -_sym_db.RegisterMessage(SpeechContext) - -RecognitionAudio = _reflection.GeneratedProtocolMessageType( - "RecognitionAudio", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNITIONAUDIO, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Contains audio data in the encoding specified in the - ``RecognitionConfig``. Either ``content`` or ``uri`` must be supplied. - Supplying both or neither returns - [google.rpc.Code.INVALID\_ARGUMENT][google.rpc.Code.INVALID\_ARGUMENT]. - See `content - limits `__. - - - Attributes: - audio_source: - The audio source, which is either inline content or a Google - Cloud Storage uri. - content: - The audio data bytes encoded as specified in - ``RecognitionConfig``. Note: as with all bytes fields, proto - buffers use a pure binary representation, whereas JSON - representations use base64. - uri: - URI that points to a file that contains audio data bytes as - specified in ``RecognitionConfig``. The file must not be - compressed (for example, gzip). Currently, only Google Cloud - Storage URIs are supported, which must be specified in the - following format: ``gs://bucket_name/object_name`` (other URI - formats return [google.rpc.Code.INVALID\_ARGUMENT][google.rpc. - Code.INVALID\_ARGUMENT]). For more information, see `Request - URIs `__. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.RecognitionAudio) - ), -) -_sym_db.RegisterMessage(RecognitionAudio) - -RecognizeResponse = _reflection.GeneratedProtocolMessageType( - "RecognizeResponse", - (_message.Message,), - dict( - DESCRIPTOR=_RECOGNIZERESPONSE, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""The only message returned to the client by the - ``Recognize`` method. It contains the result as zero or more sequential - ``SpeechRecognitionResult`` messages. - - - Attributes: - results: - Sequential list of transcription results corresponding to - sequential portions of audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.RecognizeResponse) - ), -) -_sym_db.RegisterMessage(RecognizeResponse) - -LongRunningRecognizeResponse = _reflection.GeneratedProtocolMessageType( - "LongRunningRecognizeResponse", - (_message.Message,), - dict( - DESCRIPTOR=_LONGRUNNINGRECOGNIZERESPONSE, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""The only message returned to the client by the - ``LongRunningRecognize`` method. It contains the result as zero or more - sequential ``SpeechRecognitionResult`` messages. It is included in the - ``result.response`` field of the ``Operation`` returned by the - ``GetOperation`` call of the ``google::longrunning::Operations`` - service. - - - Attributes: - results: - Sequential list of transcription results corresponding to - sequential portions of audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.LongRunningRecognizeResponse) - ), -) -_sym_db.RegisterMessage(LongRunningRecognizeResponse) - -LongRunningRecognizeMetadata = _reflection.GeneratedProtocolMessageType( - "LongRunningRecognizeMetadata", - (_message.Message,), - dict( - DESCRIPTOR=_LONGRUNNINGRECOGNIZEMETADATA, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Describes the progress of a long-running - ``LongRunningRecognize`` call. It is included in the ``metadata`` field - of the ``Operation`` returned by the ``GetOperation`` call of the - ``google::longrunning::Operations`` service. - - - Attributes: - progress_percent: - Approximate percentage of audio processed thus far. Guaranteed - to be 100 when the audio is fully processed and the results - are available. - start_time: - Time when the request was received. - last_update_time: - Time of the most recent processing update. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.LongRunningRecognizeMetadata) - ), -) -_sym_db.RegisterMessage(LongRunningRecognizeMetadata) - -StreamingRecognizeResponse = _reflection.GeneratedProtocolMessageType( - "StreamingRecognizeResponse", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGRECOGNIZERESPONSE, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""\ ``StreamingRecognizeResponse`` is the only message - returned to the client by ``StreamingRecognize``. A series of zero or - more ``StreamingRecognizeResponse`` messages are streamed back to the - client. If there is no recognizable audio, and ``single_utterance`` is - set to false, then no messages are streamed back to the client. - - Here's an example of a series of ten ``StreamingRecognizeResponse``\ s - that might be returned while processing audio: - - 1. results { alternatives { transcript: "tube" } stability: 0.01 } - - 2. results { alternatives { transcript: "to be a" } stability: 0.01 } - - 3. results { alternatives { transcript: "to be" } stability: 0.9 } - results { alternatives { transcript: " or not to be" } stability: - 0.01 } - - 4. results { alternatives { transcript: "to be or not to be" confidence: - 0.92 } alternatives { transcript: "to bee or not to bee" } is\_final: - true } - - 5. results { alternatives { transcript: " that's" } stability: 0.01 } - - 6. results { alternatives { transcript: " that is" } stability: 0.9 } - results { alternatives { transcript: " the question" } stability: - 0.01 } - - 7. results { alternatives { transcript: " that is the question" - confidence: 0.98 } alternatives { transcript: " that was the - question" } is\_final: true } - - Notes: - - - Only two of the above responses #4 and #7 contain final results; they - are indicated by ``is_final: true``. Concatenating these together - generates the full transcript: "to be or not to be that is the - question". - - - The others contain interim ``results``. #3 and #6 contain two interim - ``results``: the first portion has a high stability and is less - likely to change; the second portion has a low stability and is very - likely to change. A UI designer might choose to show only high - stability ``results``. - - - The specific ``stability`` and ``confidence`` values shown above are - only for illustrative purposes. Actual values may vary. - - - In each response, only one of these fields will be set: ``error``, - ``speech_event_type``, or one or more (repeated) ``results``. - - - Attributes: - error: - If set, returns a [google.rpc.Status][google.rpc.Status] - message that specifies the error for the operation. - results: - This repeated list contains zero or more results that - correspond to consecutive portions of the audio currently - being processed. It contains zero or one ``is_final=true`` - result (the newly settled portion), followed by zero or more - ``is_final=false`` results (the interim results). - speech_event_type: - Indicates the type of speech event. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.StreamingRecognizeResponse) - ), -) -_sym_db.RegisterMessage(StreamingRecognizeResponse) - -StreamingRecognitionResult = _reflection.GeneratedProtocolMessageType( - "StreamingRecognitionResult", - (_message.Message,), - dict( - DESCRIPTOR=_STREAMINGRECOGNITIONRESULT, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""A streaming speech recognition result corresponding to a - portion of the audio that is currently being processed. - - - Attributes: - alternatives: - May contain one or more recognition hypotheses (up to the - maximum specified in ``max_alternatives``). These alternatives - are ordered in terms of accuracy, with the top (first) - alternative being the most probable, as ranked by the - recognizer. - is_final: - If ``false``, this ``StreamingRecognitionResult`` represents - an interim result that may change. If ``true``, this is the - final time the speech service will return this particular - ``StreamingRecognitionResult``, the recognizer will not return - any further hypotheses for this portion of the transcript and - corresponding audio. - stability: - An estimate of the likelihood that the recognizer will not - change its guess about this interim result. Values range from - 0.0 (completely unstable) to 1.0 (completely stable). This - field is only provided for interim results - (``is_final=false``). The default of 0.0 is a sentinel value - indicating ``stability`` was not set. - result_end_time: - Time offset of the end of this result relative to the - beginning of the audio. - channel_tag: - For multi-channel audio, this is the channel number - corresponding to the recognized result for the audio from that - channel. For audio\_channel\_count = N, its output values can - range from '1' to 'N'. - language_code: - The `BCP-47 `__ - language tag of the language in this result. This language - code was detected to have the most likelihood of being spoken - in the audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.StreamingRecognitionResult) - ), -) -_sym_db.RegisterMessage(StreamingRecognitionResult) - -SpeechRecognitionResult = _reflection.GeneratedProtocolMessageType( - "SpeechRecognitionResult", - (_message.Message,), - dict( - DESCRIPTOR=_SPEECHRECOGNITIONRESULT, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""A speech recognition result corresponding to a portion of the audio. - - - Attributes: - alternatives: - May contain one or more recognition hypotheses (up to the - maximum specified in ``max_alternatives``). These alternatives - are ordered in terms of accuracy, with the top (first) - alternative being the most probable, as ranked by the - recognizer. - channel_tag: - For multi-channel audio, this is the channel number - corresponding to the recognized result for the audio from that - channel. For audio\_channel\_count = N, its output values can - range from '1' to 'N'. - language_code: - The `BCP-47 `__ - language tag of the language in this result. This language - code was detected to have the most likelihood of being spoken - in the audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.SpeechRecognitionResult) - ), -) -_sym_db.RegisterMessage(SpeechRecognitionResult) - -SpeechRecognitionAlternative = _reflection.GeneratedProtocolMessageType( - "SpeechRecognitionAlternative", - (_message.Message,), - dict( - DESCRIPTOR=_SPEECHRECOGNITIONALTERNATIVE, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Alternative hypotheses (a.k.a. n-best list). - - - Attributes: - transcript: - Transcript text representing the words that the user spoke. - confidence: - The confidence estimate between 0.0 and 1.0. A higher number - indicates an estimated greater likelihood that the recognized - words are correct. This field is set only for the top - alternative of a non-streaming result or, of a streaming - result where ``is_final=true``. This field is not guaranteed - to be accurate and users should not rely on it to be always - provided. The default of 0.0 is a sentinel value indicating - ``confidence`` was not set. - words: - A list of word-specific information for each recognized word. - Note: When ``enable_speaker_diarization`` is true, you will - see all the words from the beginning of the audio. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative) - ), -) -_sym_db.RegisterMessage(SpeechRecognitionAlternative) - -WordInfo = _reflection.GeneratedProtocolMessageType( - "WordInfo", - (_message.Message,), - dict( - DESCRIPTOR=_WORDINFO, - __module__="google.cloud.speech_v1p1beta1.proto.cloud_speech_pb2", - __doc__="""Word-specific information for recognized words. - - - Attributes: - start_time: - Time offset relative to the beginning of the audio, and - corresponding to the start of the spoken word. This field is - only set if ``enable_word_time_offsets=true`` and only in the - top hypothesis. This is an experimental feature and the - accuracy of the time offset can vary. - end_time: - Time offset relative to the beginning of the audio, and - corresponding to the end of the spoken word. This field is - only set if ``enable_word_time_offsets=true`` and only in the - top hypothesis. This is an experimental feature and the - accuracy of the time offset can vary. - word: - The word corresponding to this set of information. - confidence: - The confidence estimate between 0.0 and 1.0. A higher number - indicates an estimated greater likelihood that the recognized - words are correct. This field is set only for the top - alternative of a non-streaming result or, of a streaming - result where ``is_final=true``. This field is not guaranteed - to be accurate and users should not rely on it to be always - provided. The default of 0.0 is a sentinel value indicating - ``confidence`` was not set. - speaker_tag: - A distinct integer value is assigned for every speaker within - the audio. This field specifies which one of those speakers - was detected to have spoken this word. Value ranges from '1' - to diarization\_speaker\_count. speaker\_tag is set if - enable\_speaker\_diarization = 'true' and only in the top - alternative. - """, - # @@protoc_insertion_point(class_scope:google.cloud.speech.v1p1beta1.WordInfo) - ), -) -_sym_db.RegisterMessage(WordInfo) - - -DESCRIPTOR._options = None -_RECOGNIZEREQUEST.fields_by_name["config"]._options = None -_RECOGNIZEREQUEST.fields_by_name["audio"]._options = None -_LONGRUNNINGRECOGNIZEREQUEST.fields_by_name["config"]._options = None -_LONGRUNNINGRECOGNIZEREQUEST.fields_by_name["audio"]._options = None -_STREAMINGRECOGNITIONCONFIG.fields_by_name["config"]._options = None -_RECOGNITIONCONFIG.fields_by_name["language_code"]._options = None -_RECOGNITIONCONFIG.fields_by_name["enable_speaker_diarization"]._options = None -_RECOGNITIONCONFIG.fields_by_name["diarization_speaker_count"]._options = None -_RECOGNITIONMETADATA.fields_by_name["obfuscated_id"]._options = None - -_SPEECH = _descriptor.ServiceDescriptor( - name="Speech", - full_name="google.cloud.speech.v1p1beta1.Speech", - file=DESCRIPTOR, - index=0, - serialized_options=_b( - "\312A\025speech.googleapis.com\322A.https://www.googleapis.com/auth/cloud-platform" - ), - serialized_start=4626, - serialized_end=5268, - methods=[ - _descriptor.MethodDescriptor( - name="Recognize", - full_name="google.cloud.speech.v1p1beta1.Speech.Recognize", - index=0, - containing_service=None, - input_type=_RECOGNIZEREQUEST, - output_type=_RECOGNIZERESPONSE, - serialized_options=_b( - '\202\323\344\223\002 "\033/v1p1beta1/speech:recognize:\001*\332A\014config,audio' - ), - ), - _descriptor.MethodDescriptor( - name="LongRunningRecognize", - full_name="google.cloud.speech.v1p1beta1.Speech.LongRunningRecognize", - index=1, - containing_service=None, - input_type=_LONGRUNNINGRECOGNIZEREQUEST, - output_type=google_dot_longrunning_dot_operations__pb2._OPERATION, - serialized_options=_b( - '\202\323\344\223\002+"&/v1p1beta1/speech:longrunningrecognize:\001*\332A\014config,audio\312A<\n\034LongRunningRecognizeResponse\022\034LongRunningRecognizeMetadata' - ), - ), - _descriptor.MethodDescriptor( - name="StreamingRecognize", - full_name="google.cloud.speech.v1p1beta1.Speech.StreamingRecognize", - index=2, - containing_service=None, - input_type=_STREAMINGRECOGNIZEREQUEST, - output_type=_STREAMINGRECOGNIZERESPONSE, - serialized_options=None, - ), - ], -) -_sym_db.RegisterServiceDescriptor(_SPEECH) - -DESCRIPTOR.services_by_name["Speech"] = _SPEECH - -# @@protoc_insertion_point(module_scope) diff --git a/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2_grpc.py b/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2_grpc.py deleted file mode 100644 index ba4950fd256e..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/proto/cloud_speech_pb2_grpc.py +++ /dev/null @@ -1,93 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -from google.cloud.speech_v1p1beta1.proto import ( - cloud_speech_pb2 as google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2, -) -from google.longrunning import ( - operations_pb2 as google_dot_longrunning_dot_operations__pb2, -) - - -class SpeechStub(object): - """Service that implements Google Cloud Speech API. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.Recognize = channel.unary_unary( - "/google.cloud.speech.v1p1beta1.Speech/Recognize", - request_serializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.RecognizeRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.RecognizeResponse.FromString, - ) - self.LongRunningRecognize = channel.unary_unary( - "/google.cloud.speech.v1p1beta1.Speech/LongRunningRecognize", - request_serializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.LongRunningRecognizeRequest.SerializeToString, - response_deserializer=google_dot_longrunning_dot_operations__pb2.Operation.FromString, - ) - self.StreamingRecognize = channel.stream_stream( - "/google.cloud.speech.v1p1beta1.Speech/StreamingRecognize", - request_serializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeRequest.SerializeToString, - response_deserializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeResponse.FromString, - ) - - -class SpeechServicer(object): - """Service that implements Google Cloud Speech API. - """ - - def Recognize(self, request, context): - """Performs synchronous speech recognition: receive results after all audio - has been sent and processed. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def LongRunningRecognize(self, request, context): - """Performs asynchronous speech recognition: receive results via the - google.longrunning.Operations interface. Returns either an - `Operation.error` or an `Operation.response` which contains - a `LongRunningRecognizeResponse` message. - For more information on asynchronous speech recognition, see the - [how-to](https://cloud.google.com/speech-to-text/docs/async-recognize). - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - def StreamingRecognize(self, request_iterator, context): - """Performs bidirectional streaming speech recognition: receive results while - sending audio. This method is only available via the gRPC API (not REST). - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details("Method not implemented!") - raise NotImplementedError("Method not implemented!") - - -def add_SpeechServicer_to_server(servicer, server): - rpc_method_handlers = { - "Recognize": grpc.unary_unary_rpc_method_handler( - servicer.Recognize, - request_deserializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.RecognizeRequest.FromString, - response_serializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.RecognizeResponse.SerializeToString, - ), - "LongRunningRecognize": grpc.unary_unary_rpc_method_handler( - servicer.LongRunningRecognize, - request_deserializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.LongRunningRecognizeRequest.FromString, - response_serializer=google_dot_longrunning_dot_operations__pb2.Operation.SerializeToString, - ), - "StreamingRecognize": grpc.stream_stream_rpc_method_handler( - servicer.StreamingRecognize, - request_deserializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeRequest.FromString, - response_serializer=google_dot_cloud_dot_speech__v1p1beta1_dot_proto_dot_cloud__speech__pb2.StreamingRecognizeResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - "google.cloud.speech.v1p1beta1.Speech", rpc_method_handlers - ) - server.add_generic_rpc_handlers((generic_handler,)) diff --git a/speech/google/cloud/speech_v1p1beta1/types.py b/speech/google/cloud/speech_v1p1beta1/types.py deleted file mode 100644 index 35c7a2c09519..000000000000 --- a/speech/google/cloud/speech_v1p1beta1/types.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from __future__ import absolute_import -import sys - -from google.api_core.protobuf_helpers import get_messages - -from google.cloud.speech_v1p1beta1.proto import cloud_speech_pb2 -from google.longrunning import operations_pb2 -from google.protobuf import any_pb2 -from google.protobuf import duration_pb2 -from google.protobuf import timestamp_pb2 -from google.rpc import status_pb2 - - -_shared_modules = [operations_pb2, any_pb2, duration_pb2, timestamp_pb2, status_pb2] - -_local_modules = [cloud_speech_pb2] - -names = [] - -for module in _shared_modules: # pragma: NO COVER - for name, message in get_messages(module).items(): - setattr(sys.modules[__name__], name, message) - names.append(name) -for module in _local_modules: - for name, message in get_messages(module).items(): - message.__module__ = "google.cloud.speech_v1p1beta1.types" - setattr(sys.modules[__name__], name, message) - names.append(name) - - -__all__ = tuple(sorted(names)) diff --git a/speech/noxfile.py b/speech/noxfile.py deleted file mode 100644 index 9bc787f5ac16..000000000000 --- a/speech/noxfile.py +++ /dev/null @@ -1,180 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2018 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Generated by synthtool. DO NOT EDIT! - -from __future__ import absolute_import -import os -import shutil - -import nox - - -LOCAL_DEPS = (os.path.join("..", "api_core"), os.path.join("..", "core")) -BLACK_VERSION = "black==19.3b0" -BLACK_PATHS = ["docs", "google", "tests", "noxfile.py", "setup.py"] - -if os.path.exists("samples"): - BLACK_PATHS.append("samples") - - -@nox.session(python="3.7") -def lint(session): - """Run linters. - - Returns a failure if the linters find linting errors or sufficiently - serious code quality issues. - """ - session.install("flake8", BLACK_VERSION, *LOCAL_DEPS) - session.run("black", "--check", *BLACK_PATHS) - session.run("flake8", "google", "tests") - - -@nox.session(python="3.6") -def blacken(session): - """Run black. - - Format code to uniform standard. - - This currently uses Python 3.6 due to the automated Kokoro run of synthtool. - That run uses an image that doesn't have 3.6 installed. Before updating this - check the state of the `gcp_ubuntu_config` we use for that Kokoro run. - """ - session.install(BLACK_VERSION) - session.run("black", *BLACK_PATHS) - - -@nox.session(python="3.7") -def lint_setup_py(session): - """Verify that setup.py is valid (including RST check).""" - session.install("docutils", "pygments") - session.run("python", "setup.py", "check", "--restructuredtext", "--strict") - - -def default(session): - # Install all test dependencies, then install this package in-place. - session.install("mock", "pytest", "pytest-cov") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", ".") - - # Run py.test against the unit tests. - session.run( - "py.test", - "--quiet", - "--cov=google.cloud", - "--cov=tests.unit", - "--cov-append", - "--cov-config=.coveragerc", - "--cov-report=", - "--cov-fail-under=0", - os.path.join("tests", "unit"), - *session.posargs, - ) - - -@nox.session(python=["2.7", "3.5", "3.6", "3.7"]) -def unit(session): - """Run the unit test suite.""" - default(session) - - -@nox.session(python=["2.7", "3.7"]) -def system(session): - """Run the system test suite.""" - system_test_path = os.path.join("tests", "system.py") - system_test_folder_path = os.path.join("tests", "system") - # Sanity check: Only run tests if the environment variable is set. - if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): - session.skip("Credentials must be set via environment variable") - - system_test_exists = os.path.exists(system_test_path) - system_test_folder_exists = os.path.exists(system_test_folder_path) - # Sanity check: only run tests if found. - if not system_test_exists and not system_test_folder_exists: - session.skip("System tests were not found") - - # Use pre-release gRPC for system tests. - session.install("--pre", "grpcio") - - # Install all test dependencies, then install this package into the - # virtualenv's dist-packages. - session.install("mock", "pytest") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", "../test_utils/") - session.install("-e", ".") - - # Run py.test against the system tests. - if system_test_exists: - session.run("py.test", "--quiet", system_test_path, *session.posargs) - if system_test_folder_exists: - session.run("py.test", "--quiet", system_test_folder_path, *session.posargs) - - -@nox.session(python=["3.7"]) -def samples(session): - """Run the sample test suite.""" - # Sanity check: Only run tests if the environment variable is set. - if not os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""): - session.skip("Credentials must be set via environment variable") - - samples_path = "samples" - if not os.path.exists(samples_path): - session.skip("Samples not found.") - - session.install("pyyaml") - session.install("sample-tester") - for local_dep in LOCAL_DEPS: - session.install("-e", local_dep) - session.install("-e", ".") - - session.run("sample-tester", samples_path, *session.posargs) - - -@nox.session(python="3.7") -def cover(session): - """Run the final coverage report. - - This outputs the coverage report aggregating coverage from the unit - test runs (not system test runs), and then erases coverage data. - """ - session.install("coverage", "pytest-cov") - session.run("coverage", "report", "--show-missing", "--fail-under=100") - - session.run("coverage", "erase") - - -@nox.session(python="3.7") -def docs(session): - """Build the docs for this library.""" - - session.install("-e", ".") - session.install("sphinx", "alabaster", "recommonmark") - - shutil.rmtree(os.path.join("docs", "_build"), ignore_errors=True) - session.run( - "sphinx-build", - "-W", # warnings as errors - "-T", # show full traceback on exception - "-N", # no colors - "-b", - "html", - "-d", - os.path.join("docs", "_build", "doctrees", ""), - os.path.join("docs", ""), - os.path.join("docs", "_build", "html", ""), - ) diff --git a/speech/pylint.config.py b/speech/pylint.config.py deleted file mode 100644 index 5d64b9d2f256..000000000000 --- a/speech/pylint.config.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2017 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""This module is used to configure gcp-devrel-py-tools run-pylint.""" - -# Library configuration - -# library_additions = {} -# library_replacements = {} - -# Test configuration - -# test_additions = copy.deepcopy(library_additions) -# test_replacements = copy.deepcopy(library_replacements) diff --git a/speech/samples/resources/brooklyn_bridge.flac b/speech/samples/resources/brooklyn_bridge.flac deleted file mode 100644 index 0e101a55df77e426e19b4f0082fa831c94e8e5de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52410 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 diff --git a/speech/samples/resources/brooklyn_bridge.mp3 b/speech/samples/resources/brooklyn_bridge.mp3 deleted file mode 100644 index 97f9955c6f80ee61abb25328c0268189acc4bb0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29928 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
  • ?dZ^!ab%qlspp&C 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 diff --git a/speech/samples/resources/brooklyn_bridge.wav b/speech/samples/resources/brooklyn_bridge.wav deleted file mode 100644 index 044086e91411536a1e92ebbca1ead56cda37f0b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319574 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%0D7{#kWMZL|%lO;U<_4Tmchw#3zZa+&hi87l3=| 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%0DT;5p=LG z!6lFeMWsc7FD@u8_&-}xnjbup_LQ1Cwu8Pf5*~-w;A=PlUgxeb71RK|H@|_k!#!Xf z%j=m^nNm3zK7+)n#Ndo2*C~Gh8=wIEeAaB1KslVxUMcq0*r%fwcQ@Fh>$T1W_xspI z@0m4G^EG1|YYTURy1c#GyXob%FUQ_J>+XKfpSkwJ{t@d=*6Zx^uy$wvf;HrK;404R z3CD+n^VG+L#sq8Jtl2)r`Kt93>nBc!e6WT%7dXNzX-M*rOop$(T1`*5A11&k7y-A# zR9FtjplfN@(uwc^{0fe_wq~megS|01NLpeWdDSNv{E2BZ3b6Ip*^gLJ>S%-DIB@(HK5M@7GaTXMn z7nN^?P4FA+1Rwq0cGwS2!g>|;D$aueFb?K{dFw8Si^K&sW^!b5M55n!x2TpzY&}bH=nhhC&J9inU(dyTE6w0k0T!k_2&H*`zu}t{hRqgH}D=cf^<+<(_bZn zH5Pw|NAHAH5ULDSo(BVA5-fskkW!TroWDM?eJa%@)U$tqzrnR+mw-J>KSC8WrXFvzEBpdJ?gqc7o_G)rLnV0cdc)J;yxI-s#%k|f zU=|pkjE8^VjOsJ0hrn#u10Cs|dL0t}O9;-rwExuj(!RRUU@xQEtLsb~u@?0@coE#E z%Js;u*&hP$fNS4e3#l#L3C&seKN_|`i*O67HzPQ)c@_%L$KfAgCz$&cLIL~*et$mr zyUpRx(4V0>a3eH@J@I?upMe(eIlBg24HY#i*hS>ypr5N#jZTKfHH@$94IKpb3EDS# zD%g{2KZ$)Kt|^hrKpSIhW-pGtjq2w9y*=6bdo?%vLEFNm&>!vq*9j~Eug72DTAv)w z0&p$d2(Xr@4v-L^z-smL*oFEIR(QV|)GNEN*8Mf8hMwV`;b~xfHzOeTboV|QJG{qhfVveQTlR`zxZ&XT&1 zedX*udkvPs_n@EM3_rjppdRbJehVCz>tHABhCksqSPx&rr{Ma^cj0xI4tIllFZ$a1 zYwQo+&u8paq3>{?#|OaoZO_lC;2ICt+qv#jz00)$u0wH*+duEVOTWPT@De-?ULS33 zKd=Y&Z1BJreFYFo9T+GoGt3H&?lu4_$ww9j5&t^TnMj5X%N6u2Gw z!o_d~)CGGxy_dg(_jM)2`aA7!@_xS$e*HSU3XTJ9mfF3&jQ4{*gN~iHa0=81^`?WI z4*Da!5A$FqJOh*9UU2WWZqOEtJ=ANAhs-VihTX6S{sJHEy;=`yp}#|osv1@2z;JjH z=E4&A3if~#x*41Y)`WV28l|6OJ2-~D9Q+-F3=8t0oolk8|UclFc}=L&%$hY56rRmf^&L5Xp=sJ7vUbzj;jAU?(2a6cC!!b zhcFTPg6p0Bqp#d`ixc5&IKp~r*OgBOeLFu6_D0jMcz<1&Z=c;!&Vn??u{Rg;;&$-o3&4IyV-wv7&fnXnG@o43G^;JW!|!F$@Avr2A-4}exvPAnW4^n0tv zI44|3@FDnut{1TH-9CEP8aQ8Fcj?+w*Pcy)xv&!c1fC+;r>rCUO7?=A!237}-T>`P zTzp*o>2MWjpT~fENw{y_c2MtX1>M2A{4j7ou!*4m{0#KN+Wta7;tjsu8`>M3X}6E_ zMGk}Cx7N1@>`7Py-@sbf4*q>H&_ZfyKX`QC7r$2qq{88oKppNr(C@qfZ^CQf<0tSl z*!#8{Hoyn)96Siapg(knv!Ma_&-Z3LupU;y5||D4+ui~Fz}ix4u;<5GE=#R~$NHiA zsG04^7Oo2VfYi&LgO6bs`26Z;#vImy?I+$1U&CAQH24}_ARG3^?+wlsv<7V-l6B$> zfs$H$316got=T(7n~(vKasse_ks0n$A)VOe+PTemV!FaC@?m$WkL%0$ksFCDa7xoMTiC%JFKvYA^hsRe!Pr(&8Y`vj60C$bl1}i2W@8 zfnULKzXmqKVKDA*3@1Y!&{qCe`Clb%$^o=}1^vLwE0MsEXzyGXYn=ER zXp@aM)q|Yl{lNIheaN((Kf^8v_J*Jto_6$LU*eX;&F4WkP(yN`?JJ=x`2AL3?I;!8 z3uGs(0=4YN!SOQ?+^5Qz_e?ki8i2iCaZq|fX|UcwJLLW`-@r%U{td5!bz+Y+5`*0IO9xEkoXFog@JH7R8&<| ztpff3Wsn6sDt83ht$Er>a433+>htR8D=+~@zyL6}QnTiIs_TGv@|#qElt3%0A#Y9|h0AdtjX5{B*892kM{JV~r(T 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�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

    F6?itUNvlp25+3spfz>*w55iK~dO2uj-_b@dv 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

    MWMRNw8GuD4_yBvYhU`l^qpC|ZyI?+ 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 diff --git a/speech/samples/resources/hello.raw b/speech/samples/resources/hello.raw deleted file mode 100644 index b5b46450082a3ed23988c1ceefb01e98c6c63378..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16114 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 diff --git a/speech/samples/resources/hello.wav b/speech/samples/resources/hello.wav deleted file mode 100644 index 69b506936a33fcdebd27c9c22a7ef3f07d5b5a3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44494 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

    k0JOP8=dwk%uFcGi|1_P|=( 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 diff --git a/speech/samples/resources/multi.flac b/speech/samples/resources/multi.flac deleted file mode 100644 index c550e0f42a141b9ada2baa604a2d886eb194ffc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228398 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

    S_^3ADJ0ZZ)MQ@>lW{>eLB@ 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

    bX_OQxidgHmLKF-!OG z!_DR7R=u9B(Zu;bA{@#(QH9ClRvuVKwjQ4&y)|o-3S)aE23uiIkt6HWADGf5t)or7 z&3#zoOZCck%7-eZMdWpKMD|j%CNcXhN|t5aUp$vpDjL)Z`?T%d~Q0Z&t^3Y}*I5*|WUI1oqf zU~n9WMouQqXx3=~1j&Ad&=N6zyvs^B=uzAknZQvZXe9umSRw2X!)BT_E__$QR1g-7 z@C*%E2{`kD#!yCCY6HbE8W9rP5h)4?gi|OMuxSvAuK}=-F*Mr&5Jy5_G=Hh>AnQY9 z5XekKPs~YY&`73`4kPh+Hm#S#hQw@C?~ib0FhLrLpfpSmk+DG%=h>;*42DdwVX$_q znSRO+(|sfxI-TRkL)n7X96Qmah^$m;T(mOcZ-ONk4-!mp8Dp;ESpQ1`^G+0HxQ^`* zeOC|aoEb%t5pxjmVH=9Xf#5K_LQ+*YUt{N02FE0Y@)BClVUqtF3kz5Q*+dS5cMqRJu&FIS@E_y(|WW zlM>xB+0`n>L``E79JMBpy^oTW{@Na#Gvm)vxP_`$iS;4~N&J0!rJ^}3LP2J~x`7QA z<-P2=w>s)r%(NiG2ykDn%NaDQ)GGVQ^)2Oet|nM`lp(Lw%leI4>r=p>oiaKa$d<;H zbl_o45bm0#MKV(*!!s!u6hfQ9QIV#Utg+brprd4~`8iy9aR6k&e_|UjFt6zrJyV=g zqf@K>NDw5%Y}y0Cgu|s0fh9{_2_4>*Ip|1cVod@Z7|`v(Hx9Z9+}i&<42+I>fiOx! z-#EC5%&sB_heBLnsF&uo(beg`r0wanu&kS4 z0tF#ec0p7~pc>SYxym4pP%mVYf%QlywOAXd4T0jyu2N5kJ!odZNiXjpY{bc6hQ4SmoFUOD)uib(o>yMHj5W)_c*lT}3WQCoA1 zfAe9T4!v5$WHDw58%425>1>2LCKH1dUjO@J5FuKeVSbk)6m5a~;whxTfy%1Bbn0!* zSA^87Y}7a`3_zQoItAgV@`68MIdV>G*h z;Lvh+JLNc%K#4I20w|NJMgq);7j&HQu~9X{yi|x-&k__Pq)Oc57}&VJ!=|vaB|~xx z5-2Y0LPH{kP$m;i@54oSKEB4GM(_pg#hg{8n{@ z4NHAU6$q_k2%i{5W7Hy&LZIvz66r>iAyifqbRk_cMVQiUNdm;wxKP1k0OS<$6NH34 zGe~i?ltB+JP2-(;d<7Hz)O_dOLFF{=lm9q?XD*_zIcg)taYS@n z*3t}%P(Z}4`J#9ao^TLpUkPTi*H;CM8{?w}Lq84RQW`9*B)DjO(?}6e zizzZIvXvx?p-i95%Yp)BO%WP@`8WUZZvzG)OA!wM7}bad}y!5^m5_ zt$?yU)^6LYEt6BG}od-QBiXb%(JU0Q+IBuF4mD%qAr!jFm2 zBE|Oycr=pYgvlwVh@M$&ghG}U)5n?h%OuU--ahhb1&QGLM0ygA32YGpNCT?WnnAb0 z$0P`pY&4vc9aRA)q%sMrl9DPfhPY0{Fahpc=clzA8DdVkzF!vk|r$g{ccW*$YF@xGlVNgyAiu7Xe_t(=@jCU^w+?X zQzZ;5BD{-aiZ&>Ea`qG}2e03yf4{L6kgVwOg979e;6>6BfdpL9W~0VrKQ3 z2*etO;a~5<_HALRomO$#z{E~C3BkA{4ua7rguL+4844_VrFBvY`?-YHK9S5P6Zxf# zj>27Sd-8+ZOebl^hoLCkFBb#@u^2)s5Qt4(o0%D);#Wt{)jvCFh4mdgw(`D)=H^@X z2Er9wA9q&pLX%fz$Sm75RDnS&M4HHZc*9Yj{sc;}sME)iS~MS6Hc;&YhU$Hmp*GYn zVvgG?VeLgHss2&E6tZGlUm8qfqNUC*k${l0Wsk5H8eEni8U9{g(5Kb}wbo(~k`&^G zBKaK&W>%5~j%xXkse@_PRgu;r0oN9iIysIUy+5~XXAE<6IzdN;fitD{!Nf|LB!wwr z5l509QI622e5zqU7EaRvy^njCQEB%A>OOBNV?>rWnyrwS zn5`i8S89D(7EnK!g6P%N3L*m{Wsx5&sS$vPXo^o66f8x5S4YWt4!_EGox7%D%`PO? zrr|uLRcu(8v**Z#Upa%u!1}BI_*n=rtVRJ+0bBt*0X63=8u!pDTx8H|5wN}#Da_); z)QnDz1c0<(%C+g0%^=uGO(hJo*>q$Mjna8MLWq7-t92!*$jNs`t(i(YSf!y-jpM5n zUdqLTf zWZfT4jday3L@UwXigx#7YZX5yhjf40y~$UE*BVRV?sR3$9bfQy3WWpu~PrfKzP-rAklE(;&iQNiTk)p3` zRoR{^Y?^X8Ypz6@RwZbGn}@~<7ZVW*CP2Z}NoR=-Dbi&>hYU<_Kwvc~s6qwJjtKy;mCHJuPSKUn44LoKE*Ubv<{7{9 zA$zdeWKG=>qK*-mm#X1yD;C#ikR%J!3lxeg?6_z)2r6X$VRkU41x4U0+x5Xq2Bu@? z@` z>4zT|hs;@$wMKP1C1nM?Get@hNACp2b+WhuNr^pzQ~KLrVsjWcap4UY6ID{q#~p;h zM=<;M%IOW443J2{yBNBZDk4aQl00OrxVt*=*AdC z@be=L1R?^Y-@?MAL-RF)7Yj&~oBdGkim%77ojf2|O=37Xey@Z!#0_x+NZP1rDA>WG zLBl3WuqYIKVhk||XkwS8qDF;J;CNYR=0f3I;W`&YC{L4<<@WmmVn!TavBsiGVE2bE zJc?xvfKKAzCN9{IkE=tp5P{^pMgsXATq4+jdvVgG5_gVSA3EYn=(fNb)#Ap{73VoA5Gg4qjBBoBn zz`-mh_>`gfTwbB|L6FKwD3jlOQ)~VqhAbu#YIux|iD*7KX`9L+A1Os#)4j3E~ zTgHtQK|%=_3Kq>+z z#2#5^j}&BMRxeP{*xpel!P#92D#RWTB|^o9!L_$G_JHv!B~V1Z?hdXXG}af08Fs2U z7qq~2FcVe*lrB`qn4JA{xWZy_@sq!e2`myI5eQs@%-^@onE_`>kZhr}1$c2Gg}qFK zj07A8S0)q=mExmeGAxK6ilI-EEfdGsCb){ZLdD1gikOlO*&&`~0dS~#rGDFvOo+0_ zlq`QtK#sQhb43m2n-v=PMr!4)T$f`jYcFxfH(x9j!3vr5abNh5&ut79M)ESt*08n} z;toGUjrut%RSTPwcRs0;V0?|8ZF^$AMO-3hId(H5>713>w4_foUXkrH%FPdn6(Uo0 zY`Fed$W?epZyfs~g&vcpY^oWhE7MbA0#+z3o5=QcDy#}qf)7G6XT>*#iA}2;kvQB} z_SDi=-nwUe?&a$n`|7=|ze|X8Ush8Uqh0DOvwLdJNLy^~?doLaBh^(}lTHjvnG(`) zp4oE3`XS=#Bbww@Syq_U?=Kj5@RKSgNfLxCUGx@Gau{CxXp)MwhHA_1RY`8|cWGim{fhs1` zoGgvm6kOsmFax3u3f#tj9nlJf z>)lT;T%}3ikcz}7aTK64<#rpoYhB3jg#o)5mL$BB_3z66BCeHHWlSXWRI~0Q>wU26 zuC#+zc^8&_<>v*@ElQWu&%Jpvf+%p{vkX-AJH-AQI_byJB(!vg*5}F?ppnF@6ct_U zsk1>x1QH{aBGERIGe-?REU}NAE~il_$2K^ugn+9LAV7#@2wXr1221|~#nl~6l|xgF z2Ays0$V3(+nRJt4N?>SUE8jRASDh|Vw83+A!G4b>B^=Qc1VT#zbIWM_j4cPS*>+;> z$dxUqVCJIWZF-^!m2F}I6>Gow6Jc>;*%Aok(2%Aa8S*0~cp@uw`?QwqdOUDSf($$c z2m(H-hK+)=cd%@rfk20@NMYjuNWkDd9Xs|*_H(qt-G>?zV3p+NNHUTsyM#-X|9CCL zMbwgxuh4yP%ElHz$W(`n0abw@3G0gFJ61~6MB$czM)hh$pFMV8CL|(o*ol3MzL`;W z$4r`F(69>VB%SzC9jprwT=1$@S8w~CE}2otSy6vJalsCh6f=MXQA$M6XzK({3Y%f8 zh~^kE=6!3Nms@rGY3cr`K5_3(;@hYr2}$05=E9|GP6dLV#2XSL~15n9Za#C z2o0PgFJwyu0|gj$W?t7D*y9VFD&EK}fv2*-DCwummUMYVL^{cHbs*>7)sZuUW-+DIl9)au;AoB0PB|?CJUKJ0ZeKERZ_UGN&s0)fxjGw8y zS$zG)c*5EulZ7_tk-PFuKC@#5{z6}h7#G^Hnx_U6rQOa-w)$mL>%Ljjy0>_wEdNZG z7vM;S?-GAfik-&e_}+X-hBa6w)@YTcCWS8*F+|l-T|3_Ts|FaKm1j~4+>}aCzhB(! zrn71OOI&E@@@~E=@q)h_F){7FSMyr#j^c!`S+{IMZWCLft#}{Y?MC~1oI_fWXBl`x(=T{m%IGIKu) zSfbp8gIpHqo=727Ke5J`;k6jM{AY=u^5YS!OqTULt5xWZu zwqIG@ruxo+T-ZtCmpDZ#3Xhg)U9=$atIa87T{w?^y7J75h)@>u0I?-9`l^w4e$!lzWDV|!~%Q--tvSVYcPDn_hWU6!@G>zzs{&o4$e#Hd}Gr-YBB>LGh%6iN!Byr`* zbKNKKr&Ce{5G2ej!)oNZ!#3)=qP18cQ?`F4Q4<0h$hRh!8rL;QiCx1h`DdOE2w@Bu zCLvyaBNBJ*%CnIBln(HZYG>mk+fZD>)*0m`31L!@-9%iWtZ4Vi5+q?IKT<)$oe}Q6 zvtQ8@F?vXq28k7|ZMt7k7VN3OZemunm&C!4<=TW;qx;F`q>a<1=U z;(a^2+a!rbP-6(=Bqr=r!O+QCX3UpT$4N9 zXwKSoh;@2}JKWVXmRWB!?NWOOj2vp>hPq~!p2}<#RFznvJ)rtp|M+K$k_h`!uf3^8WN!uSxiLbTh~+3is>q8GlTd<>liv9u zeuY+t+9*^v&lCRqubne#5iT|sD#5f+Ndz)5&e2Lg5hC?Fb3!7ks5YXz+vOs-=an7k zaQ5P4)%_1ubHY1bW<8AV4HU^o((|LQGC-DznZTQGE$xlaW26rDXpL8FUs{>t8?xp^ z2;9%5xPI}?Z4$%o4!Uz>Z4xkSW4dpO^X5W!bFHFe4VOuJ%j3$lXy&C|7^p7N-mbS5 z2iMZ#2&lV;F<*q< z`khZrZw7eNNswjN6|cq3L-wHOV<$@DThIt zHdqR@rAPK5gBfh*#S7!9lvq zOL>2WSaR{Bw5lEFixP5aKBAg>u#D9qAwNC}nUZFnPLib{bp-lhGR$Pfb%K0b)Auz* zSgGff_csQN2_=pZn`M1qsMuMa!w!5WGI699dwbR5i4yJs9Aq9PqUOyZRg|uyI=o^ zS5{$@EV%02-~aL#TBY5O*dvBNL;@5g3q1K`lVr&_OS72jkZ?gw7?-xM_$NGQMAuda z@6Aoka6WX8%@!!=dlKv3SJ6yVc{-MM&bIFr9~f=&C*DkI-%+o4GZR-meURj|jLG7{ zc2q`XhuySSQEuCp!2fOjhVm$`_RJ?%!Akv!-^UtrukDeY1m0uU1;uV7-DhN~X3Zr? zBrap0TA4)3%8hA;yQHlveCgGJVnvDPNuqUF#DeM1#pIh-h?jV)Q=E)~Vt>R<2ck9w zYEEMkPDS9J*R%_B*8qrX-V&~7d!$`mhqb=QX{rGgLQ+26#VX`Th6d9?g~z4wD z29Yeu!z5g;L4$nkC*kFkm1fHY)G%FU=-Er%8cnyfBu!@4TuHt~7>c0EV1$Yk?<>i0 zkspl{H>(_3G%|jL<9eJwjO!GZ*rFmVDIus)JU=xI7!|YsbExY`m=-57?hbw_DB#*D z^IosGf2Ga}EYR*cn4Ld^3K>O;n{?cdjc_#ZPVDW{yBE7mPXVje9B!yWF2YYSIWHq? z(VvP|cRh0P+E`6qn2^#=y9U-tGIZ>6j3eLsm721y)Q_m`SyKhOA={hjF^LD-B=N$~ Mmue_+hWr4-ko57%JOBUy diff --git a/speech/samples/resources/multi.wav b/speech/samples/resources/multi.wav deleted file mode 100644 index 7f71d74b951aefe19081ee8ca7d0d5bac0d45ace..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 909356 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

    qbERXVxEm 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%0D&= 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