koichi12 commited on
Commit
a189997
·
verified ·
1 Parent(s): bcfd742

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +2 -0
  2. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/__pycache__/__init__.cpython-311.pyc +0 -0
  3. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/__pycache__/gapic_version.cpython-311.pyc +0 -0
  4. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/gapic_metadata.json +152 -0
  5. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/gapic_version.py +16 -0
  6. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/py.typed +2 -0
  7. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/__init__.py +15 -0
  8. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/__init__.py +22 -0
  9. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/__pycache__/async_client.cpython-311.pyc +0 -0
  10. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/async_client.py +1150 -0
  11. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/client.py +1529 -0
  12. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/transports/__pycache__/grpc.cpython-311.pyc +0 -0
  13. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/transports/rest.py +1643 -0
  14. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/transports/rest_base.py +484 -0
  15. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/__init__.cpython-311.pyc +0 -0
  16. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/async_client.cpython-311.pyc +0 -0
  17. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/client.cpython-311.pyc +0 -0
  18. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/pagers.cpython-311.pyc +0 -0
  19. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/__init__.cpython-311.pyc +0 -0
  20. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/citation.cpython-311.pyc +0 -0
  21. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/content.cpython-311.pyc +0 -0
  22. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/model.cpython-311.pyc +0 -0
  23. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/model.py +171 -0
  24. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/__pycache__/__init__.cpython-311.pyc +0 -0
  25. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/__pycache__/gapic_version.cpython-311.pyc +0 -0
  26. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/__pycache__/__init__.cpython-311.pyc +0 -0
  27. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/__pycache__/client.cpython-311.pyc +0 -0
  28. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/__pycache__/pagers.cpython-311.pyc +0 -0
  29. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/transports/__pycache__/rest_base.cpython-311.pyc +0 -0
  30. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/__pycache__/client.cpython-311.pyc +3 -0
  31. .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc +3 -0
  32. .venv/lib/python3.11/site-packages/google/api_core/__init__.py +22 -0
  33. .venv/lib/python3.11/site-packages/google/api_core/__pycache__/bidi.cpython-311.pyc +0 -0
  34. .venv/lib/python3.11/site-packages/google/api_core/__pycache__/client_options.cpython-311.pyc +0 -0
  35. .venv/lib/python3.11/site-packages/google/api_core/__pycache__/operation.cpython-311.pyc +0 -0
  36. .venv/lib/python3.11/site-packages/google/api_core/__pycache__/page_iterator.cpython-311.pyc +0 -0
  37. .venv/lib/python3.11/site-packages/google/api_core/__pycache__/rest_helpers.cpython-311.pyc +0 -0
  38. .venv/lib/python3.11/site-packages/google/api_core/__pycache__/retry_async.cpython-311.pyc +0 -0
  39. .venv/lib/python3.11/site-packages/google/api_core/__pycache__/version.cpython-311.pyc +0 -0
  40. .venv/lib/python3.11/site-packages/google/api_core/_rest_streaming_base.py +118 -0
  41. .venv/lib/python3.11/site-packages/google/api_core/bidi.py +743 -0
  42. .venv/lib/python3.11/site-packages/google/api_core/client_info.py +108 -0
  43. .venv/lib/python3.11/site-packages/google/api_core/client_logging.py +144 -0
  44. .venv/lib/python3.11/site-packages/google/api_core/client_options.py +141 -0
  45. .venv/lib/python3.11/site-packages/google/api_core/datetime_helpers.py +298 -0
  46. .venv/lib/python3.11/site-packages/google/api_core/exceptions.py +670 -0
  47. .venv/lib/python3.11/site-packages/google/api_core/extended_operation.py +225 -0
  48. .venv/lib/python3.11/site-packages/google/api_core/general_helpers.py +16 -0
  49. .venv/lib/python3.11/site-packages/google/api_core/grpc_helpers.py +622 -0
  50. .venv/lib/python3.11/site-packages/google/api_core/grpc_helpers_async.py +331 -0
.gitattributes CHANGED
@@ -194,3 +194,5 @@ tuning-competition-baseline/.venv/lib/python3.11/site-packages/torch/_inductor/_
194
  .venv/lib/python3.11/site-packages/pillow.libs/libharfbuzz-89381d8f.so.0.60850.0 filter=lfs diff=lfs merge=lfs -text
195
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1alpha/services/retriever_service/__pycache__/client.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
196
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1alpha/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
 
 
 
194
  .venv/lib/python3.11/site-packages/pillow.libs/libharfbuzz-89381d8f.so.0.60850.0 filter=lfs diff=lfs merge=lfs -text
195
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1alpha/services/retriever_service/__pycache__/client.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
196
  .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1alpha/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
197
+ .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
198
+ .venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/__pycache__/client.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (2.13 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/__pycache__/gapic_version.cpython-311.pyc ADDED
Binary file (232 Bytes). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/gapic_metadata.json ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "comment": "This file maps proto services/RPCs to the corresponding library clients/methods",
3
+ "language": "python",
4
+ "libraryPackage": "google.ai.generativelanguage_v1",
5
+ "protoPackage": "google.ai.generativelanguage.v1",
6
+ "schema": "1.0",
7
+ "services": {
8
+ "GenerativeService": {
9
+ "clients": {
10
+ "grpc": {
11
+ "libraryClient": "GenerativeServiceClient",
12
+ "rpcs": {
13
+ "BatchEmbedContents": {
14
+ "methods": [
15
+ "batch_embed_contents"
16
+ ]
17
+ },
18
+ "CountTokens": {
19
+ "methods": [
20
+ "count_tokens"
21
+ ]
22
+ },
23
+ "EmbedContent": {
24
+ "methods": [
25
+ "embed_content"
26
+ ]
27
+ },
28
+ "GenerateContent": {
29
+ "methods": [
30
+ "generate_content"
31
+ ]
32
+ },
33
+ "StreamGenerateContent": {
34
+ "methods": [
35
+ "stream_generate_content"
36
+ ]
37
+ }
38
+ }
39
+ },
40
+ "grpc-async": {
41
+ "libraryClient": "GenerativeServiceAsyncClient",
42
+ "rpcs": {
43
+ "BatchEmbedContents": {
44
+ "methods": [
45
+ "batch_embed_contents"
46
+ ]
47
+ },
48
+ "CountTokens": {
49
+ "methods": [
50
+ "count_tokens"
51
+ ]
52
+ },
53
+ "EmbedContent": {
54
+ "methods": [
55
+ "embed_content"
56
+ ]
57
+ },
58
+ "GenerateContent": {
59
+ "methods": [
60
+ "generate_content"
61
+ ]
62
+ },
63
+ "StreamGenerateContent": {
64
+ "methods": [
65
+ "stream_generate_content"
66
+ ]
67
+ }
68
+ }
69
+ },
70
+ "rest": {
71
+ "libraryClient": "GenerativeServiceClient",
72
+ "rpcs": {
73
+ "BatchEmbedContents": {
74
+ "methods": [
75
+ "batch_embed_contents"
76
+ ]
77
+ },
78
+ "CountTokens": {
79
+ "methods": [
80
+ "count_tokens"
81
+ ]
82
+ },
83
+ "EmbedContent": {
84
+ "methods": [
85
+ "embed_content"
86
+ ]
87
+ },
88
+ "GenerateContent": {
89
+ "methods": [
90
+ "generate_content"
91
+ ]
92
+ },
93
+ "StreamGenerateContent": {
94
+ "methods": [
95
+ "stream_generate_content"
96
+ ]
97
+ }
98
+ }
99
+ }
100
+ }
101
+ },
102
+ "ModelService": {
103
+ "clients": {
104
+ "grpc": {
105
+ "libraryClient": "ModelServiceClient",
106
+ "rpcs": {
107
+ "GetModel": {
108
+ "methods": [
109
+ "get_model"
110
+ ]
111
+ },
112
+ "ListModels": {
113
+ "methods": [
114
+ "list_models"
115
+ ]
116
+ }
117
+ }
118
+ },
119
+ "grpc-async": {
120
+ "libraryClient": "ModelServiceAsyncClient",
121
+ "rpcs": {
122
+ "GetModel": {
123
+ "methods": [
124
+ "get_model"
125
+ ]
126
+ },
127
+ "ListModels": {
128
+ "methods": [
129
+ "list_models"
130
+ ]
131
+ }
132
+ }
133
+ },
134
+ "rest": {
135
+ "libraryClient": "ModelServiceClient",
136
+ "rpcs": {
137
+ "GetModel": {
138
+ "methods": [
139
+ "get_model"
140
+ ]
141
+ },
142
+ "ListModels": {
143
+ "methods": [
144
+ "list_models"
145
+ ]
146
+ }
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/gapic_version.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ __version__ = "0.6.15" # {x-release-please-version}
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/py.typed ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # Marker file for PEP 561.
2
+ # The google-ai-generativelanguage package uses inline types.
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/__init__.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/__init__.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ from .async_client import GenerativeServiceAsyncClient
17
+ from .client import GenerativeServiceClient
18
+
19
+ __all__ = (
20
+ "GenerativeServiceClient",
21
+ "GenerativeServiceAsyncClient",
22
+ )
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/__pycache__/async_client.cpython-311.pyc ADDED
Binary file (47 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/async_client.py ADDED
@@ -0,0 +1,1150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ from collections import OrderedDict
17
+ import logging as std_logging
18
+ import re
19
+ from typing import (
20
+ AsyncIterable,
21
+ Awaitable,
22
+ Callable,
23
+ Dict,
24
+ Mapping,
25
+ MutableMapping,
26
+ MutableSequence,
27
+ Optional,
28
+ Sequence,
29
+ Tuple,
30
+ Type,
31
+ Union,
32
+ )
33
+
34
+ from google.api_core import exceptions as core_exceptions
35
+ from google.api_core import gapic_v1
36
+ from google.api_core import retry_async as retries
37
+ from google.api_core.client_options import ClientOptions
38
+ from google.auth import credentials as ga_credentials # type: ignore
39
+ from google.oauth2 import service_account # type: ignore
40
+
41
+ from google.ai.generativelanguage_v1 import gapic_version as package_version
42
+
43
+ try:
44
+ OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None]
45
+ except AttributeError: # pragma: NO COVER
46
+ OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore
47
+
48
+ from google.longrunning import operations_pb2 # type: ignore
49
+
50
+ from google.ai.generativelanguage_v1.types import content
51
+ from google.ai.generativelanguage_v1.types import content as gag_content
52
+ from google.ai.generativelanguage_v1.types import generative_service
53
+
54
+ from .client import GenerativeServiceClient
55
+ from .transports.base import DEFAULT_CLIENT_INFO, GenerativeServiceTransport
56
+ from .transports.grpc_asyncio import GenerativeServiceGrpcAsyncIOTransport
57
+
58
+ try:
59
+ from google.api_core import client_logging # type: ignore
60
+
61
+ CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
62
+ except ImportError: # pragma: NO COVER
63
+ CLIENT_LOGGING_SUPPORTED = False
64
+
65
+ _LOGGER = std_logging.getLogger(__name__)
66
+
67
+
68
+ class GenerativeServiceAsyncClient:
69
+ """API for using Large Models that generate multimodal content
70
+ and have additional capabilities beyond text generation.
71
+ """
72
+
73
+ _client: GenerativeServiceClient
74
+
75
+ # Copy defaults from the synchronous client for use here.
76
+ # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead.
77
+ DEFAULT_ENDPOINT = GenerativeServiceClient.DEFAULT_ENDPOINT
78
+ DEFAULT_MTLS_ENDPOINT = GenerativeServiceClient.DEFAULT_MTLS_ENDPOINT
79
+ _DEFAULT_ENDPOINT_TEMPLATE = GenerativeServiceClient._DEFAULT_ENDPOINT_TEMPLATE
80
+ _DEFAULT_UNIVERSE = GenerativeServiceClient._DEFAULT_UNIVERSE
81
+
82
+ model_path = staticmethod(GenerativeServiceClient.model_path)
83
+ parse_model_path = staticmethod(GenerativeServiceClient.parse_model_path)
84
+ common_billing_account_path = staticmethod(
85
+ GenerativeServiceClient.common_billing_account_path
86
+ )
87
+ parse_common_billing_account_path = staticmethod(
88
+ GenerativeServiceClient.parse_common_billing_account_path
89
+ )
90
+ common_folder_path = staticmethod(GenerativeServiceClient.common_folder_path)
91
+ parse_common_folder_path = staticmethod(
92
+ GenerativeServiceClient.parse_common_folder_path
93
+ )
94
+ common_organization_path = staticmethod(
95
+ GenerativeServiceClient.common_organization_path
96
+ )
97
+ parse_common_organization_path = staticmethod(
98
+ GenerativeServiceClient.parse_common_organization_path
99
+ )
100
+ common_project_path = staticmethod(GenerativeServiceClient.common_project_path)
101
+ parse_common_project_path = staticmethod(
102
+ GenerativeServiceClient.parse_common_project_path
103
+ )
104
+ common_location_path = staticmethod(GenerativeServiceClient.common_location_path)
105
+ parse_common_location_path = staticmethod(
106
+ GenerativeServiceClient.parse_common_location_path
107
+ )
108
+
109
+ @classmethod
110
+ def from_service_account_info(cls, info: dict, *args, **kwargs):
111
+ """Creates an instance of this client using the provided credentials
112
+ info.
113
+
114
+ Args:
115
+ info (dict): The service account private key info.
116
+ args: Additional arguments to pass to the constructor.
117
+ kwargs: Additional arguments to pass to the constructor.
118
+
119
+ Returns:
120
+ GenerativeServiceAsyncClient: The constructed client.
121
+ """
122
+ return GenerativeServiceClient.from_service_account_info.__func__(GenerativeServiceAsyncClient, info, *args, **kwargs) # type: ignore
123
+
124
+ @classmethod
125
+ def from_service_account_file(cls, filename: str, *args, **kwargs):
126
+ """Creates an instance of this client using the provided credentials
127
+ file.
128
+
129
+ Args:
130
+ filename (str): The path to the service account private key json
131
+ file.
132
+ args: Additional arguments to pass to the constructor.
133
+ kwargs: Additional arguments to pass to the constructor.
134
+
135
+ Returns:
136
+ GenerativeServiceAsyncClient: The constructed client.
137
+ """
138
+ return GenerativeServiceClient.from_service_account_file.__func__(GenerativeServiceAsyncClient, filename, *args, **kwargs) # type: ignore
139
+
140
+ from_service_account_json = from_service_account_file
141
+
142
+ @classmethod
143
+ def get_mtls_endpoint_and_cert_source(
144
+ cls, client_options: Optional[ClientOptions] = None
145
+ ):
146
+ """Return the API endpoint and client cert source for mutual TLS.
147
+
148
+ The client cert source is determined in the following order:
149
+ (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
150
+ client cert source is None.
151
+ (2) if `client_options.client_cert_source` is provided, use the provided one; if the
152
+ default client cert source exists, use the default one; otherwise the client cert
153
+ source is None.
154
+
155
+ The API endpoint is determined in the following order:
156
+ (1) if `client_options.api_endpoint` if provided, use the provided one.
157
+ (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
158
+ default mTLS endpoint; if the environment variable is "never", use the default API
159
+ endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
160
+ use the default API endpoint.
161
+
162
+ More details can be found at https://google.aip.dev/auth/4114.
163
+
164
+ Args:
165
+ client_options (google.api_core.client_options.ClientOptions): Custom options for the
166
+ client. Only the `api_endpoint` and `client_cert_source` properties may be used
167
+ in this method.
168
+
169
+ Returns:
170
+ Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
171
+ client cert source to use.
172
+
173
+ Raises:
174
+ google.auth.exceptions.MutualTLSChannelError: If any errors happen.
175
+ """
176
+ return GenerativeServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore
177
+
178
+ @property
179
+ def transport(self) -> GenerativeServiceTransport:
180
+ """Returns the transport used by the client instance.
181
+
182
+ Returns:
183
+ GenerativeServiceTransport: The transport used by the client instance.
184
+ """
185
+ return self._client.transport
186
+
187
+ @property
188
+ def api_endpoint(self):
189
+ """Return the API endpoint used by the client instance.
190
+
191
+ Returns:
192
+ str: The API endpoint used by the client instance.
193
+ """
194
+ return self._client._api_endpoint
195
+
196
+ @property
197
+ def universe_domain(self) -> str:
198
+ """Return the universe domain used by the client instance.
199
+
200
+ Returns:
201
+ str: The universe domain used
202
+ by the client instance.
203
+ """
204
+ return self._client._universe_domain
205
+
206
+ get_transport_class = GenerativeServiceClient.get_transport_class
207
+
208
+ def __init__(
209
+ self,
210
+ *,
211
+ credentials: Optional[ga_credentials.Credentials] = None,
212
+ transport: Optional[
213
+ Union[
214
+ str,
215
+ GenerativeServiceTransport,
216
+ Callable[..., GenerativeServiceTransport],
217
+ ]
218
+ ] = "grpc_asyncio",
219
+ client_options: Optional[ClientOptions] = None,
220
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
221
+ ) -> None:
222
+ """Instantiates the generative service async client.
223
+
224
+ Args:
225
+ credentials (Optional[google.auth.credentials.Credentials]): The
226
+ authorization credentials to attach to requests. These
227
+ credentials identify the application to the service; if none
228
+ are specified, the client will attempt to ascertain the
229
+ credentials from the environment.
230
+ transport (Optional[Union[str,GenerativeServiceTransport,Callable[..., GenerativeServiceTransport]]]):
231
+ The transport to use, or a Callable that constructs and returns a new transport to use.
232
+ If a Callable is given, it will be called with the same set of initialization
233
+ arguments as used in the GenerativeServiceTransport constructor.
234
+ If set to None, a transport is chosen automatically.
235
+ client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]):
236
+ Custom options for the client.
237
+
238
+ 1. The ``api_endpoint`` property can be used to override the
239
+ default endpoint provided by the client when ``transport`` is
240
+ not explicitly provided. Only if this property is not set and
241
+ ``transport`` was not explicitly provided, the endpoint is
242
+ determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment
243
+ variable, which have one of the following values:
244
+ "always" (always use the default mTLS endpoint), "never" (always
245
+ use the default regular endpoint) and "auto" (auto-switch to the
246
+ default mTLS endpoint if client certificate is present; this is
247
+ the default value).
248
+
249
+ 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
250
+ is "true", then the ``client_cert_source`` property can be used
251
+ to provide a client certificate for mTLS transport. If
252
+ not provided, the default SSL client certificate will be used if
253
+ present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
254
+ set, no client certificate will be used.
255
+
256
+ 3. The ``universe_domain`` property can be used to override the
257
+ default "googleapis.com" universe. Note that ``api_endpoint``
258
+ property still takes precedence; and ``universe_domain`` is
259
+ currently not supported for mTLS.
260
+
261
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
262
+ The client info used to send a user-agent string along with
263
+ API requests. If ``None``, then default info will be used.
264
+ Generally, you only need to set this if you're developing
265
+ your own client library.
266
+
267
+ Raises:
268
+ google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport
269
+ creation failed for any reason.
270
+ """
271
+ self._client = GenerativeServiceClient(
272
+ credentials=credentials,
273
+ transport=transport,
274
+ client_options=client_options,
275
+ client_info=client_info,
276
+ )
277
+
278
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
279
+ std_logging.DEBUG
280
+ ): # pragma: NO COVER
281
+ _LOGGER.debug(
282
+ "Created client `google.ai.generativelanguage_v1.GenerativeServiceAsyncClient`.",
283
+ extra={
284
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
285
+ "universeDomain": getattr(
286
+ self._client._transport._credentials, "universe_domain", ""
287
+ ),
288
+ "credentialsType": f"{type(self._client._transport._credentials).__module__}.{type(self._client._transport._credentials).__qualname__}",
289
+ "credentialsInfo": getattr(
290
+ self.transport._credentials, "get_cred_info", lambda: None
291
+ )(),
292
+ }
293
+ if hasattr(self._client._transport, "_credentials")
294
+ else {
295
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
296
+ "credentialsType": None,
297
+ },
298
+ )
299
+
300
+ async def generate_content(
301
+ self,
302
+ request: Optional[
303
+ Union[generative_service.GenerateContentRequest, dict]
304
+ ] = None,
305
+ *,
306
+ model: Optional[str] = None,
307
+ contents: Optional[MutableSequence[content.Content]] = None,
308
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
309
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
310
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
311
+ ) -> generative_service.GenerateContentResponse:
312
+ r"""Generates a model response given an input
313
+ ``GenerateContentRequest``. Refer to the `text generation
314
+ guide <https://ai.google.dev/gemini-api/docs/text-generation>`__
315
+ for detailed usage information. Input capabilities differ
316
+ between models, including tuned models. Refer to the `model
317
+ guide <https://ai.google.dev/gemini-api/docs/models/gemini>`__
318
+ and `tuning
319
+ guide <https://ai.google.dev/gemini-api/docs/model-tuning>`__
320
+ for details.
321
+
322
+ .. code-block:: python
323
+
324
+ # This snippet has been automatically generated and should be regarded as a
325
+ # code template only.
326
+ # It will require modifications to work:
327
+ # - It may require correct/in-range values for request initialization.
328
+ # - It may require specifying regional endpoints when creating the service
329
+ # client as shown in:
330
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
331
+ from google.ai import generativelanguage_v1
332
+
333
+ async def sample_generate_content():
334
+ # Create a client
335
+ client = generativelanguage_v1.GenerativeServiceAsyncClient()
336
+
337
+ # Initialize request argument(s)
338
+ request = generativelanguage_v1.GenerateContentRequest(
339
+ model="model_value",
340
+ )
341
+
342
+ # Make the request
343
+ response = await client.generate_content(request=request)
344
+
345
+ # Handle the response
346
+ print(response)
347
+
348
+ Args:
349
+ request (Optional[Union[google.ai.generativelanguage_v1.types.GenerateContentRequest, dict]]):
350
+ The request object. Request to generate a completion from
351
+ the model.
352
+ model (:class:`str`):
353
+ Required. The name of the ``Model`` to use for
354
+ generating the completion.
355
+
356
+ Format: ``models/{model}``.
357
+
358
+ This corresponds to the ``model`` field
359
+ on the ``request`` instance; if ``request`` is provided, this
360
+ should not be set.
361
+ contents (:class:`MutableSequence[google.ai.generativelanguage_v1.types.Content]`):
362
+ Required. The content of the current conversation with
363
+ the model.
364
+
365
+ For single-turn queries, this is a single instance. For
366
+ multi-turn queries like
367
+ `chat <https://ai.google.dev/gemini-api/docs/text-generation#chat>`__,
368
+ this is a repeated field that contains the conversation
369
+ history and the latest request.
370
+
371
+ This corresponds to the ``contents`` field
372
+ on the ``request`` instance; if ``request`` is provided, this
373
+ should not be set.
374
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
375
+ should be retried.
376
+ timeout (float): The timeout for this request.
377
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
378
+ sent along with the request as metadata. Normally, each value must be of type `str`,
379
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
380
+ be of type `bytes`.
381
+
382
+ Returns:
383
+ google.ai.generativelanguage_v1.types.GenerateContentResponse:
384
+ Response from the model supporting multiple candidate
385
+ responses.
386
+
387
+ Safety ratings and content filtering are reported for
388
+ both prompt in
389
+ GenerateContentResponse.prompt_feedback and for each
390
+ candidate in finish_reason and in safety_ratings. The
391
+ API: - Returns either all requested candidates or
392
+ none of them - Returns no candidates at all only if
393
+ there was something wrong with the prompt (check
394
+ prompt_feedback) - Reports feedback on each candidate
395
+ in finish_reason and safety_ratings.
396
+
397
+ """
398
+ # Create or coerce a protobuf request object.
399
+ # - Quick check: If we got a request object, we should *not* have
400
+ # gotten any keyword arguments that map to the request.
401
+ has_flattened_params = any([model, contents])
402
+ if request is not None and has_flattened_params:
403
+ raise ValueError(
404
+ "If the `request` argument is set, then none of "
405
+ "the individual field arguments should be set."
406
+ )
407
+
408
+ # - Use the request object if provided (there's no risk of modifying the input as
409
+ # there are no flattened fields), or create one.
410
+ if not isinstance(request, generative_service.GenerateContentRequest):
411
+ request = generative_service.GenerateContentRequest(request)
412
+
413
+ # If we have keyword arguments corresponding to fields on the
414
+ # request, apply these.
415
+ if model is not None:
416
+ request.model = model
417
+ if contents:
418
+ request.contents.extend(contents)
419
+
420
+ # Wrap the RPC method; this adds retry and timeout information,
421
+ # and friendly error handling.
422
+ rpc = self._client._transport._wrapped_methods[
423
+ self._client._transport.generate_content
424
+ ]
425
+
426
+ # Certain fields should be provided within the metadata header;
427
+ # add these here.
428
+ metadata = tuple(metadata) + (
429
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
430
+ )
431
+
432
+ # Validate the universe domain.
433
+ self._client._validate_universe_domain()
434
+
435
+ # Send the request.
436
+ response = await rpc(
437
+ request,
438
+ retry=retry,
439
+ timeout=timeout,
440
+ metadata=metadata,
441
+ )
442
+
443
+ # Done; return the response.
444
+ return response
445
+
446
+ def stream_generate_content(
447
+ self,
448
+ request: Optional[
449
+ Union[generative_service.GenerateContentRequest, dict]
450
+ ] = None,
451
+ *,
452
+ model: Optional[str] = None,
453
+ contents: Optional[MutableSequence[content.Content]] = None,
454
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
455
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
456
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
457
+ ) -> Awaitable[AsyncIterable[generative_service.GenerateContentResponse]]:
458
+ r"""Generates a `streamed
459
+ response <https://ai.google.dev/gemini-api/docs/text-generation?lang=python#generate-a-text-stream>`__
460
+ from the model given an input ``GenerateContentRequest``.
461
+
462
+ .. code-block:: python
463
+
464
+ # This snippet has been automatically generated and should be regarded as a
465
+ # code template only.
466
+ # It will require modifications to work:
467
+ # - It may require correct/in-range values for request initialization.
468
+ # - It may require specifying regional endpoints when creating the service
469
+ # client as shown in:
470
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
471
+ from google.ai import generativelanguage_v1
472
+
473
+ async def sample_stream_generate_content():
474
+ # Create a client
475
+ client = generativelanguage_v1.GenerativeServiceAsyncClient()
476
+
477
+ # Initialize request argument(s)
478
+ request = generativelanguage_v1.GenerateContentRequest(
479
+ model="model_value",
480
+ )
481
+
482
+ # Make the request
483
+ stream = await client.stream_generate_content(request=request)
484
+
485
+ # Handle the response
486
+ async for response in stream:
487
+ print(response)
488
+
489
+ Args:
490
+ request (Optional[Union[google.ai.generativelanguage_v1.types.GenerateContentRequest, dict]]):
491
+ The request object. Request to generate a completion from
492
+ the model.
493
+ model (:class:`str`):
494
+ Required. The name of the ``Model`` to use for
495
+ generating the completion.
496
+
497
+ Format: ``models/{model}``.
498
+
499
+ This corresponds to the ``model`` field
500
+ on the ``request`` instance; if ``request`` is provided, this
501
+ should not be set.
502
+ contents (:class:`MutableSequence[google.ai.generativelanguage_v1.types.Content]`):
503
+ Required. The content of the current conversation with
504
+ the model.
505
+
506
+ For single-turn queries, this is a single instance. For
507
+ multi-turn queries like
508
+ `chat <https://ai.google.dev/gemini-api/docs/text-generation#chat>`__,
509
+ this is a repeated field that contains the conversation
510
+ history and the latest request.
511
+
512
+ This corresponds to the ``contents`` field
513
+ on the ``request`` instance; if ``request`` is provided, this
514
+ should not be set.
515
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
516
+ should be retried.
517
+ timeout (float): The timeout for this request.
518
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
519
+ sent along with the request as metadata. Normally, each value must be of type `str`,
520
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
521
+ be of type `bytes`.
522
+
523
+ Returns:
524
+ AsyncIterable[google.ai.generativelanguage_v1.types.GenerateContentResponse]:
525
+ Response from the model supporting multiple candidate
526
+ responses.
527
+
528
+ Safety ratings and content filtering are reported for
529
+ both prompt in
530
+ GenerateContentResponse.prompt_feedback and for each
531
+ candidate in finish_reason and in safety_ratings. The
532
+ API: - Returns either all requested candidates or
533
+ none of them - Returns no candidates at all only if
534
+ there was something wrong with the prompt (check
535
+ prompt_feedback) - Reports feedback on each candidate
536
+ in finish_reason and safety_ratings.
537
+
538
+ """
539
+ # Create or coerce a protobuf request object.
540
+ # - Quick check: If we got a request object, we should *not* have
541
+ # gotten any keyword arguments that map to the request.
542
+ has_flattened_params = any([model, contents])
543
+ if request is not None and has_flattened_params:
544
+ raise ValueError(
545
+ "If the `request` argument is set, then none of "
546
+ "the individual field arguments should be set."
547
+ )
548
+
549
+ # - Use the request object if provided (there's no risk of modifying the input as
550
+ # there are no flattened fields), or create one.
551
+ if not isinstance(request, generative_service.GenerateContentRequest):
552
+ request = generative_service.GenerateContentRequest(request)
553
+
554
+ # If we have keyword arguments corresponding to fields on the
555
+ # request, apply these.
556
+ if model is not None:
557
+ request.model = model
558
+ if contents:
559
+ request.contents.extend(contents)
560
+
561
+ # Wrap the RPC method; this adds retry and timeout information,
562
+ # and friendly error handling.
563
+ rpc = self._client._transport._wrapped_methods[
564
+ self._client._transport.stream_generate_content
565
+ ]
566
+
567
+ # Certain fields should be provided within the metadata header;
568
+ # add these here.
569
+ metadata = tuple(metadata) + (
570
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
571
+ )
572
+
573
+ # Validate the universe domain.
574
+ self._client._validate_universe_domain()
575
+
576
+ # Send the request.
577
+ response = rpc(
578
+ request,
579
+ retry=retry,
580
+ timeout=timeout,
581
+ metadata=metadata,
582
+ )
583
+
584
+ # Done; return the response.
585
+ return response
586
+
587
+ async def embed_content(
588
+ self,
589
+ request: Optional[Union[generative_service.EmbedContentRequest, dict]] = None,
590
+ *,
591
+ model: Optional[str] = None,
592
+ content: Optional[gag_content.Content] = None,
593
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
594
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
595
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
596
+ ) -> generative_service.EmbedContentResponse:
597
+ r"""Generates a text embedding vector from the input ``Content``
598
+ using the specified `Gemini Embedding
599
+ model <https://ai.google.dev/gemini-api/docs/models/gemini#text-embedding>`__.
600
+
601
+ .. code-block:: python
602
+
603
+ # This snippet has been automatically generated and should be regarded as a
604
+ # code template only.
605
+ # It will require modifications to work:
606
+ # - It may require correct/in-range values for request initialization.
607
+ # - It may require specifying regional endpoints when creating the service
608
+ # client as shown in:
609
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
610
+ from google.ai import generativelanguage_v1
611
+
612
+ async def sample_embed_content():
613
+ # Create a client
614
+ client = generativelanguage_v1.GenerativeServiceAsyncClient()
615
+
616
+ # Initialize request argument(s)
617
+ request = generativelanguage_v1.EmbedContentRequest(
618
+ model="model_value",
619
+ )
620
+
621
+ # Make the request
622
+ response = await client.embed_content(request=request)
623
+
624
+ # Handle the response
625
+ print(response)
626
+
627
+ Args:
628
+ request (Optional[Union[google.ai.generativelanguage_v1.types.EmbedContentRequest, dict]]):
629
+ The request object. Request containing the ``Content`` for the model to
630
+ embed.
631
+ model (:class:`str`):
632
+ Required. The model's resource name. This serves as an
633
+ ID for the Model to use.
634
+
635
+ This name should match a model name returned by the
636
+ ``ListModels`` method.
637
+
638
+ Format: ``models/{model}``
639
+
640
+ This corresponds to the ``model`` field
641
+ on the ``request`` instance; if ``request`` is provided, this
642
+ should not be set.
643
+ content (:class:`google.ai.generativelanguage_v1.types.Content`):
644
+ Required. The content to embed. Only the ``parts.text``
645
+ fields will be counted.
646
+
647
+ This corresponds to the ``content`` field
648
+ on the ``request`` instance; if ``request`` is provided, this
649
+ should not be set.
650
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
651
+ should be retried.
652
+ timeout (float): The timeout for this request.
653
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
654
+ sent along with the request as metadata. Normally, each value must be of type `str`,
655
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
656
+ be of type `bytes`.
657
+
658
+ Returns:
659
+ google.ai.generativelanguage_v1.types.EmbedContentResponse:
660
+ The response to an EmbedContentRequest.
661
+ """
662
+ # Create or coerce a protobuf request object.
663
+ # - Quick check: If we got a request object, we should *not* have
664
+ # gotten any keyword arguments that map to the request.
665
+ has_flattened_params = any([model, content])
666
+ if request is not None and has_flattened_params:
667
+ raise ValueError(
668
+ "If the `request` argument is set, then none of "
669
+ "the individual field arguments should be set."
670
+ )
671
+
672
+ # - Use the request object if provided (there's no risk of modifying the input as
673
+ # there are no flattened fields), or create one.
674
+ if not isinstance(request, generative_service.EmbedContentRequest):
675
+ request = generative_service.EmbedContentRequest(request)
676
+
677
+ # If we have keyword arguments corresponding to fields on the
678
+ # request, apply these.
679
+ if model is not None:
680
+ request.model = model
681
+ if content is not None:
682
+ request.content = content
683
+
684
+ # Wrap the RPC method; this adds retry and timeout information,
685
+ # and friendly error handling.
686
+ rpc = self._client._transport._wrapped_methods[
687
+ self._client._transport.embed_content
688
+ ]
689
+
690
+ # Certain fields should be provided within the metadata header;
691
+ # add these here.
692
+ metadata = tuple(metadata) + (
693
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
694
+ )
695
+
696
+ # Validate the universe domain.
697
+ self._client._validate_universe_domain()
698
+
699
+ # Send the request.
700
+ response = await rpc(
701
+ request,
702
+ retry=retry,
703
+ timeout=timeout,
704
+ metadata=metadata,
705
+ )
706
+
707
+ # Done; return the response.
708
+ return response
709
+
710
+ async def batch_embed_contents(
711
+ self,
712
+ request: Optional[
713
+ Union[generative_service.BatchEmbedContentsRequest, dict]
714
+ ] = None,
715
+ *,
716
+ model: Optional[str] = None,
717
+ requests: Optional[
718
+ MutableSequence[generative_service.EmbedContentRequest]
719
+ ] = None,
720
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
721
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
722
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
723
+ ) -> generative_service.BatchEmbedContentsResponse:
724
+ r"""Generates multiple embedding vectors from the input ``Content``
725
+ which consists of a batch of strings represented as
726
+ ``EmbedContentRequest`` objects.
727
+
728
+ .. code-block:: python
729
+
730
+ # This snippet has been automatically generated and should be regarded as a
731
+ # code template only.
732
+ # It will require modifications to work:
733
+ # - It may require correct/in-range values for request initialization.
734
+ # - It may require specifying regional endpoints when creating the service
735
+ # client as shown in:
736
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
737
+ from google.ai import generativelanguage_v1
738
+
739
+ async def sample_batch_embed_contents():
740
+ # Create a client
741
+ client = generativelanguage_v1.GenerativeServiceAsyncClient()
742
+
743
+ # Initialize request argument(s)
744
+ requests = generativelanguage_v1.EmbedContentRequest()
745
+ requests.model = "model_value"
746
+
747
+ request = generativelanguage_v1.BatchEmbedContentsRequest(
748
+ model="model_value",
749
+ requests=requests,
750
+ )
751
+
752
+ # Make the request
753
+ response = await client.batch_embed_contents(request=request)
754
+
755
+ # Handle the response
756
+ print(response)
757
+
758
+ Args:
759
+ request (Optional[Union[google.ai.generativelanguage_v1.types.BatchEmbedContentsRequest, dict]]):
760
+ The request object. Batch request to get embeddings from
761
+ the model for a list of prompts.
762
+ model (:class:`str`):
763
+ Required. The model's resource name. This serves as an
764
+ ID for the Model to use.
765
+
766
+ This name should match a model name returned by the
767
+ ``ListModels`` method.
768
+
769
+ Format: ``models/{model}``
770
+
771
+ This corresponds to the ``model`` field
772
+ on the ``request`` instance; if ``request`` is provided, this
773
+ should not be set.
774
+ requests (:class:`MutableSequence[google.ai.generativelanguage_v1.types.EmbedContentRequest]`):
775
+ Required. Embed requests for the batch. The model in
776
+ each of these requests must match the model specified
777
+ ``BatchEmbedContentsRequest.model``.
778
+
779
+ This corresponds to the ``requests`` field
780
+ on the ``request`` instance; if ``request`` is provided, this
781
+ should not be set.
782
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
783
+ should be retried.
784
+ timeout (float): The timeout for this request.
785
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
786
+ sent along with the request as metadata. Normally, each value must be of type `str`,
787
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
788
+ be of type `bytes`.
789
+
790
+ Returns:
791
+ google.ai.generativelanguage_v1.types.BatchEmbedContentsResponse:
792
+ The response to a BatchEmbedContentsRequest.
793
+ """
794
+ # Create or coerce a protobuf request object.
795
+ # - Quick check: If we got a request object, we should *not* have
796
+ # gotten any keyword arguments that map to the request.
797
+ has_flattened_params = any([model, requests])
798
+ if request is not None and has_flattened_params:
799
+ raise ValueError(
800
+ "If the `request` argument is set, then none of "
801
+ "the individual field arguments should be set."
802
+ )
803
+
804
+ # - Use the request object if provided (there's no risk of modifying the input as
805
+ # there are no flattened fields), or create one.
806
+ if not isinstance(request, generative_service.BatchEmbedContentsRequest):
807
+ request = generative_service.BatchEmbedContentsRequest(request)
808
+
809
+ # If we have keyword arguments corresponding to fields on the
810
+ # request, apply these.
811
+ if model is not None:
812
+ request.model = model
813
+ if requests:
814
+ request.requests.extend(requests)
815
+
816
+ # Wrap the RPC method; this adds retry and timeout information,
817
+ # and friendly error handling.
818
+ rpc = self._client._transport._wrapped_methods[
819
+ self._client._transport.batch_embed_contents
820
+ ]
821
+
822
+ # Certain fields should be provided within the metadata header;
823
+ # add these here.
824
+ metadata = tuple(metadata) + (
825
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
826
+ )
827
+
828
+ # Validate the universe domain.
829
+ self._client._validate_universe_domain()
830
+
831
+ # Send the request.
832
+ response = await rpc(
833
+ request,
834
+ retry=retry,
835
+ timeout=timeout,
836
+ metadata=metadata,
837
+ )
838
+
839
+ # Done; return the response.
840
+ return response
841
+
842
+ async def count_tokens(
843
+ self,
844
+ request: Optional[Union[generative_service.CountTokensRequest, dict]] = None,
845
+ *,
846
+ model: Optional[str] = None,
847
+ contents: Optional[MutableSequence[content.Content]] = None,
848
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
849
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
850
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
851
+ ) -> generative_service.CountTokensResponse:
852
+ r"""Runs a model's tokenizer on input ``Content`` and returns the
853
+ token count. Refer to the `tokens
854
+ guide <https://ai.google.dev/gemini-api/docs/tokens>`__ to learn
855
+ more about tokens.
856
+
857
+ .. code-block:: python
858
+
859
+ # This snippet has been automatically generated and should be regarded as a
860
+ # code template only.
861
+ # It will require modifications to work:
862
+ # - It may require correct/in-range values for request initialization.
863
+ # - It may require specifying regional endpoints when creating the service
864
+ # client as shown in:
865
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
866
+ from google.ai import generativelanguage_v1
867
+
868
+ async def sample_count_tokens():
869
+ # Create a client
870
+ client = generativelanguage_v1.GenerativeServiceAsyncClient()
871
+
872
+ # Initialize request argument(s)
873
+ request = generativelanguage_v1.CountTokensRequest(
874
+ model="model_value",
875
+ )
876
+
877
+ # Make the request
878
+ response = await client.count_tokens(request=request)
879
+
880
+ # Handle the response
881
+ print(response)
882
+
883
+ Args:
884
+ request (Optional[Union[google.ai.generativelanguage_v1.types.CountTokensRequest, dict]]):
885
+ The request object. Counts the number of tokens in the ``prompt`` sent to a
886
+ model.
887
+
888
+ Models may tokenize text differently, so each model may
889
+ return a different ``token_count``.
890
+ model (:class:`str`):
891
+ Required. The model's resource name. This serves as an
892
+ ID for the Model to use.
893
+
894
+ This name should match a model name returned by the
895
+ ``ListModels`` method.
896
+
897
+ Format: ``models/{model}``
898
+
899
+ This corresponds to the ``model`` field
900
+ on the ``request`` instance; if ``request`` is provided, this
901
+ should not be set.
902
+ contents (:class:`MutableSequence[google.ai.generativelanguage_v1.types.Content]`):
903
+ Optional. The input given to the model as a prompt. This
904
+ field is ignored when ``generate_content_request`` is
905
+ set.
906
+
907
+ This corresponds to the ``contents`` field
908
+ on the ``request`` instance; if ``request`` is provided, this
909
+ should not be set.
910
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any,
911
+ should be retried.
912
+ timeout (float): The timeout for this request.
913
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
914
+ sent along with the request as metadata. Normally, each value must be of type `str`,
915
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
916
+ be of type `bytes`.
917
+
918
+ Returns:
919
+ google.ai.generativelanguage_v1.types.CountTokensResponse:
920
+ A response from CountTokens.
921
+
922
+ It returns the model's token_count for the prompt.
923
+
924
+ """
925
+ # Create or coerce a protobuf request object.
926
+ # - Quick check: If we got a request object, we should *not* have
927
+ # gotten any keyword arguments that map to the request.
928
+ has_flattened_params = any([model, contents])
929
+ if request is not None and has_flattened_params:
930
+ raise ValueError(
931
+ "If the `request` argument is set, then none of "
932
+ "the individual field arguments should be set."
933
+ )
934
+
935
+ # - Use the request object if provided (there's no risk of modifying the input as
936
+ # there are no flattened fields), or create one.
937
+ if not isinstance(request, generative_service.CountTokensRequest):
938
+ request = generative_service.CountTokensRequest(request)
939
+
940
+ # If we have keyword arguments corresponding to fields on the
941
+ # request, apply these.
942
+ if model is not None:
943
+ request.model = model
944
+ if contents:
945
+ request.contents.extend(contents)
946
+
947
+ # Wrap the RPC method; this adds retry and timeout information,
948
+ # and friendly error handling.
949
+ rpc = self._client._transport._wrapped_methods[
950
+ self._client._transport.count_tokens
951
+ ]
952
+
953
+ # Certain fields should be provided within the metadata header;
954
+ # add these here.
955
+ metadata = tuple(metadata) + (
956
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
957
+ )
958
+
959
+ # Validate the universe domain.
960
+ self._client._validate_universe_domain()
961
+
962
+ # Send the request.
963
+ response = await rpc(
964
+ request,
965
+ retry=retry,
966
+ timeout=timeout,
967
+ metadata=metadata,
968
+ )
969
+
970
+ # Done; return the response.
971
+ return response
972
+
973
+ async def list_operations(
974
+ self,
975
+ request: Optional[operations_pb2.ListOperationsRequest] = None,
976
+ *,
977
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
978
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
979
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
980
+ ) -> operations_pb2.ListOperationsResponse:
981
+ r"""Lists operations that match the specified filter in the request.
982
+
983
+ Args:
984
+ request (:class:`~.operations_pb2.ListOperationsRequest`):
985
+ The request object. Request message for
986
+ `ListOperations` method.
987
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors,
988
+ if any, should be retried.
989
+ timeout (float): The timeout for this request.
990
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
991
+ sent along with the request as metadata. Normally, each value must be of type `str`,
992
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
993
+ be of type `bytes`.
994
+ Returns:
995
+ ~.operations_pb2.ListOperationsResponse:
996
+ Response message for ``ListOperations`` method.
997
+ """
998
+ # Create or coerce a protobuf request object.
999
+ # The request isn't a proto-plus wrapped type,
1000
+ # so it must be constructed via keyword expansion.
1001
+ if isinstance(request, dict):
1002
+ request = operations_pb2.ListOperationsRequest(**request)
1003
+
1004
+ # Wrap the RPC method; this adds retry and timeout information,
1005
+ # and friendly error handling.
1006
+ rpc = self.transport._wrapped_methods[self._client._transport.list_operations]
1007
+
1008
+ # Certain fields should be provided within the metadata header;
1009
+ # add these here.
1010
+ metadata = tuple(metadata) + (
1011
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
1012
+ )
1013
+
1014
+ # Validate the universe domain.
1015
+ self._client._validate_universe_domain()
1016
+
1017
+ # Send the request.
1018
+ response = await rpc(
1019
+ request,
1020
+ retry=retry,
1021
+ timeout=timeout,
1022
+ metadata=metadata,
1023
+ )
1024
+
1025
+ # Done; return the response.
1026
+ return response
1027
+
1028
+ async def get_operation(
1029
+ self,
1030
+ request: Optional[operations_pb2.GetOperationRequest] = None,
1031
+ *,
1032
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1033
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
1034
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1035
+ ) -> operations_pb2.Operation:
1036
+ r"""Gets the latest state of a long-running operation.
1037
+
1038
+ Args:
1039
+ request (:class:`~.operations_pb2.GetOperationRequest`):
1040
+ The request object. Request message for
1041
+ `GetOperation` method.
1042
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors,
1043
+ if any, should be retried.
1044
+ timeout (float): The timeout for this request.
1045
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1046
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1047
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1048
+ be of type `bytes`.
1049
+ Returns:
1050
+ ~.operations_pb2.Operation:
1051
+ An ``Operation`` object.
1052
+ """
1053
+ # Create or coerce a protobuf request object.
1054
+ # The request isn't a proto-plus wrapped type,
1055
+ # so it must be constructed via keyword expansion.
1056
+ if isinstance(request, dict):
1057
+ request = operations_pb2.GetOperationRequest(**request)
1058
+
1059
+ # Wrap the RPC method; this adds retry and timeout information,
1060
+ # and friendly error handling.
1061
+ rpc = self.transport._wrapped_methods[self._client._transport.get_operation]
1062
+
1063
+ # Certain fields should be provided within the metadata header;
1064
+ # add these here.
1065
+ metadata = tuple(metadata) + (
1066
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
1067
+ )
1068
+
1069
+ # Validate the universe domain.
1070
+ self._client._validate_universe_domain()
1071
+
1072
+ # Send the request.
1073
+ response = await rpc(
1074
+ request,
1075
+ retry=retry,
1076
+ timeout=timeout,
1077
+ metadata=metadata,
1078
+ )
1079
+
1080
+ # Done; return the response.
1081
+ return response
1082
+
1083
+ async def cancel_operation(
1084
+ self,
1085
+ request: Optional[operations_pb2.CancelOperationRequest] = None,
1086
+ *,
1087
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1088
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
1089
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1090
+ ) -> None:
1091
+ r"""Starts asynchronous cancellation on a long-running operation.
1092
+
1093
+ The server makes a best effort to cancel the operation, but success
1094
+ is not guaranteed. If the server doesn't support this method, it returns
1095
+ `google.rpc.Code.UNIMPLEMENTED`.
1096
+
1097
+ Args:
1098
+ request (:class:`~.operations_pb2.CancelOperationRequest`):
1099
+ The request object. Request message for
1100
+ `CancelOperation` method.
1101
+ retry (google.api_core.retry_async.AsyncRetry): Designation of what errors,
1102
+ if any, should be retried.
1103
+ timeout (float): The timeout for this request.
1104
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1105
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1106
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1107
+ be of type `bytes`.
1108
+ Returns:
1109
+ None
1110
+ """
1111
+ # Create or coerce a protobuf request object.
1112
+ # The request isn't a proto-plus wrapped type,
1113
+ # so it must be constructed via keyword expansion.
1114
+ if isinstance(request, dict):
1115
+ request = operations_pb2.CancelOperationRequest(**request)
1116
+
1117
+ # Wrap the RPC method; this adds retry and timeout information,
1118
+ # and friendly error handling.
1119
+ rpc = self.transport._wrapped_methods[self._client._transport.cancel_operation]
1120
+
1121
+ # Certain fields should be provided within the metadata header;
1122
+ # add these here.
1123
+ metadata = tuple(metadata) + (
1124
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
1125
+ )
1126
+
1127
+ # Validate the universe domain.
1128
+ self._client._validate_universe_domain()
1129
+
1130
+ # Send the request.
1131
+ await rpc(
1132
+ request,
1133
+ retry=retry,
1134
+ timeout=timeout,
1135
+ metadata=metadata,
1136
+ )
1137
+
1138
+ async def __aenter__(self) -> "GenerativeServiceAsyncClient":
1139
+ return self
1140
+
1141
+ async def __aexit__(self, exc_type, exc, tb):
1142
+ await self.transport.close()
1143
+
1144
+
1145
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
1146
+ gapic_version=package_version.__version__
1147
+ )
1148
+
1149
+
1150
+ __all__ = ("GenerativeServiceAsyncClient",)
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/client.py ADDED
@@ -0,0 +1,1529 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ from collections import OrderedDict
17
+ import logging as std_logging
18
+ import os
19
+ import re
20
+ from typing import (
21
+ Callable,
22
+ Dict,
23
+ Iterable,
24
+ Mapping,
25
+ MutableMapping,
26
+ MutableSequence,
27
+ Optional,
28
+ Sequence,
29
+ Tuple,
30
+ Type,
31
+ Union,
32
+ cast,
33
+ )
34
+ import warnings
35
+
36
+ from google.api_core import client_options as client_options_lib
37
+ from google.api_core import exceptions as core_exceptions
38
+ from google.api_core import gapic_v1
39
+ from google.api_core import retry as retries
40
+ from google.auth import credentials as ga_credentials # type: ignore
41
+ from google.auth.exceptions import MutualTLSChannelError # type: ignore
42
+ from google.auth.transport import mtls # type: ignore
43
+ from google.auth.transport.grpc import SslCredentials # type: ignore
44
+ from google.oauth2 import service_account # type: ignore
45
+
46
+ from google.ai.generativelanguage_v1 import gapic_version as package_version
47
+
48
+ try:
49
+ OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
50
+ except AttributeError: # pragma: NO COVER
51
+ OptionalRetry = Union[retries.Retry, object, None] # type: ignore
52
+
53
+ try:
54
+ from google.api_core import client_logging # type: ignore
55
+
56
+ CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
57
+ except ImportError: # pragma: NO COVER
58
+ CLIENT_LOGGING_SUPPORTED = False
59
+
60
+ _LOGGER = std_logging.getLogger(__name__)
61
+
62
+ from google.longrunning import operations_pb2 # type: ignore
63
+
64
+ from google.ai.generativelanguage_v1.types import content
65
+ from google.ai.generativelanguage_v1.types import content as gag_content
66
+ from google.ai.generativelanguage_v1.types import generative_service
67
+
68
+ from .transports.base import DEFAULT_CLIENT_INFO, GenerativeServiceTransport
69
+ from .transports.grpc import GenerativeServiceGrpcTransport
70
+ from .transports.grpc_asyncio import GenerativeServiceGrpcAsyncIOTransport
71
+ from .transports.rest import GenerativeServiceRestTransport
72
+
73
+
74
+ class GenerativeServiceClientMeta(type):
75
+ """Metaclass for the GenerativeService client.
76
+
77
+ This provides class-level methods for building and retrieving
78
+ support objects (e.g. transport) without polluting the client instance
79
+ objects.
80
+ """
81
+
82
+ _transport_registry = (
83
+ OrderedDict()
84
+ ) # type: Dict[str, Type[GenerativeServiceTransport]]
85
+ _transport_registry["grpc"] = GenerativeServiceGrpcTransport
86
+ _transport_registry["grpc_asyncio"] = GenerativeServiceGrpcAsyncIOTransport
87
+ _transport_registry["rest"] = GenerativeServiceRestTransport
88
+
89
+ def get_transport_class(
90
+ cls,
91
+ label: Optional[str] = None,
92
+ ) -> Type[GenerativeServiceTransport]:
93
+ """Returns an appropriate transport class.
94
+
95
+ Args:
96
+ label: The name of the desired transport. If none is
97
+ provided, then the first transport in the registry is used.
98
+
99
+ Returns:
100
+ The transport class to use.
101
+ """
102
+ # If a specific transport is requested, return that one.
103
+ if label:
104
+ return cls._transport_registry[label]
105
+
106
+ # No transport is requested; return the default (that is, the first one
107
+ # in the dictionary).
108
+ return next(iter(cls._transport_registry.values()))
109
+
110
+
111
+ class GenerativeServiceClient(metaclass=GenerativeServiceClientMeta):
112
+ """API for using Large Models that generate multimodal content
113
+ and have additional capabilities beyond text generation.
114
+ """
115
+
116
+ @staticmethod
117
+ def _get_default_mtls_endpoint(api_endpoint):
118
+ """Converts api endpoint to mTLS endpoint.
119
+
120
+ Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to
121
+ "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively.
122
+ Args:
123
+ api_endpoint (Optional[str]): the api endpoint to convert.
124
+ Returns:
125
+ str: converted mTLS api endpoint.
126
+ """
127
+ if not api_endpoint:
128
+ return api_endpoint
129
+
130
+ mtls_endpoint_re = re.compile(
131
+ r"(?P<name>[^.]+)(?P<mtls>\.mtls)?(?P<sandbox>\.sandbox)?(?P<googledomain>\.googleapis\.com)?"
132
+ )
133
+
134
+ m = mtls_endpoint_re.match(api_endpoint)
135
+ name, mtls, sandbox, googledomain = m.groups()
136
+ if mtls or not googledomain:
137
+ return api_endpoint
138
+
139
+ if sandbox:
140
+ return api_endpoint.replace(
141
+ "sandbox.googleapis.com", "mtls.sandbox.googleapis.com"
142
+ )
143
+
144
+ return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com")
145
+
146
+ # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead.
147
+ DEFAULT_ENDPOINT = "generativelanguage.googleapis.com"
148
+ DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore
149
+ DEFAULT_ENDPOINT
150
+ )
151
+
152
+ _DEFAULT_ENDPOINT_TEMPLATE = "generativelanguage.{UNIVERSE_DOMAIN}"
153
+ _DEFAULT_UNIVERSE = "googleapis.com"
154
+
155
+ @classmethod
156
+ def from_service_account_info(cls, info: dict, *args, **kwargs):
157
+ """Creates an instance of this client using the provided credentials
158
+ info.
159
+
160
+ Args:
161
+ info (dict): The service account private key info.
162
+ args: Additional arguments to pass to the constructor.
163
+ kwargs: Additional arguments to pass to the constructor.
164
+
165
+ Returns:
166
+ GenerativeServiceClient: The constructed client.
167
+ """
168
+ credentials = service_account.Credentials.from_service_account_info(info)
169
+ kwargs["credentials"] = credentials
170
+ return cls(*args, **kwargs)
171
+
172
+ @classmethod
173
+ def from_service_account_file(cls, filename: str, *args, **kwargs):
174
+ """Creates an instance of this client using the provided credentials
175
+ file.
176
+
177
+ Args:
178
+ filename (str): The path to the service account private key json
179
+ file.
180
+ args: Additional arguments to pass to the constructor.
181
+ kwargs: Additional arguments to pass to the constructor.
182
+
183
+ Returns:
184
+ GenerativeServiceClient: The constructed client.
185
+ """
186
+ credentials = service_account.Credentials.from_service_account_file(filename)
187
+ kwargs["credentials"] = credentials
188
+ return cls(*args, **kwargs)
189
+
190
+ from_service_account_json = from_service_account_file
191
+
192
+ @property
193
+ def transport(self) -> GenerativeServiceTransport:
194
+ """Returns the transport used by the client instance.
195
+
196
+ Returns:
197
+ GenerativeServiceTransport: The transport used by the client
198
+ instance.
199
+ """
200
+ return self._transport
201
+
202
+ @staticmethod
203
+ def model_path(
204
+ model: str,
205
+ ) -> str:
206
+ """Returns a fully-qualified model string."""
207
+ return "models/{model}".format(
208
+ model=model,
209
+ )
210
+
211
+ @staticmethod
212
+ def parse_model_path(path: str) -> Dict[str, str]:
213
+ """Parses a model path into its component segments."""
214
+ m = re.match(r"^models/(?P<model>.+?)$", path)
215
+ return m.groupdict() if m else {}
216
+
217
+ @staticmethod
218
+ def common_billing_account_path(
219
+ billing_account: str,
220
+ ) -> str:
221
+ """Returns a fully-qualified billing_account string."""
222
+ return "billingAccounts/{billing_account}".format(
223
+ billing_account=billing_account,
224
+ )
225
+
226
+ @staticmethod
227
+ def parse_common_billing_account_path(path: str) -> Dict[str, str]:
228
+ """Parse a billing_account path into its component segments."""
229
+ m = re.match(r"^billingAccounts/(?P<billing_account>.+?)$", path)
230
+ return m.groupdict() if m else {}
231
+
232
+ @staticmethod
233
+ def common_folder_path(
234
+ folder: str,
235
+ ) -> str:
236
+ """Returns a fully-qualified folder string."""
237
+ return "folders/{folder}".format(
238
+ folder=folder,
239
+ )
240
+
241
+ @staticmethod
242
+ def parse_common_folder_path(path: str) -> Dict[str, str]:
243
+ """Parse a folder path into its component segments."""
244
+ m = re.match(r"^folders/(?P<folder>.+?)$", path)
245
+ return m.groupdict() if m else {}
246
+
247
+ @staticmethod
248
+ def common_organization_path(
249
+ organization: str,
250
+ ) -> str:
251
+ """Returns a fully-qualified organization string."""
252
+ return "organizations/{organization}".format(
253
+ organization=organization,
254
+ )
255
+
256
+ @staticmethod
257
+ def parse_common_organization_path(path: str) -> Dict[str, str]:
258
+ """Parse a organization path into its component segments."""
259
+ m = re.match(r"^organizations/(?P<organization>.+?)$", path)
260
+ return m.groupdict() if m else {}
261
+
262
+ @staticmethod
263
+ def common_project_path(
264
+ project: str,
265
+ ) -> str:
266
+ """Returns a fully-qualified project string."""
267
+ return "projects/{project}".format(
268
+ project=project,
269
+ )
270
+
271
+ @staticmethod
272
+ def parse_common_project_path(path: str) -> Dict[str, str]:
273
+ """Parse a project path into its component segments."""
274
+ m = re.match(r"^projects/(?P<project>.+?)$", path)
275
+ return m.groupdict() if m else {}
276
+
277
+ @staticmethod
278
+ def common_location_path(
279
+ project: str,
280
+ location: str,
281
+ ) -> str:
282
+ """Returns a fully-qualified location string."""
283
+ return "projects/{project}/locations/{location}".format(
284
+ project=project,
285
+ location=location,
286
+ )
287
+
288
+ @staticmethod
289
+ def parse_common_location_path(path: str) -> Dict[str, str]:
290
+ """Parse a location path into its component segments."""
291
+ m = re.match(r"^projects/(?P<project>.+?)/locations/(?P<location>.+?)$", path)
292
+ return m.groupdict() if m else {}
293
+
294
+ @classmethod
295
+ def get_mtls_endpoint_and_cert_source(
296
+ cls, client_options: Optional[client_options_lib.ClientOptions] = None
297
+ ):
298
+ """Deprecated. Return the API endpoint and client cert source for mutual TLS.
299
+
300
+ The client cert source is determined in the following order:
301
+ (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the
302
+ client cert source is None.
303
+ (2) if `client_options.client_cert_source` is provided, use the provided one; if the
304
+ default client cert source exists, use the default one; otherwise the client cert
305
+ source is None.
306
+
307
+ The API endpoint is determined in the following order:
308
+ (1) if `client_options.api_endpoint` if provided, use the provided one.
309
+ (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the
310
+ default mTLS endpoint; if the environment variable is "never", use the default API
311
+ endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise
312
+ use the default API endpoint.
313
+
314
+ More details can be found at https://google.aip.dev/auth/4114.
315
+
316
+ Args:
317
+ client_options (google.api_core.client_options.ClientOptions): Custom options for the
318
+ client. Only the `api_endpoint` and `client_cert_source` properties may be used
319
+ in this method.
320
+
321
+ Returns:
322
+ Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the
323
+ client cert source to use.
324
+
325
+ Raises:
326
+ google.auth.exceptions.MutualTLSChannelError: If any errors happen.
327
+ """
328
+
329
+ warnings.warn(
330
+ "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.",
331
+ DeprecationWarning,
332
+ )
333
+ if client_options is None:
334
+ client_options = client_options_lib.ClientOptions()
335
+ use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false")
336
+ use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto")
337
+ if use_client_cert not in ("true", "false"):
338
+ raise ValueError(
339
+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
340
+ )
341
+ if use_mtls_endpoint not in ("auto", "never", "always"):
342
+ raise MutualTLSChannelError(
343
+ "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
344
+ )
345
+
346
+ # Figure out the client cert source to use.
347
+ client_cert_source = None
348
+ if use_client_cert == "true":
349
+ if client_options.client_cert_source:
350
+ client_cert_source = client_options.client_cert_source
351
+ elif mtls.has_default_client_cert_source():
352
+ client_cert_source = mtls.default_client_cert_source()
353
+
354
+ # Figure out which api endpoint to use.
355
+ if client_options.api_endpoint is not None:
356
+ api_endpoint = client_options.api_endpoint
357
+ elif use_mtls_endpoint == "always" or (
358
+ use_mtls_endpoint == "auto" and client_cert_source
359
+ ):
360
+ api_endpoint = cls.DEFAULT_MTLS_ENDPOINT
361
+ else:
362
+ api_endpoint = cls.DEFAULT_ENDPOINT
363
+
364
+ return api_endpoint, client_cert_source
365
+
366
+ @staticmethod
367
+ def _read_environment_variables():
368
+ """Returns the environment variables used by the client.
369
+
370
+ Returns:
371
+ Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE,
372
+ GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables.
373
+
374
+ Raises:
375
+ ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not
376
+ any of ["true", "false"].
377
+ google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT
378
+ is not any of ["auto", "never", "always"].
379
+ """
380
+ use_client_cert = os.getenv(
381
+ "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false"
382
+ ).lower()
383
+ use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower()
384
+ universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN")
385
+ if use_client_cert not in ("true", "false"):
386
+ raise ValueError(
387
+ "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`"
388
+ )
389
+ if use_mtls_endpoint not in ("auto", "never", "always"):
390
+ raise MutualTLSChannelError(
391
+ "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`"
392
+ )
393
+ return use_client_cert == "true", use_mtls_endpoint, universe_domain_env
394
+
395
+ @staticmethod
396
+ def _get_client_cert_source(provided_cert_source, use_cert_flag):
397
+ """Return the client cert source to be used by the client.
398
+
399
+ Args:
400
+ provided_cert_source (bytes): The client certificate source provided.
401
+ use_cert_flag (bool): A flag indicating whether to use the client certificate.
402
+
403
+ Returns:
404
+ bytes or None: The client cert source to be used by the client.
405
+ """
406
+ client_cert_source = None
407
+ if use_cert_flag:
408
+ if provided_cert_source:
409
+ client_cert_source = provided_cert_source
410
+ elif mtls.has_default_client_cert_source():
411
+ client_cert_source = mtls.default_client_cert_source()
412
+ return client_cert_source
413
+
414
+ @staticmethod
415
+ def _get_api_endpoint(
416
+ api_override, client_cert_source, universe_domain, use_mtls_endpoint
417
+ ):
418
+ """Return the API endpoint used by the client.
419
+
420
+ Args:
421
+ api_override (str): The API endpoint override. If specified, this is always
422
+ the return value of this function and the other arguments are not used.
423
+ client_cert_source (bytes): The client certificate source used by the client.
424
+ universe_domain (str): The universe domain used by the client.
425
+ use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters.
426
+ Possible values are "always", "auto", or "never".
427
+
428
+ Returns:
429
+ str: The API endpoint to be used by the client.
430
+ """
431
+ if api_override is not None:
432
+ api_endpoint = api_override
433
+ elif use_mtls_endpoint == "always" or (
434
+ use_mtls_endpoint == "auto" and client_cert_source
435
+ ):
436
+ _default_universe = GenerativeServiceClient._DEFAULT_UNIVERSE
437
+ if universe_domain != _default_universe:
438
+ raise MutualTLSChannelError(
439
+ f"mTLS is not supported in any universe other than {_default_universe}."
440
+ )
441
+ api_endpoint = GenerativeServiceClient.DEFAULT_MTLS_ENDPOINT
442
+ else:
443
+ api_endpoint = GenerativeServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format(
444
+ UNIVERSE_DOMAIN=universe_domain
445
+ )
446
+ return api_endpoint
447
+
448
+ @staticmethod
449
+ def _get_universe_domain(
450
+ client_universe_domain: Optional[str], universe_domain_env: Optional[str]
451
+ ) -> str:
452
+ """Return the universe domain used by the client.
453
+
454
+ Args:
455
+ client_universe_domain (Optional[str]): The universe domain configured via the client options.
456
+ universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable.
457
+
458
+ Returns:
459
+ str: The universe domain to be used by the client.
460
+
461
+ Raises:
462
+ ValueError: If the universe domain is an empty string.
463
+ """
464
+ universe_domain = GenerativeServiceClient._DEFAULT_UNIVERSE
465
+ if client_universe_domain is not None:
466
+ universe_domain = client_universe_domain
467
+ elif universe_domain_env is not None:
468
+ universe_domain = universe_domain_env
469
+ if len(universe_domain.strip()) == 0:
470
+ raise ValueError("Universe Domain cannot be an empty string.")
471
+ return universe_domain
472
+
473
+ def _validate_universe_domain(self):
474
+ """Validates client's and credentials' universe domains are consistent.
475
+
476
+ Returns:
477
+ bool: True iff the configured universe domain is valid.
478
+
479
+ Raises:
480
+ ValueError: If the configured universe domain is not valid.
481
+ """
482
+
483
+ # NOTE (b/349488459): universe validation is disabled until further notice.
484
+ return True
485
+
486
+ @property
487
+ def api_endpoint(self):
488
+ """Return the API endpoint used by the client instance.
489
+
490
+ Returns:
491
+ str: The API endpoint used by the client instance.
492
+ """
493
+ return self._api_endpoint
494
+
495
+ @property
496
+ def universe_domain(self) -> str:
497
+ """Return the universe domain used by the client instance.
498
+
499
+ Returns:
500
+ str: The universe domain used by the client instance.
501
+ """
502
+ return self._universe_domain
503
+
504
+ def __init__(
505
+ self,
506
+ *,
507
+ credentials: Optional[ga_credentials.Credentials] = None,
508
+ transport: Optional[
509
+ Union[
510
+ str,
511
+ GenerativeServiceTransport,
512
+ Callable[..., GenerativeServiceTransport],
513
+ ]
514
+ ] = None,
515
+ client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None,
516
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
517
+ ) -> None:
518
+ """Instantiates the generative service client.
519
+
520
+ Args:
521
+ credentials (Optional[google.auth.credentials.Credentials]): The
522
+ authorization credentials to attach to requests. These
523
+ credentials identify the application to the service; if none
524
+ are specified, the client will attempt to ascertain the
525
+ credentials from the environment.
526
+ transport (Optional[Union[str,GenerativeServiceTransport,Callable[..., GenerativeServiceTransport]]]):
527
+ The transport to use, or a Callable that constructs and returns a new transport.
528
+ If a Callable is given, it will be called with the same set of initialization
529
+ arguments as used in the GenerativeServiceTransport constructor.
530
+ If set to None, a transport is chosen automatically.
531
+ client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]):
532
+ Custom options for the client.
533
+
534
+ 1. The ``api_endpoint`` property can be used to override the
535
+ default endpoint provided by the client when ``transport`` is
536
+ not explicitly provided. Only if this property is not set and
537
+ ``transport`` was not explicitly provided, the endpoint is
538
+ determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment
539
+ variable, which have one of the following values:
540
+ "always" (always use the default mTLS endpoint), "never" (always
541
+ use the default regular endpoint) and "auto" (auto-switch to the
542
+ default mTLS endpoint if client certificate is present; this is
543
+ the default value).
544
+
545
+ 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable
546
+ is "true", then the ``client_cert_source`` property can be used
547
+ to provide a client certificate for mTLS transport. If
548
+ not provided, the default SSL client certificate will be used if
549
+ present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not
550
+ set, no client certificate will be used.
551
+
552
+ 3. The ``universe_domain`` property can be used to override the
553
+ default "googleapis.com" universe. Note that the ``api_endpoint``
554
+ property still takes precedence; and ``universe_domain`` is
555
+ currently not supported for mTLS.
556
+
557
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
558
+ The client info used to send a user-agent string along with
559
+ API requests. If ``None``, then default info will be used.
560
+ Generally, you only need to set this if you're developing
561
+ your own client library.
562
+
563
+ Raises:
564
+ google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport
565
+ creation failed for any reason.
566
+ """
567
+ self._client_options = client_options
568
+ if isinstance(self._client_options, dict):
569
+ self._client_options = client_options_lib.from_dict(self._client_options)
570
+ if self._client_options is None:
571
+ self._client_options = client_options_lib.ClientOptions()
572
+ self._client_options = cast(
573
+ client_options_lib.ClientOptions, self._client_options
574
+ )
575
+
576
+ universe_domain_opt = getattr(self._client_options, "universe_domain", None)
577
+
578
+ (
579
+ self._use_client_cert,
580
+ self._use_mtls_endpoint,
581
+ self._universe_domain_env,
582
+ ) = GenerativeServiceClient._read_environment_variables()
583
+ self._client_cert_source = GenerativeServiceClient._get_client_cert_source(
584
+ self._client_options.client_cert_source, self._use_client_cert
585
+ )
586
+ self._universe_domain = GenerativeServiceClient._get_universe_domain(
587
+ universe_domain_opt, self._universe_domain_env
588
+ )
589
+ self._api_endpoint = None # updated below, depending on `transport`
590
+
591
+ # Initialize the universe domain validation.
592
+ self._is_universe_domain_valid = False
593
+
594
+ if CLIENT_LOGGING_SUPPORTED: # pragma: NO COVER
595
+ # Setup logging.
596
+ client_logging.initialize_logging()
597
+
598
+ api_key_value = getattr(self._client_options, "api_key", None)
599
+ if api_key_value and credentials:
600
+ raise ValueError(
601
+ "client_options.api_key and credentials are mutually exclusive"
602
+ )
603
+
604
+ # Save or instantiate the transport.
605
+ # Ordinarily, we provide the transport, but allowing a custom transport
606
+ # instance provides an extensibility point for unusual situations.
607
+ transport_provided = isinstance(transport, GenerativeServiceTransport)
608
+ if transport_provided:
609
+ # transport is a GenerativeServiceTransport instance.
610
+ if credentials or self._client_options.credentials_file or api_key_value:
611
+ raise ValueError(
612
+ "When providing a transport instance, "
613
+ "provide its credentials directly."
614
+ )
615
+ if self._client_options.scopes:
616
+ raise ValueError(
617
+ "When providing a transport instance, provide its scopes "
618
+ "directly."
619
+ )
620
+ self._transport = cast(GenerativeServiceTransport, transport)
621
+ self._api_endpoint = self._transport.host
622
+
623
+ self._api_endpoint = (
624
+ self._api_endpoint
625
+ or GenerativeServiceClient._get_api_endpoint(
626
+ self._client_options.api_endpoint,
627
+ self._client_cert_source,
628
+ self._universe_domain,
629
+ self._use_mtls_endpoint,
630
+ )
631
+ )
632
+
633
+ if not transport_provided:
634
+ import google.auth._default # type: ignore
635
+
636
+ if api_key_value and hasattr(
637
+ google.auth._default, "get_api_key_credentials"
638
+ ):
639
+ credentials = google.auth._default.get_api_key_credentials(
640
+ api_key_value
641
+ )
642
+
643
+ transport_init: Union[
644
+ Type[GenerativeServiceTransport],
645
+ Callable[..., GenerativeServiceTransport],
646
+ ] = (
647
+ GenerativeServiceClient.get_transport_class(transport)
648
+ if isinstance(transport, str) or transport is None
649
+ else cast(Callable[..., GenerativeServiceTransport], transport)
650
+ )
651
+ # initialize with the provided callable or the passed in class
652
+ self._transport = transport_init(
653
+ credentials=credentials,
654
+ credentials_file=self._client_options.credentials_file,
655
+ host=self._api_endpoint,
656
+ scopes=self._client_options.scopes,
657
+ client_cert_source_for_mtls=self._client_cert_source,
658
+ quota_project_id=self._client_options.quota_project_id,
659
+ client_info=client_info,
660
+ always_use_jwt_access=True,
661
+ api_audience=self._client_options.api_audience,
662
+ )
663
+
664
+ if "async" not in str(self._transport):
665
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
666
+ std_logging.DEBUG
667
+ ): # pragma: NO COVER
668
+ _LOGGER.debug(
669
+ "Created client `google.ai.generativelanguage_v1.GenerativeServiceClient`.",
670
+ extra={
671
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
672
+ "universeDomain": getattr(
673
+ self._transport._credentials, "universe_domain", ""
674
+ ),
675
+ "credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}",
676
+ "credentialsInfo": getattr(
677
+ self.transport._credentials, "get_cred_info", lambda: None
678
+ )(),
679
+ }
680
+ if hasattr(self._transport, "_credentials")
681
+ else {
682
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
683
+ "credentialsType": None,
684
+ },
685
+ )
686
+
687
+ def generate_content(
688
+ self,
689
+ request: Optional[
690
+ Union[generative_service.GenerateContentRequest, dict]
691
+ ] = None,
692
+ *,
693
+ model: Optional[str] = None,
694
+ contents: Optional[MutableSequence[content.Content]] = None,
695
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
696
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
697
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
698
+ ) -> generative_service.GenerateContentResponse:
699
+ r"""Generates a model response given an input
700
+ ``GenerateContentRequest``. Refer to the `text generation
701
+ guide <https://ai.google.dev/gemini-api/docs/text-generation>`__
702
+ for detailed usage information. Input capabilities differ
703
+ between models, including tuned models. Refer to the `model
704
+ guide <https://ai.google.dev/gemini-api/docs/models/gemini>`__
705
+ and `tuning
706
+ guide <https://ai.google.dev/gemini-api/docs/model-tuning>`__
707
+ for details.
708
+
709
+ .. code-block:: python
710
+
711
+ # This snippet has been automatically generated and should be regarded as a
712
+ # code template only.
713
+ # It will require modifications to work:
714
+ # - It may require correct/in-range values for request initialization.
715
+ # - It may require specifying regional endpoints when creating the service
716
+ # client as shown in:
717
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
718
+ from google.ai import generativelanguage_v1
719
+
720
+ def sample_generate_content():
721
+ # Create a client
722
+ client = generativelanguage_v1.GenerativeServiceClient()
723
+
724
+ # Initialize request argument(s)
725
+ request = generativelanguage_v1.GenerateContentRequest(
726
+ model="model_value",
727
+ )
728
+
729
+ # Make the request
730
+ response = client.generate_content(request=request)
731
+
732
+ # Handle the response
733
+ print(response)
734
+
735
+ Args:
736
+ request (Union[google.ai.generativelanguage_v1.types.GenerateContentRequest, dict]):
737
+ The request object. Request to generate a completion from
738
+ the model.
739
+ model (str):
740
+ Required. The name of the ``Model`` to use for
741
+ generating the completion.
742
+
743
+ Format: ``models/{model}``.
744
+
745
+ This corresponds to the ``model`` field
746
+ on the ``request`` instance; if ``request`` is provided, this
747
+ should not be set.
748
+ contents (MutableSequence[google.ai.generativelanguage_v1.types.Content]):
749
+ Required. The content of the current conversation with
750
+ the model.
751
+
752
+ For single-turn queries, this is a single instance. For
753
+ multi-turn queries like
754
+ `chat <https://ai.google.dev/gemini-api/docs/text-generation#chat>`__,
755
+ this is a repeated field that contains the conversation
756
+ history and the latest request.
757
+
758
+ This corresponds to the ``contents`` field
759
+ on the ``request`` instance; if ``request`` is provided, this
760
+ should not be set.
761
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
762
+ should be retried.
763
+ timeout (float): The timeout for this request.
764
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
765
+ sent along with the request as metadata. Normally, each value must be of type `str`,
766
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
767
+ be of type `bytes`.
768
+
769
+ Returns:
770
+ google.ai.generativelanguage_v1.types.GenerateContentResponse:
771
+ Response from the model supporting multiple candidate
772
+ responses.
773
+
774
+ Safety ratings and content filtering are reported for
775
+ both prompt in
776
+ GenerateContentResponse.prompt_feedback and for each
777
+ candidate in finish_reason and in safety_ratings. The
778
+ API: - Returns either all requested candidates or
779
+ none of them - Returns no candidates at all only if
780
+ there was something wrong with the prompt (check
781
+ prompt_feedback) - Reports feedback on each candidate
782
+ in finish_reason and safety_ratings.
783
+
784
+ """
785
+ # Create or coerce a protobuf request object.
786
+ # - Quick check: If we got a request object, we should *not* have
787
+ # gotten any keyword arguments that map to the request.
788
+ has_flattened_params = any([model, contents])
789
+ if request is not None and has_flattened_params:
790
+ raise ValueError(
791
+ "If the `request` argument is set, then none of "
792
+ "the individual field arguments should be set."
793
+ )
794
+
795
+ # - Use the request object if provided (there's no risk of modifying the input as
796
+ # there are no flattened fields), or create one.
797
+ if not isinstance(request, generative_service.GenerateContentRequest):
798
+ request = generative_service.GenerateContentRequest(request)
799
+ # If we have keyword arguments corresponding to fields on the
800
+ # request, apply these.
801
+ if model is not None:
802
+ request.model = model
803
+ if contents is not None:
804
+ request.contents = contents
805
+
806
+ # Wrap the RPC method; this adds retry and timeout information,
807
+ # and friendly error handling.
808
+ rpc = self._transport._wrapped_methods[self._transport.generate_content]
809
+
810
+ # Certain fields should be provided within the metadata header;
811
+ # add these here.
812
+ metadata = tuple(metadata) + (
813
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
814
+ )
815
+
816
+ # Validate the universe domain.
817
+ self._validate_universe_domain()
818
+
819
+ # Send the request.
820
+ response = rpc(
821
+ request,
822
+ retry=retry,
823
+ timeout=timeout,
824
+ metadata=metadata,
825
+ )
826
+
827
+ # Done; return the response.
828
+ return response
829
+
830
+ def stream_generate_content(
831
+ self,
832
+ request: Optional[
833
+ Union[generative_service.GenerateContentRequest, dict]
834
+ ] = None,
835
+ *,
836
+ model: Optional[str] = None,
837
+ contents: Optional[MutableSequence[content.Content]] = None,
838
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
839
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
840
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
841
+ ) -> Iterable[generative_service.GenerateContentResponse]:
842
+ r"""Generates a `streamed
843
+ response <https://ai.google.dev/gemini-api/docs/text-generation?lang=python#generate-a-text-stream>`__
844
+ from the model given an input ``GenerateContentRequest``.
845
+
846
+ .. code-block:: python
847
+
848
+ # This snippet has been automatically generated and should be regarded as a
849
+ # code template only.
850
+ # It will require modifications to work:
851
+ # - It may require correct/in-range values for request initialization.
852
+ # - It may require specifying regional endpoints when creating the service
853
+ # client as shown in:
854
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
855
+ from google.ai import generativelanguage_v1
856
+
857
+ def sample_stream_generate_content():
858
+ # Create a client
859
+ client = generativelanguage_v1.GenerativeServiceClient()
860
+
861
+ # Initialize request argument(s)
862
+ request = generativelanguage_v1.GenerateContentRequest(
863
+ model="model_value",
864
+ )
865
+
866
+ # Make the request
867
+ stream = client.stream_generate_content(request=request)
868
+
869
+ # Handle the response
870
+ for response in stream:
871
+ print(response)
872
+
873
+ Args:
874
+ request (Union[google.ai.generativelanguage_v1.types.GenerateContentRequest, dict]):
875
+ The request object. Request to generate a completion from
876
+ the model.
877
+ model (str):
878
+ Required. The name of the ``Model`` to use for
879
+ generating the completion.
880
+
881
+ Format: ``models/{model}``.
882
+
883
+ This corresponds to the ``model`` field
884
+ on the ``request`` instance; if ``request`` is provided, this
885
+ should not be set.
886
+ contents (MutableSequence[google.ai.generativelanguage_v1.types.Content]):
887
+ Required. The content of the current conversation with
888
+ the model.
889
+
890
+ For single-turn queries, this is a single instance. For
891
+ multi-turn queries like
892
+ `chat <https://ai.google.dev/gemini-api/docs/text-generation#chat>`__,
893
+ this is a repeated field that contains the conversation
894
+ history and the latest request.
895
+
896
+ This corresponds to the ``contents`` field
897
+ on the ``request`` instance; if ``request`` is provided, this
898
+ should not be set.
899
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
900
+ should be retried.
901
+ timeout (float): The timeout for this request.
902
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
903
+ sent along with the request as metadata. Normally, each value must be of type `str`,
904
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
905
+ be of type `bytes`.
906
+
907
+ Returns:
908
+ Iterable[google.ai.generativelanguage_v1.types.GenerateContentResponse]:
909
+ Response from the model supporting multiple candidate
910
+ responses.
911
+
912
+ Safety ratings and content filtering are reported for
913
+ both prompt in
914
+ GenerateContentResponse.prompt_feedback and for each
915
+ candidate in finish_reason and in safety_ratings. The
916
+ API: - Returns either all requested candidates or
917
+ none of them - Returns no candidates at all only if
918
+ there was something wrong with the prompt (check
919
+ prompt_feedback) - Reports feedback on each candidate
920
+ in finish_reason and safety_ratings.
921
+
922
+ """
923
+ # Create or coerce a protobuf request object.
924
+ # - Quick check: If we got a request object, we should *not* have
925
+ # gotten any keyword arguments that map to the request.
926
+ has_flattened_params = any([model, contents])
927
+ if request is not None and has_flattened_params:
928
+ raise ValueError(
929
+ "If the `request` argument is set, then none of "
930
+ "the individual field arguments should be set."
931
+ )
932
+
933
+ # - Use the request object if provided (there's no risk of modifying the input as
934
+ # there are no flattened fields), or create one.
935
+ if not isinstance(request, generative_service.GenerateContentRequest):
936
+ request = generative_service.GenerateContentRequest(request)
937
+ # If we have keyword arguments corresponding to fields on the
938
+ # request, apply these.
939
+ if model is not None:
940
+ request.model = model
941
+ if contents is not None:
942
+ request.contents = contents
943
+
944
+ # Wrap the RPC method; this adds retry and timeout information,
945
+ # and friendly error handling.
946
+ rpc = self._transport._wrapped_methods[self._transport.stream_generate_content]
947
+
948
+ # Certain fields should be provided within the metadata header;
949
+ # add these here.
950
+ metadata = tuple(metadata) + (
951
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
952
+ )
953
+
954
+ # Validate the universe domain.
955
+ self._validate_universe_domain()
956
+
957
+ # Send the request.
958
+ response = rpc(
959
+ request,
960
+ retry=retry,
961
+ timeout=timeout,
962
+ metadata=metadata,
963
+ )
964
+
965
+ # Done; return the response.
966
+ return response
967
+
968
+ def embed_content(
969
+ self,
970
+ request: Optional[Union[generative_service.EmbedContentRequest, dict]] = None,
971
+ *,
972
+ model: Optional[str] = None,
973
+ content: Optional[gag_content.Content] = None,
974
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
975
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
976
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
977
+ ) -> generative_service.EmbedContentResponse:
978
+ r"""Generates a text embedding vector from the input ``Content``
979
+ using the specified `Gemini Embedding
980
+ model <https://ai.google.dev/gemini-api/docs/models/gemini#text-embedding>`__.
981
+
982
+ .. code-block:: python
983
+
984
+ # This snippet has been automatically generated and should be regarded as a
985
+ # code template only.
986
+ # It will require modifications to work:
987
+ # - It may require correct/in-range values for request initialization.
988
+ # - It may require specifying regional endpoints when creating the service
989
+ # client as shown in:
990
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
991
+ from google.ai import generativelanguage_v1
992
+
993
+ def sample_embed_content():
994
+ # Create a client
995
+ client = generativelanguage_v1.GenerativeServiceClient()
996
+
997
+ # Initialize request argument(s)
998
+ request = generativelanguage_v1.EmbedContentRequest(
999
+ model="model_value",
1000
+ )
1001
+
1002
+ # Make the request
1003
+ response = client.embed_content(request=request)
1004
+
1005
+ # Handle the response
1006
+ print(response)
1007
+
1008
+ Args:
1009
+ request (Union[google.ai.generativelanguage_v1.types.EmbedContentRequest, dict]):
1010
+ The request object. Request containing the ``Content`` for the model to
1011
+ embed.
1012
+ model (str):
1013
+ Required. The model's resource name. This serves as an
1014
+ ID for the Model to use.
1015
+
1016
+ This name should match a model name returned by the
1017
+ ``ListModels`` method.
1018
+
1019
+ Format: ``models/{model}``
1020
+
1021
+ This corresponds to the ``model`` field
1022
+ on the ``request`` instance; if ``request`` is provided, this
1023
+ should not be set.
1024
+ content (google.ai.generativelanguage_v1.types.Content):
1025
+ Required. The content to embed. Only the ``parts.text``
1026
+ fields will be counted.
1027
+
1028
+ This corresponds to the ``content`` field
1029
+ on the ``request`` instance; if ``request`` is provided, this
1030
+ should not be set.
1031
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
1032
+ should be retried.
1033
+ timeout (float): The timeout for this request.
1034
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1035
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1036
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1037
+ be of type `bytes`.
1038
+
1039
+ Returns:
1040
+ google.ai.generativelanguage_v1.types.EmbedContentResponse:
1041
+ The response to an EmbedContentRequest.
1042
+ """
1043
+ # Create or coerce a protobuf request object.
1044
+ # - Quick check: If we got a request object, we should *not* have
1045
+ # gotten any keyword arguments that map to the request.
1046
+ has_flattened_params = any([model, content])
1047
+ if request is not None and has_flattened_params:
1048
+ raise ValueError(
1049
+ "If the `request` argument is set, then none of "
1050
+ "the individual field arguments should be set."
1051
+ )
1052
+
1053
+ # - Use the request object if provided (there's no risk of modifying the input as
1054
+ # there are no flattened fields), or create one.
1055
+ if not isinstance(request, generative_service.EmbedContentRequest):
1056
+ request = generative_service.EmbedContentRequest(request)
1057
+ # If we have keyword arguments corresponding to fields on the
1058
+ # request, apply these.
1059
+ if model is not None:
1060
+ request.model = model
1061
+ if content is not None:
1062
+ request.content = content
1063
+
1064
+ # Wrap the RPC method; this adds retry and timeout information,
1065
+ # and friendly error handling.
1066
+ rpc = self._transport._wrapped_methods[self._transport.embed_content]
1067
+
1068
+ # Certain fields should be provided within the metadata header;
1069
+ # add these here.
1070
+ metadata = tuple(metadata) + (
1071
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
1072
+ )
1073
+
1074
+ # Validate the universe domain.
1075
+ self._validate_universe_domain()
1076
+
1077
+ # Send the request.
1078
+ response = rpc(
1079
+ request,
1080
+ retry=retry,
1081
+ timeout=timeout,
1082
+ metadata=metadata,
1083
+ )
1084
+
1085
+ # Done; return the response.
1086
+ return response
1087
+
1088
+ def batch_embed_contents(
1089
+ self,
1090
+ request: Optional[
1091
+ Union[generative_service.BatchEmbedContentsRequest, dict]
1092
+ ] = None,
1093
+ *,
1094
+ model: Optional[str] = None,
1095
+ requests: Optional[
1096
+ MutableSequence[generative_service.EmbedContentRequest]
1097
+ ] = None,
1098
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1099
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
1100
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1101
+ ) -> generative_service.BatchEmbedContentsResponse:
1102
+ r"""Generates multiple embedding vectors from the input ``Content``
1103
+ which consists of a batch of strings represented as
1104
+ ``EmbedContentRequest`` objects.
1105
+
1106
+ .. code-block:: python
1107
+
1108
+ # This snippet has been automatically generated and should be regarded as a
1109
+ # code template only.
1110
+ # It will require modifications to work:
1111
+ # - It may require correct/in-range values for request initialization.
1112
+ # - It may require specifying regional endpoints when creating the service
1113
+ # client as shown in:
1114
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
1115
+ from google.ai import generativelanguage_v1
1116
+
1117
+ def sample_batch_embed_contents():
1118
+ # Create a client
1119
+ client = generativelanguage_v1.GenerativeServiceClient()
1120
+
1121
+ # Initialize request argument(s)
1122
+ requests = generativelanguage_v1.EmbedContentRequest()
1123
+ requests.model = "model_value"
1124
+
1125
+ request = generativelanguage_v1.BatchEmbedContentsRequest(
1126
+ model="model_value",
1127
+ requests=requests,
1128
+ )
1129
+
1130
+ # Make the request
1131
+ response = client.batch_embed_contents(request=request)
1132
+
1133
+ # Handle the response
1134
+ print(response)
1135
+
1136
+ Args:
1137
+ request (Union[google.ai.generativelanguage_v1.types.BatchEmbedContentsRequest, dict]):
1138
+ The request object. Batch request to get embeddings from
1139
+ the model for a list of prompts.
1140
+ model (str):
1141
+ Required. The model's resource name. This serves as an
1142
+ ID for the Model to use.
1143
+
1144
+ This name should match a model name returned by the
1145
+ ``ListModels`` method.
1146
+
1147
+ Format: ``models/{model}``
1148
+
1149
+ This corresponds to the ``model`` field
1150
+ on the ``request`` instance; if ``request`` is provided, this
1151
+ should not be set.
1152
+ requests (MutableSequence[google.ai.generativelanguage_v1.types.EmbedContentRequest]):
1153
+ Required. Embed requests for the batch. The model in
1154
+ each of these requests must match the model specified
1155
+ ``BatchEmbedContentsRequest.model``.
1156
+
1157
+ This corresponds to the ``requests`` field
1158
+ on the ``request`` instance; if ``request`` is provided, this
1159
+ should not be set.
1160
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
1161
+ should be retried.
1162
+ timeout (float): The timeout for this request.
1163
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1164
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1165
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1166
+ be of type `bytes`.
1167
+
1168
+ Returns:
1169
+ google.ai.generativelanguage_v1.types.BatchEmbedContentsResponse:
1170
+ The response to a BatchEmbedContentsRequest.
1171
+ """
1172
+ # Create or coerce a protobuf request object.
1173
+ # - Quick check: If we got a request object, we should *not* have
1174
+ # gotten any keyword arguments that map to the request.
1175
+ has_flattened_params = any([model, requests])
1176
+ if request is not None and has_flattened_params:
1177
+ raise ValueError(
1178
+ "If the `request` argument is set, then none of "
1179
+ "the individual field arguments should be set."
1180
+ )
1181
+
1182
+ # - Use the request object if provided (there's no risk of modifying the input as
1183
+ # there are no flattened fields), or create one.
1184
+ if not isinstance(request, generative_service.BatchEmbedContentsRequest):
1185
+ request = generative_service.BatchEmbedContentsRequest(request)
1186
+ # If we have keyword arguments corresponding to fields on the
1187
+ # request, apply these.
1188
+ if model is not None:
1189
+ request.model = model
1190
+ if requests is not None:
1191
+ request.requests = requests
1192
+
1193
+ # Wrap the RPC method; this adds retry and timeout information,
1194
+ # and friendly error handling.
1195
+ rpc = self._transport._wrapped_methods[self._transport.batch_embed_contents]
1196
+
1197
+ # Certain fields should be provided within the metadata header;
1198
+ # add these here.
1199
+ metadata = tuple(metadata) + (
1200
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
1201
+ )
1202
+
1203
+ # Validate the universe domain.
1204
+ self._validate_universe_domain()
1205
+
1206
+ # Send the request.
1207
+ response = rpc(
1208
+ request,
1209
+ retry=retry,
1210
+ timeout=timeout,
1211
+ metadata=metadata,
1212
+ )
1213
+
1214
+ # Done; return the response.
1215
+ return response
1216
+
1217
+ def count_tokens(
1218
+ self,
1219
+ request: Optional[Union[generative_service.CountTokensRequest, dict]] = None,
1220
+ *,
1221
+ model: Optional[str] = None,
1222
+ contents: Optional[MutableSequence[content.Content]] = None,
1223
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1224
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
1225
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1226
+ ) -> generative_service.CountTokensResponse:
1227
+ r"""Runs a model's tokenizer on input ``Content`` and returns the
1228
+ token count. Refer to the `tokens
1229
+ guide <https://ai.google.dev/gemini-api/docs/tokens>`__ to learn
1230
+ more about tokens.
1231
+
1232
+ .. code-block:: python
1233
+
1234
+ # This snippet has been automatically generated and should be regarded as a
1235
+ # code template only.
1236
+ # It will require modifications to work:
1237
+ # - It may require correct/in-range values for request initialization.
1238
+ # - It may require specifying regional endpoints when creating the service
1239
+ # client as shown in:
1240
+ # https://googleapis.dev/python/google-api-core/latest/client_options.html
1241
+ from google.ai import generativelanguage_v1
1242
+
1243
+ def sample_count_tokens():
1244
+ # Create a client
1245
+ client = generativelanguage_v1.GenerativeServiceClient()
1246
+
1247
+ # Initialize request argument(s)
1248
+ request = generativelanguage_v1.CountTokensRequest(
1249
+ model="model_value",
1250
+ )
1251
+
1252
+ # Make the request
1253
+ response = client.count_tokens(request=request)
1254
+
1255
+ # Handle the response
1256
+ print(response)
1257
+
1258
+ Args:
1259
+ request (Union[google.ai.generativelanguage_v1.types.CountTokensRequest, dict]):
1260
+ The request object. Counts the number of tokens in the ``prompt`` sent to a
1261
+ model.
1262
+
1263
+ Models may tokenize text differently, so each model may
1264
+ return a different ``token_count``.
1265
+ model (str):
1266
+ Required. The model's resource name. This serves as an
1267
+ ID for the Model to use.
1268
+
1269
+ This name should match a model name returned by the
1270
+ ``ListModels`` method.
1271
+
1272
+ Format: ``models/{model}``
1273
+
1274
+ This corresponds to the ``model`` field
1275
+ on the ``request`` instance; if ``request`` is provided, this
1276
+ should not be set.
1277
+ contents (MutableSequence[google.ai.generativelanguage_v1.types.Content]):
1278
+ Optional. The input given to the model as a prompt. This
1279
+ field is ignored when ``generate_content_request`` is
1280
+ set.
1281
+
1282
+ This corresponds to the ``contents`` field
1283
+ on the ``request`` instance; if ``request`` is provided, this
1284
+ should not be set.
1285
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
1286
+ should be retried.
1287
+ timeout (float): The timeout for this request.
1288
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1289
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1290
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1291
+ be of type `bytes`.
1292
+
1293
+ Returns:
1294
+ google.ai.generativelanguage_v1.types.CountTokensResponse:
1295
+ A response from CountTokens.
1296
+
1297
+ It returns the model's token_count for the prompt.
1298
+
1299
+ """
1300
+ # Create or coerce a protobuf request object.
1301
+ # - Quick check: If we got a request object, we should *not* have
1302
+ # gotten any keyword arguments that map to the request.
1303
+ has_flattened_params = any([model, contents])
1304
+ if request is not None and has_flattened_params:
1305
+ raise ValueError(
1306
+ "If the `request` argument is set, then none of "
1307
+ "the individual field arguments should be set."
1308
+ )
1309
+
1310
+ # - Use the request object if provided (there's no risk of modifying the input as
1311
+ # there are no flattened fields), or create one.
1312
+ if not isinstance(request, generative_service.CountTokensRequest):
1313
+ request = generative_service.CountTokensRequest(request)
1314
+ # If we have keyword arguments corresponding to fields on the
1315
+ # request, apply these.
1316
+ if model is not None:
1317
+ request.model = model
1318
+ if contents is not None:
1319
+ request.contents = contents
1320
+
1321
+ # Wrap the RPC method; this adds retry and timeout information,
1322
+ # and friendly error handling.
1323
+ rpc = self._transport._wrapped_methods[self._transport.count_tokens]
1324
+
1325
+ # Certain fields should be provided within the metadata header;
1326
+ # add these here.
1327
+ metadata = tuple(metadata) + (
1328
+ gapic_v1.routing_header.to_grpc_metadata((("model", request.model),)),
1329
+ )
1330
+
1331
+ # Validate the universe domain.
1332
+ self._validate_universe_domain()
1333
+
1334
+ # Send the request.
1335
+ response = rpc(
1336
+ request,
1337
+ retry=retry,
1338
+ timeout=timeout,
1339
+ metadata=metadata,
1340
+ )
1341
+
1342
+ # Done; return the response.
1343
+ return response
1344
+
1345
+ def __enter__(self) -> "GenerativeServiceClient":
1346
+ return self
1347
+
1348
+ def __exit__(self, type, value, traceback):
1349
+ """Releases underlying transport's resources.
1350
+
1351
+ .. warning::
1352
+ ONLY use as a context manager if the transport is NOT shared
1353
+ with other clients! Exiting the with block will CLOSE the transport
1354
+ and may cause errors in other clients!
1355
+ """
1356
+ self.transport.close()
1357
+
1358
+ def list_operations(
1359
+ self,
1360
+ request: Optional[operations_pb2.ListOperationsRequest] = None,
1361
+ *,
1362
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1363
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
1364
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1365
+ ) -> operations_pb2.ListOperationsResponse:
1366
+ r"""Lists operations that match the specified filter in the request.
1367
+
1368
+ Args:
1369
+ request (:class:`~.operations_pb2.ListOperationsRequest`):
1370
+ The request object. Request message for
1371
+ `ListOperations` method.
1372
+ retry (google.api_core.retry.Retry): Designation of what errors,
1373
+ if any, should be retried.
1374
+ timeout (float): The timeout for this request.
1375
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1376
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1377
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1378
+ be of type `bytes`.
1379
+ Returns:
1380
+ ~.operations_pb2.ListOperationsResponse:
1381
+ Response message for ``ListOperations`` method.
1382
+ """
1383
+ # Create or coerce a protobuf request object.
1384
+ # The request isn't a proto-plus wrapped type,
1385
+ # so it must be constructed via keyword expansion.
1386
+ if isinstance(request, dict):
1387
+ request = operations_pb2.ListOperationsRequest(**request)
1388
+
1389
+ # Wrap the RPC method; this adds retry and timeout information,
1390
+ # and friendly error handling.
1391
+ rpc = self._transport._wrapped_methods[self._transport.list_operations]
1392
+
1393
+ # Certain fields should be provided within the metadata header;
1394
+ # add these here.
1395
+ metadata = tuple(metadata) + (
1396
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
1397
+ )
1398
+
1399
+ # Validate the universe domain.
1400
+ self._validate_universe_domain()
1401
+
1402
+ # Send the request.
1403
+ response = rpc(
1404
+ request,
1405
+ retry=retry,
1406
+ timeout=timeout,
1407
+ metadata=metadata,
1408
+ )
1409
+
1410
+ # Done; return the response.
1411
+ return response
1412
+
1413
+ def get_operation(
1414
+ self,
1415
+ request: Optional[operations_pb2.GetOperationRequest] = None,
1416
+ *,
1417
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1418
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
1419
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1420
+ ) -> operations_pb2.Operation:
1421
+ r"""Gets the latest state of a long-running operation.
1422
+
1423
+ Args:
1424
+ request (:class:`~.operations_pb2.GetOperationRequest`):
1425
+ The request object. Request message for
1426
+ `GetOperation` method.
1427
+ retry (google.api_core.retry.Retry): Designation of what errors,
1428
+ if any, should be retried.
1429
+ timeout (float): The timeout for this request.
1430
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1431
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1432
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1433
+ be of type `bytes`.
1434
+ Returns:
1435
+ ~.operations_pb2.Operation:
1436
+ An ``Operation`` object.
1437
+ """
1438
+ # Create or coerce a protobuf request object.
1439
+ # The request isn't a proto-plus wrapped type,
1440
+ # so it must be constructed via keyword expansion.
1441
+ if isinstance(request, dict):
1442
+ request = operations_pb2.GetOperationRequest(**request)
1443
+
1444
+ # Wrap the RPC method; this adds retry and timeout information,
1445
+ # and friendly error handling.
1446
+ rpc = self._transport._wrapped_methods[self._transport.get_operation]
1447
+
1448
+ # Certain fields should be provided within the metadata header;
1449
+ # add these here.
1450
+ metadata = tuple(metadata) + (
1451
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
1452
+ )
1453
+
1454
+ # Validate the universe domain.
1455
+ self._validate_universe_domain()
1456
+
1457
+ # Send the request.
1458
+ response = rpc(
1459
+ request,
1460
+ retry=retry,
1461
+ timeout=timeout,
1462
+ metadata=metadata,
1463
+ )
1464
+
1465
+ # Done; return the response.
1466
+ return response
1467
+
1468
+ def cancel_operation(
1469
+ self,
1470
+ request: Optional[operations_pb2.CancelOperationRequest] = None,
1471
+ *,
1472
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1473
+ timeout: Union[float, object] = gapic_v1.method.DEFAULT,
1474
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1475
+ ) -> None:
1476
+ r"""Starts asynchronous cancellation on a long-running operation.
1477
+
1478
+ The server makes a best effort to cancel the operation, but success
1479
+ is not guaranteed. If the server doesn't support this method, it returns
1480
+ `google.rpc.Code.UNIMPLEMENTED`.
1481
+
1482
+ Args:
1483
+ request (:class:`~.operations_pb2.CancelOperationRequest`):
1484
+ The request object. Request message for
1485
+ `CancelOperation` method.
1486
+ retry (google.api_core.retry.Retry): Designation of what errors,
1487
+ if any, should be retried.
1488
+ timeout (float): The timeout for this request.
1489
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1490
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1491
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1492
+ be of type `bytes`.
1493
+ Returns:
1494
+ None
1495
+ """
1496
+ # Create or coerce a protobuf request object.
1497
+ # The request isn't a proto-plus wrapped type,
1498
+ # so it must be constructed via keyword expansion.
1499
+ if isinstance(request, dict):
1500
+ request = operations_pb2.CancelOperationRequest(**request)
1501
+
1502
+ # Wrap the RPC method; this adds retry and timeout information,
1503
+ # and friendly error handling.
1504
+ rpc = self._transport._wrapped_methods[self._transport.cancel_operation]
1505
+
1506
+ # Certain fields should be provided within the metadata header;
1507
+ # add these here.
1508
+ metadata = tuple(metadata) + (
1509
+ gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)),
1510
+ )
1511
+
1512
+ # Validate the universe domain.
1513
+ self._validate_universe_domain()
1514
+
1515
+ # Send the request.
1516
+ rpc(
1517
+ request,
1518
+ retry=retry,
1519
+ timeout=timeout,
1520
+ metadata=metadata,
1521
+ )
1522
+
1523
+
1524
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
1525
+ gapic_version=package_version.__version__
1526
+ )
1527
+
1528
+
1529
+ __all__ = ("GenerativeServiceClient",)
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/transports/__pycache__/grpc.cpython-311.pyc ADDED
Binary file (24 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/transports/rest.py ADDED
@@ -0,0 +1,1643 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ import dataclasses
17
+ import json # type: ignore
18
+ import logging
19
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
20
+ import warnings
21
+
22
+ from google.api_core import exceptions as core_exceptions
23
+ from google.api_core import gapic_v1, rest_helpers, rest_streaming
24
+ from google.api_core import retry as retries
25
+ from google.auth import credentials as ga_credentials # type: ignore
26
+ from google.auth.transport.requests import AuthorizedSession # type: ignore
27
+ from google.longrunning import operations_pb2 # type: ignore
28
+ from google.protobuf import json_format
29
+ from requests import __version__ as requests_version
30
+
31
+ from google.ai.generativelanguage_v1.types import generative_service
32
+
33
+ from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO
34
+ from .rest_base import _BaseGenerativeServiceRestTransport
35
+
36
+ try:
37
+ OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
38
+ except AttributeError: # pragma: NO COVER
39
+ OptionalRetry = Union[retries.Retry, object, None] # type: ignore
40
+
41
+ try:
42
+ from google.api_core import client_logging # type: ignore
43
+
44
+ CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
45
+ except ImportError: # pragma: NO COVER
46
+ CLIENT_LOGGING_SUPPORTED = False
47
+
48
+ _LOGGER = logging.getLogger(__name__)
49
+
50
+ DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo(
51
+ gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version,
52
+ grpc_version=None,
53
+ rest_version=f"requests@{requests_version}",
54
+ )
55
+
56
+
57
+ class GenerativeServiceRestInterceptor:
58
+ """Interceptor for GenerativeService.
59
+
60
+ Interceptors are used to manipulate requests, request metadata, and responses
61
+ in arbitrary ways.
62
+ Example use cases include:
63
+ * Logging
64
+ * Verifying requests according to service or custom semantics
65
+ * Stripping extraneous information from responses
66
+
67
+ These use cases and more can be enabled by injecting an
68
+ instance of a custom subclass when constructing the GenerativeServiceRestTransport.
69
+
70
+ .. code-block:: python
71
+ class MyCustomGenerativeServiceInterceptor(GenerativeServiceRestInterceptor):
72
+ def pre_batch_embed_contents(self, request, metadata):
73
+ logging.log(f"Received request: {request}")
74
+ return request, metadata
75
+
76
+ def post_batch_embed_contents(self, response):
77
+ logging.log(f"Received response: {response}")
78
+ return response
79
+
80
+ def pre_count_tokens(self, request, metadata):
81
+ logging.log(f"Received request: {request}")
82
+ return request, metadata
83
+
84
+ def post_count_tokens(self, response):
85
+ logging.log(f"Received response: {response}")
86
+ return response
87
+
88
+ def pre_embed_content(self, request, metadata):
89
+ logging.log(f"Received request: {request}")
90
+ return request, metadata
91
+
92
+ def post_embed_content(self, response):
93
+ logging.log(f"Received response: {response}")
94
+ return response
95
+
96
+ def pre_generate_content(self, request, metadata):
97
+ logging.log(f"Received request: {request}")
98
+ return request, metadata
99
+
100
+ def post_generate_content(self, response):
101
+ logging.log(f"Received response: {response}")
102
+ return response
103
+
104
+ def pre_stream_generate_content(self, request, metadata):
105
+ logging.log(f"Received request: {request}")
106
+ return request, metadata
107
+
108
+ def post_stream_generate_content(self, response):
109
+ logging.log(f"Received response: {response}")
110
+ return response
111
+
112
+ transport = GenerativeServiceRestTransport(interceptor=MyCustomGenerativeServiceInterceptor())
113
+ client = GenerativeServiceClient(transport=transport)
114
+
115
+
116
+ """
117
+
118
+ def pre_batch_embed_contents(
119
+ self,
120
+ request: generative_service.BatchEmbedContentsRequest,
121
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
122
+ ) -> Tuple[
123
+ generative_service.BatchEmbedContentsRequest,
124
+ Sequence[Tuple[str, Union[str, bytes]]],
125
+ ]:
126
+ """Pre-rpc interceptor for batch_embed_contents
127
+
128
+ Override in a subclass to manipulate the request or metadata
129
+ before they are sent to the GenerativeService server.
130
+ """
131
+ return request, metadata
132
+
133
+ def post_batch_embed_contents(
134
+ self, response: generative_service.BatchEmbedContentsResponse
135
+ ) -> generative_service.BatchEmbedContentsResponse:
136
+ """Post-rpc interceptor for batch_embed_contents
137
+
138
+ Override in a subclass to manipulate the response
139
+ after it is returned by the GenerativeService server but before
140
+ it is returned to user code.
141
+ """
142
+ return response
143
+
144
+ def pre_count_tokens(
145
+ self,
146
+ request: generative_service.CountTokensRequest,
147
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
148
+ ) -> Tuple[
149
+ generative_service.CountTokensRequest, Sequence[Tuple[str, Union[str, bytes]]]
150
+ ]:
151
+ """Pre-rpc interceptor for count_tokens
152
+
153
+ Override in a subclass to manipulate the request or metadata
154
+ before they are sent to the GenerativeService server.
155
+ """
156
+ return request, metadata
157
+
158
+ def post_count_tokens(
159
+ self, response: generative_service.CountTokensResponse
160
+ ) -> generative_service.CountTokensResponse:
161
+ """Post-rpc interceptor for count_tokens
162
+
163
+ Override in a subclass to manipulate the response
164
+ after it is returned by the GenerativeService server but before
165
+ it is returned to user code.
166
+ """
167
+ return response
168
+
169
+ def pre_embed_content(
170
+ self,
171
+ request: generative_service.EmbedContentRequest,
172
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
173
+ ) -> Tuple[
174
+ generative_service.EmbedContentRequest, Sequence[Tuple[str, Union[str, bytes]]]
175
+ ]:
176
+ """Pre-rpc interceptor for embed_content
177
+
178
+ Override in a subclass to manipulate the request or metadata
179
+ before they are sent to the GenerativeService server.
180
+ """
181
+ return request, metadata
182
+
183
+ def post_embed_content(
184
+ self, response: generative_service.EmbedContentResponse
185
+ ) -> generative_service.EmbedContentResponse:
186
+ """Post-rpc interceptor for embed_content
187
+
188
+ Override in a subclass to manipulate the response
189
+ after it is returned by the GenerativeService server but before
190
+ it is returned to user code.
191
+ """
192
+ return response
193
+
194
+ def pre_generate_content(
195
+ self,
196
+ request: generative_service.GenerateContentRequest,
197
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
198
+ ) -> Tuple[
199
+ generative_service.GenerateContentRequest,
200
+ Sequence[Tuple[str, Union[str, bytes]]],
201
+ ]:
202
+ """Pre-rpc interceptor for generate_content
203
+
204
+ Override in a subclass to manipulate the request or metadata
205
+ before they are sent to the GenerativeService server.
206
+ """
207
+ return request, metadata
208
+
209
+ def post_generate_content(
210
+ self, response: generative_service.GenerateContentResponse
211
+ ) -> generative_service.GenerateContentResponse:
212
+ """Post-rpc interceptor for generate_content
213
+
214
+ Override in a subclass to manipulate the response
215
+ after it is returned by the GenerativeService server but before
216
+ it is returned to user code.
217
+ """
218
+ return response
219
+
220
+ def pre_stream_generate_content(
221
+ self,
222
+ request: generative_service.GenerateContentRequest,
223
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
224
+ ) -> Tuple[
225
+ generative_service.GenerateContentRequest,
226
+ Sequence[Tuple[str, Union[str, bytes]]],
227
+ ]:
228
+ """Pre-rpc interceptor for stream_generate_content
229
+
230
+ Override in a subclass to manipulate the request or metadata
231
+ before they are sent to the GenerativeService server.
232
+ """
233
+ return request, metadata
234
+
235
+ def post_stream_generate_content(
236
+ self, response: rest_streaming.ResponseIterator
237
+ ) -> rest_streaming.ResponseIterator:
238
+ """Post-rpc interceptor for stream_generate_content
239
+
240
+ Override in a subclass to manipulate the response
241
+ after it is returned by the GenerativeService server but before
242
+ it is returned to user code.
243
+ """
244
+ return response
245
+
246
+ def pre_cancel_operation(
247
+ self,
248
+ request: operations_pb2.CancelOperationRequest,
249
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
250
+ ) -> Tuple[
251
+ operations_pb2.CancelOperationRequest, Sequence[Tuple[str, Union[str, bytes]]]
252
+ ]:
253
+ """Pre-rpc interceptor for cancel_operation
254
+
255
+ Override in a subclass to manipulate the request or metadata
256
+ before they are sent to the GenerativeService server.
257
+ """
258
+ return request, metadata
259
+
260
+ def post_cancel_operation(self, response: None) -> None:
261
+ """Post-rpc interceptor for cancel_operation
262
+
263
+ Override in a subclass to manipulate the response
264
+ after it is returned by the GenerativeService server but before
265
+ it is returned to user code.
266
+ """
267
+ return response
268
+
269
+ def pre_get_operation(
270
+ self,
271
+ request: operations_pb2.GetOperationRequest,
272
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
273
+ ) -> Tuple[
274
+ operations_pb2.GetOperationRequest, Sequence[Tuple[str, Union[str, bytes]]]
275
+ ]:
276
+ """Pre-rpc interceptor for get_operation
277
+
278
+ Override in a subclass to manipulate the request or metadata
279
+ before they are sent to the GenerativeService server.
280
+ """
281
+ return request, metadata
282
+
283
+ def post_get_operation(
284
+ self, response: operations_pb2.Operation
285
+ ) -> operations_pb2.Operation:
286
+ """Post-rpc interceptor for get_operation
287
+
288
+ Override in a subclass to manipulate the response
289
+ after it is returned by the GenerativeService server but before
290
+ it is returned to user code.
291
+ """
292
+ return response
293
+
294
+ def pre_list_operations(
295
+ self,
296
+ request: operations_pb2.ListOperationsRequest,
297
+ metadata: Sequence[Tuple[str, Union[str, bytes]]],
298
+ ) -> Tuple[
299
+ operations_pb2.ListOperationsRequest, Sequence[Tuple[str, Union[str, bytes]]]
300
+ ]:
301
+ """Pre-rpc interceptor for list_operations
302
+
303
+ Override in a subclass to manipulate the request or metadata
304
+ before they are sent to the GenerativeService server.
305
+ """
306
+ return request, metadata
307
+
308
+ def post_list_operations(
309
+ self, response: operations_pb2.ListOperationsResponse
310
+ ) -> operations_pb2.ListOperationsResponse:
311
+ """Post-rpc interceptor for list_operations
312
+
313
+ Override in a subclass to manipulate the response
314
+ after it is returned by the GenerativeService server but before
315
+ it is returned to user code.
316
+ """
317
+ return response
318
+
319
+
320
+ @dataclasses.dataclass
321
+ class GenerativeServiceRestStub:
322
+ _session: AuthorizedSession
323
+ _host: str
324
+ _interceptor: GenerativeServiceRestInterceptor
325
+
326
+
327
+ class GenerativeServiceRestTransport(_BaseGenerativeServiceRestTransport):
328
+ """REST backend synchronous transport for GenerativeService.
329
+
330
+ API for using Large Models that generate multimodal content
331
+ and have additional capabilities beyond text generation.
332
+
333
+ This class defines the same methods as the primary client, so the
334
+ primary client can load the underlying transport implementation
335
+ and call it.
336
+
337
+ It sends JSON representations of protocol buffers over HTTP/1.1
338
+ """
339
+
340
+ def __init__(
341
+ self,
342
+ *,
343
+ host: str = "generativelanguage.googleapis.com",
344
+ credentials: Optional[ga_credentials.Credentials] = None,
345
+ credentials_file: Optional[str] = None,
346
+ scopes: Optional[Sequence[str]] = None,
347
+ client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
348
+ quota_project_id: Optional[str] = None,
349
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
350
+ always_use_jwt_access: Optional[bool] = False,
351
+ url_scheme: str = "https",
352
+ interceptor: Optional[GenerativeServiceRestInterceptor] = None,
353
+ api_audience: Optional[str] = None,
354
+ ) -> None:
355
+ """Instantiate the transport.
356
+
357
+ Args:
358
+ host (Optional[str]):
359
+ The hostname to connect to (default: 'generativelanguage.googleapis.com').
360
+ credentials (Optional[google.auth.credentials.Credentials]): The
361
+ authorization credentials to attach to requests. These
362
+ credentials identify the application to the service; if none
363
+ are specified, the client will attempt to ascertain the
364
+ credentials from the environment.
365
+
366
+ credentials_file (Optional[str]): A file with credentials that can
367
+ be loaded with :func:`google.auth.load_credentials_from_file`.
368
+ This argument is ignored if ``channel`` is provided.
369
+ scopes (Optional(Sequence[str])): A list of scopes. This argument is
370
+ ignored if ``channel`` is provided.
371
+ client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client
372
+ certificate to configure mutual TLS HTTP channel. It is ignored
373
+ if ``channel`` is provided.
374
+ quota_project_id (Optional[str]): An optional project to use for billing
375
+ and quota.
376
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
377
+ The client info used to send a user-agent string along with
378
+ API requests. If ``None``, then default info will be used.
379
+ Generally, you only need to set this if you are developing
380
+ your own client library.
381
+ always_use_jwt_access (Optional[bool]): Whether self signed JWT should
382
+ be used for service account credentials.
383
+ url_scheme: the protocol scheme for the API endpoint. Normally
384
+ "https", but for testing or local servers,
385
+ "http" can be specified.
386
+ """
387
+ # Run the base constructor
388
+ # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc.
389
+ # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the
390
+ # credentials object
391
+ super().__init__(
392
+ host=host,
393
+ credentials=credentials,
394
+ client_info=client_info,
395
+ always_use_jwt_access=always_use_jwt_access,
396
+ url_scheme=url_scheme,
397
+ api_audience=api_audience,
398
+ )
399
+ self._session = AuthorizedSession(
400
+ self._credentials, default_host=self.DEFAULT_HOST
401
+ )
402
+ if client_cert_source_for_mtls:
403
+ self._session.configure_mtls_channel(client_cert_source_for_mtls)
404
+ self._interceptor = interceptor or GenerativeServiceRestInterceptor()
405
+ self._prep_wrapped_messages(client_info)
406
+
407
+ class _BatchEmbedContents(
408
+ _BaseGenerativeServiceRestTransport._BaseBatchEmbedContents,
409
+ GenerativeServiceRestStub,
410
+ ):
411
+ def __hash__(self):
412
+ return hash("GenerativeServiceRestTransport.BatchEmbedContents")
413
+
414
+ @staticmethod
415
+ def _get_response(
416
+ host,
417
+ metadata,
418
+ query_params,
419
+ session,
420
+ timeout,
421
+ transcoded_request,
422
+ body=None,
423
+ ):
424
+ uri = transcoded_request["uri"]
425
+ method = transcoded_request["method"]
426
+ headers = dict(metadata)
427
+ headers["Content-Type"] = "application/json"
428
+ response = getattr(session, method)(
429
+ "{host}{uri}".format(host=host, uri=uri),
430
+ timeout=timeout,
431
+ headers=headers,
432
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
433
+ data=body,
434
+ )
435
+ return response
436
+
437
+ def __call__(
438
+ self,
439
+ request: generative_service.BatchEmbedContentsRequest,
440
+ *,
441
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
442
+ timeout: Optional[float] = None,
443
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
444
+ ) -> generative_service.BatchEmbedContentsResponse:
445
+ r"""Call the batch embed contents method over HTTP.
446
+
447
+ Args:
448
+ request (~.generative_service.BatchEmbedContentsRequest):
449
+ The request object. Batch request to get embeddings from
450
+ the model for a list of prompts.
451
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
452
+ should be retried.
453
+ timeout (float): The timeout for this request.
454
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
455
+ sent along with the request as metadata. Normally, each value must be of type `str`,
456
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
457
+ be of type `bytes`.
458
+
459
+ Returns:
460
+ ~.generative_service.BatchEmbedContentsResponse:
461
+ The response to a ``BatchEmbedContentsRequest``.
462
+ """
463
+
464
+ http_options = (
465
+ _BaseGenerativeServiceRestTransport._BaseBatchEmbedContents._get_http_options()
466
+ )
467
+
468
+ request, metadata = self._interceptor.pre_batch_embed_contents(
469
+ request, metadata
470
+ )
471
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseBatchEmbedContents._get_transcoded_request(
472
+ http_options, request
473
+ )
474
+
475
+ body = _BaseGenerativeServiceRestTransport._BaseBatchEmbedContents._get_request_body_json(
476
+ transcoded_request
477
+ )
478
+
479
+ # Jsonify the query params
480
+ query_params = _BaseGenerativeServiceRestTransport._BaseBatchEmbedContents._get_query_params_json(
481
+ transcoded_request
482
+ )
483
+
484
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
485
+ logging.DEBUG
486
+ ): # pragma: NO COVER
487
+ request_url = "{host}{uri}".format(
488
+ host=self._host, uri=transcoded_request["uri"]
489
+ )
490
+ method = transcoded_request["method"]
491
+ try:
492
+ request_payload = type(request).to_json(request)
493
+ except:
494
+ request_payload = None
495
+ http_request = {
496
+ "payload": request_payload,
497
+ "requestMethod": method,
498
+ "requestUrl": request_url,
499
+ "headers": dict(metadata),
500
+ }
501
+ _LOGGER.debug(
502
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.BatchEmbedContents",
503
+ extra={
504
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
505
+ "rpcName": "BatchEmbedContents",
506
+ "httpRequest": http_request,
507
+ "metadata": http_request["headers"],
508
+ },
509
+ )
510
+
511
+ # Send the request
512
+ response = GenerativeServiceRestTransport._BatchEmbedContents._get_response(
513
+ self._host,
514
+ metadata,
515
+ query_params,
516
+ self._session,
517
+ timeout,
518
+ transcoded_request,
519
+ body,
520
+ )
521
+
522
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
523
+ # subclass.
524
+ if response.status_code >= 400:
525
+ raise core_exceptions.from_http_response(response)
526
+
527
+ # Return the response
528
+ resp = generative_service.BatchEmbedContentsResponse()
529
+ pb_resp = generative_service.BatchEmbedContentsResponse.pb(resp)
530
+
531
+ json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
532
+
533
+ resp = self._interceptor.post_batch_embed_contents(resp)
534
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
535
+ logging.DEBUG
536
+ ): # pragma: NO COVER
537
+ try:
538
+ response_payload = (
539
+ generative_service.BatchEmbedContentsResponse.to_json(response)
540
+ )
541
+ except:
542
+ response_payload = None
543
+ http_response = {
544
+ "payload": response_payload,
545
+ "headers": dict(response.headers),
546
+ "status": response.status_code,
547
+ }
548
+ _LOGGER.debug(
549
+ "Received response for google.ai.generativelanguage_v1.GenerativeServiceClient.batch_embed_contents",
550
+ extra={
551
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
552
+ "rpcName": "BatchEmbedContents",
553
+ "metadata": http_response["headers"],
554
+ "httpResponse": http_response,
555
+ },
556
+ )
557
+ return resp
558
+
559
+ class _CountTokens(
560
+ _BaseGenerativeServiceRestTransport._BaseCountTokens, GenerativeServiceRestStub
561
+ ):
562
+ def __hash__(self):
563
+ return hash("GenerativeServiceRestTransport.CountTokens")
564
+
565
+ @staticmethod
566
+ def _get_response(
567
+ host,
568
+ metadata,
569
+ query_params,
570
+ session,
571
+ timeout,
572
+ transcoded_request,
573
+ body=None,
574
+ ):
575
+ uri = transcoded_request["uri"]
576
+ method = transcoded_request["method"]
577
+ headers = dict(metadata)
578
+ headers["Content-Type"] = "application/json"
579
+ response = getattr(session, method)(
580
+ "{host}{uri}".format(host=host, uri=uri),
581
+ timeout=timeout,
582
+ headers=headers,
583
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
584
+ data=body,
585
+ )
586
+ return response
587
+
588
+ def __call__(
589
+ self,
590
+ request: generative_service.CountTokensRequest,
591
+ *,
592
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
593
+ timeout: Optional[float] = None,
594
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
595
+ ) -> generative_service.CountTokensResponse:
596
+ r"""Call the count tokens method over HTTP.
597
+
598
+ Args:
599
+ request (~.generative_service.CountTokensRequest):
600
+ The request object. Counts the number of tokens in the ``prompt`` sent to a
601
+ model.
602
+
603
+ Models may tokenize text differently, so each model may
604
+ return a different ``token_count``.
605
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
606
+ should be retried.
607
+ timeout (float): The timeout for this request.
608
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
609
+ sent along with the request as metadata. Normally, each value must be of type `str`,
610
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
611
+ be of type `bytes`.
612
+
613
+ Returns:
614
+ ~.generative_service.CountTokensResponse:
615
+ A response from ``CountTokens``.
616
+
617
+ It returns the model's ``token_count`` for the
618
+ ``prompt``.
619
+
620
+ """
621
+
622
+ http_options = (
623
+ _BaseGenerativeServiceRestTransport._BaseCountTokens._get_http_options()
624
+ )
625
+
626
+ request, metadata = self._interceptor.pre_count_tokens(request, metadata)
627
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseCountTokens._get_transcoded_request(
628
+ http_options, request
629
+ )
630
+
631
+ body = _BaseGenerativeServiceRestTransport._BaseCountTokens._get_request_body_json(
632
+ transcoded_request
633
+ )
634
+
635
+ # Jsonify the query params
636
+ query_params = _BaseGenerativeServiceRestTransport._BaseCountTokens._get_query_params_json(
637
+ transcoded_request
638
+ )
639
+
640
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
641
+ logging.DEBUG
642
+ ): # pragma: NO COVER
643
+ request_url = "{host}{uri}".format(
644
+ host=self._host, uri=transcoded_request["uri"]
645
+ )
646
+ method = transcoded_request["method"]
647
+ try:
648
+ request_payload = type(request).to_json(request)
649
+ except:
650
+ request_payload = None
651
+ http_request = {
652
+ "payload": request_payload,
653
+ "requestMethod": method,
654
+ "requestUrl": request_url,
655
+ "headers": dict(metadata),
656
+ }
657
+ _LOGGER.debug(
658
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.CountTokens",
659
+ extra={
660
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
661
+ "rpcName": "CountTokens",
662
+ "httpRequest": http_request,
663
+ "metadata": http_request["headers"],
664
+ },
665
+ )
666
+
667
+ # Send the request
668
+ response = GenerativeServiceRestTransport._CountTokens._get_response(
669
+ self._host,
670
+ metadata,
671
+ query_params,
672
+ self._session,
673
+ timeout,
674
+ transcoded_request,
675
+ body,
676
+ )
677
+
678
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
679
+ # subclass.
680
+ if response.status_code >= 400:
681
+ raise core_exceptions.from_http_response(response)
682
+
683
+ # Return the response
684
+ resp = generative_service.CountTokensResponse()
685
+ pb_resp = generative_service.CountTokensResponse.pb(resp)
686
+
687
+ json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
688
+
689
+ resp = self._interceptor.post_count_tokens(resp)
690
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
691
+ logging.DEBUG
692
+ ): # pragma: NO COVER
693
+ try:
694
+ response_payload = generative_service.CountTokensResponse.to_json(
695
+ response
696
+ )
697
+ except:
698
+ response_payload = None
699
+ http_response = {
700
+ "payload": response_payload,
701
+ "headers": dict(response.headers),
702
+ "status": response.status_code,
703
+ }
704
+ _LOGGER.debug(
705
+ "Received response for google.ai.generativelanguage_v1.GenerativeServiceClient.count_tokens",
706
+ extra={
707
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
708
+ "rpcName": "CountTokens",
709
+ "metadata": http_response["headers"],
710
+ "httpResponse": http_response,
711
+ },
712
+ )
713
+ return resp
714
+
715
+ class _EmbedContent(
716
+ _BaseGenerativeServiceRestTransport._BaseEmbedContent, GenerativeServiceRestStub
717
+ ):
718
+ def __hash__(self):
719
+ return hash("GenerativeServiceRestTransport.EmbedContent")
720
+
721
+ @staticmethod
722
+ def _get_response(
723
+ host,
724
+ metadata,
725
+ query_params,
726
+ session,
727
+ timeout,
728
+ transcoded_request,
729
+ body=None,
730
+ ):
731
+ uri = transcoded_request["uri"]
732
+ method = transcoded_request["method"]
733
+ headers = dict(metadata)
734
+ headers["Content-Type"] = "application/json"
735
+ response = getattr(session, method)(
736
+ "{host}{uri}".format(host=host, uri=uri),
737
+ timeout=timeout,
738
+ headers=headers,
739
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
740
+ data=body,
741
+ )
742
+ return response
743
+
744
+ def __call__(
745
+ self,
746
+ request: generative_service.EmbedContentRequest,
747
+ *,
748
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
749
+ timeout: Optional[float] = None,
750
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
751
+ ) -> generative_service.EmbedContentResponse:
752
+ r"""Call the embed content method over HTTP.
753
+
754
+ Args:
755
+ request (~.generative_service.EmbedContentRequest):
756
+ The request object. Request containing the ``Content`` for the model to
757
+ embed.
758
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
759
+ should be retried.
760
+ timeout (float): The timeout for this request.
761
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
762
+ sent along with the request as metadata. Normally, each value must be of type `str`,
763
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
764
+ be of type `bytes`.
765
+
766
+ Returns:
767
+ ~.generative_service.EmbedContentResponse:
768
+ The response to an ``EmbedContentRequest``.
769
+ """
770
+
771
+ http_options = (
772
+ _BaseGenerativeServiceRestTransport._BaseEmbedContent._get_http_options()
773
+ )
774
+
775
+ request, metadata = self._interceptor.pre_embed_content(request, metadata)
776
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseEmbedContent._get_transcoded_request(
777
+ http_options, request
778
+ )
779
+
780
+ body = _BaseGenerativeServiceRestTransport._BaseEmbedContent._get_request_body_json(
781
+ transcoded_request
782
+ )
783
+
784
+ # Jsonify the query params
785
+ query_params = _BaseGenerativeServiceRestTransport._BaseEmbedContent._get_query_params_json(
786
+ transcoded_request
787
+ )
788
+
789
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
790
+ logging.DEBUG
791
+ ): # pragma: NO COVER
792
+ request_url = "{host}{uri}".format(
793
+ host=self._host, uri=transcoded_request["uri"]
794
+ )
795
+ method = transcoded_request["method"]
796
+ try:
797
+ request_payload = type(request).to_json(request)
798
+ except:
799
+ request_payload = None
800
+ http_request = {
801
+ "payload": request_payload,
802
+ "requestMethod": method,
803
+ "requestUrl": request_url,
804
+ "headers": dict(metadata),
805
+ }
806
+ _LOGGER.debug(
807
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.EmbedContent",
808
+ extra={
809
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
810
+ "rpcName": "EmbedContent",
811
+ "httpRequest": http_request,
812
+ "metadata": http_request["headers"],
813
+ },
814
+ )
815
+
816
+ # Send the request
817
+ response = GenerativeServiceRestTransport._EmbedContent._get_response(
818
+ self._host,
819
+ metadata,
820
+ query_params,
821
+ self._session,
822
+ timeout,
823
+ transcoded_request,
824
+ body,
825
+ )
826
+
827
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
828
+ # subclass.
829
+ if response.status_code >= 400:
830
+ raise core_exceptions.from_http_response(response)
831
+
832
+ # Return the response
833
+ resp = generative_service.EmbedContentResponse()
834
+ pb_resp = generative_service.EmbedContentResponse.pb(resp)
835
+
836
+ json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
837
+
838
+ resp = self._interceptor.post_embed_content(resp)
839
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
840
+ logging.DEBUG
841
+ ): # pragma: NO COVER
842
+ try:
843
+ response_payload = generative_service.EmbedContentResponse.to_json(
844
+ response
845
+ )
846
+ except:
847
+ response_payload = None
848
+ http_response = {
849
+ "payload": response_payload,
850
+ "headers": dict(response.headers),
851
+ "status": response.status_code,
852
+ }
853
+ _LOGGER.debug(
854
+ "Received response for google.ai.generativelanguage_v1.GenerativeServiceClient.embed_content",
855
+ extra={
856
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
857
+ "rpcName": "EmbedContent",
858
+ "metadata": http_response["headers"],
859
+ "httpResponse": http_response,
860
+ },
861
+ )
862
+ return resp
863
+
864
+ class _GenerateContent(
865
+ _BaseGenerativeServiceRestTransport._BaseGenerateContent,
866
+ GenerativeServiceRestStub,
867
+ ):
868
+ def __hash__(self):
869
+ return hash("GenerativeServiceRestTransport.GenerateContent")
870
+
871
+ @staticmethod
872
+ def _get_response(
873
+ host,
874
+ metadata,
875
+ query_params,
876
+ session,
877
+ timeout,
878
+ transcoded_request,
879
+ body=None,
880
+ ):
881
+ uri = transcoded_request["uri"]
882
+ method = transcoded_request["method"]
883
+ headers = dict(metadata)
884
+ headers["Content-Type"] = "application/json"
885
+ response = getattr(session, method)(
886
+ "{host}{uri}".format(host=host, uri=uri),
887
+ timeout=timeout,
888
+ headers=headers,
889
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
890
+ data=body,
891
+ )
892
+ return response
893
+
894
+ def __call__(
895
+ self,
896
+ request: generative_service.GenerateContentRequest,
897
+ *,
898
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
899
+ timeout: Optional[float] = None,
900
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
901
+ ) -> generative_service.GenerateContentResponse:
902
+ r"""Call the generate content method over HTTP.
903
+
904
+ Args:
905
+ request (~.generative_service.GenerateContentRequest):
906
+ The request object. Request to generate a completion from
907
+ the model.
908
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
909
+ should be retried.
910
+ timeout (float): The timeout for this request.
911
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
912
+ sent along with the request as metadata. Normally, each value must be of type `str`,
913
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
914
+ be of type `bytes`.
915
+
916
+ Returns:
917
+ ~.generative_service.GenerateContentResponse:
918
+ Response from the model supporting multiple candidate
919
+ responses.
920
+
921
+ Safety ratings and content filtering are reported for
922
+ both prompt in
923
+ ``GenerateContentResponse.prompt_feedback`` and for each
924
+ candidate in ``finish_reason`` and in
925
+ ``safety_ratings``. The API:
926
+
927
+ - Returns either all requested candidates or none of
928
+ them
929
+ - Returns no candidates at all only if there was
930
+ something wrong with the prompt (check
931
+ ``prompt_feedback``)
932
+ - Reports feedback on each candidate in
933
+ ``finish_reason`` and ``safety_ratings``.
934
+
935
+ """
936
+
937
+ http_options = (
938
+ _BaseGenerativeServiceRestTransport._BaseGenerateContent._get_http_options()
939
+ )
940
+
941
+ request, metadata = self._interceptor.pre_generate_content(
942
+ request, metadata
943
+ )
944
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseGenerateContent._get_transcoded_request(
945
+ http_options, request
946
+ )
947
+
948
+ body = _BaseGenerativeServiceRestTransport._BaseGenerateContent._get_request_body_json(
949
+ transcoded_request
950
+ )
951
+
952
+ # Jsonify the query params
953
+ query_params = _BaseGenerativeServiceRestTransport._BaseGenerateContent._get_query_params_json(
954
+ transcoded_request
955
+ )
956
+
957
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
958
+ logging.DEBUG
959
+ ): # pragma: NO COVER
960
+ request_url = "{host}{uri}".format(
961
+ host=self._host, uri=transcoded_request["uri"]
962
+ )
963
+ method = transcoded_request["method"]
964
+ try:
965
+ request_payload = type(request).to_json(request)
966
+ except:
967
+ request_payload = None
968
+ http_request = {
969
+ "payload": request_payload,
970
+ "requestMethod": method,
971
+ "requestUrl": request_url,
972
+ "headers": dict(metadata),
973
+ }
974
+ _LOGGER.debug(
975
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.GenerateContent",
976
+ extra={
977
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
978
+ "rpcName": "GenerateContent",
979
+ "httpRequest": http_request,
980
+ "metadata": http_request["headers"],
981
+ },
982
+ )
983
+
984
+ # Send the request
985
+ response = GenerativeServiceRestTransport._GenerateContent._get_response(
986
+ self._host,
987
+ metadata,
988
+ query_params,
989
+ self._session,
990
+ timeout,
991
+ transcoded_request,
992
+ body,
993
+ )
994
+
995
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
996
+ # subclass.
997
+ if response.status_code >= 400:
998
+ raise core_exceptions.from_http_response(response)
999
+
1000
+ # Return the response
1001
+ resp = generative_service.GenerateContentResponse()
1002
+ pb_resp = generative_service.GenerateContentResponse.pb(resp)
1003
+
1004
+ json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True)
1005
+
1006
+ resp = self._interceptor.post_generate_content(resp)
1007
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
1008
+ logging.DEBUG
1009
+ ): # pragma: NO COVER
1010
+ try:
1011
+ response_payload = (
1012
+ generative_service.GenerateContentResponse.to_json(response)
1013
+ )
1014
+ except:
1015
+ response_payload = None
1016
+ http_response = {
1017
+ "payload": response_payload,
1018
+ "headers": dict(response.headers),
1019
+ "status": response.status_code,
1020
+ }
1021
+ _LOGGER.debug(
1022
+ "Received response for google.ai.generativelanguage_v1.GenerativeServiceClient.generate_content",
1023
+ extra={
1024
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
1025
+ "rpcName": "GenerateContent",
1026
+ "metadata": http_response["headers"],
1027
+ "httpResponse": http_response,
1028
+ },
1029
+ )
1030
+ return resp
1031
+
1032
+ class _StreamGenerateContent(
1033
+ _BaseGenerativeServiceRestTransport._BaseStreamGenerateContent,
1034
+ GenerativeServiceRestStub,
1035
+ ):
1036
+ def __hash__(self):
1037
+ return hash("GenerativeServiceRestTransport.StreamGenerateContent")
1038
+
1039
+ @staticmethod
1040
+ def _get_response(
1041
+ host,
1042
+ metadata,
1043
+ query_params,
1044
+ session,
1045
+ timeout,
1046
+ transcoded_request,
1047
+ body=None,
1048
+ ):
1049
+ uri = transcoded_request["uri"]
1050
+ method = transcoded_request["method"]
1051
+ headers = dict(metadata)
1052
+ headers["Content-Type"] = "application/json"
1053
+ response = getattr(session, method)(
1054
+ "{host}{uri}".format(host=host, uri=uri),
1055
+ timeout=timeout,
1056
+ headers=headers,
1057
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
1058
+ data=body,
1059
+ stream=True,
1060
+ )
1061
+ return response
1062
+
1063
+ def __call__(
1064
+ self,
1065
+ request: generative_service.GenerateContentRequest,
1066
+ *,
1067
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1068
+ timeout: Optional[float] = None,
1069
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1070
+ ) -> rest_streaming.ResponseIterator:
1071
+ r"""Call the stream generate content method over HTTP.
1072
+
1073
+ Args:
1074
+ request (~.generative_service.GenerateContentRequest):
1075
+ The request object. Request to generate a completion from
1076
+ the model.
1077
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
1078
+ should be retried.
1079
+ timeout (float): The timeout for this request.
1080
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1081
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1082
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1083
+ be of type `bytes`.
1084
+
1085
+ Returns:
1086
+ ~.generative_service.GenerateContentResponse:
1087
+ Response from the model supporting multiple candidate
1088
+ responses.
1089
+
1090
+ Safety ratings and content filtering are reported for
1091
+ both prompt in
1092
+ ``GenerateContentResponse.prompt_feedback`` and for each
1093
+ candidate in ``finish_reason`` and in
1094
+ ``safety_ratings``. The API:
1095
+
1096
+ - Returns either all requested candidates or none of
1097
+ them
1098
+ - Returns no candidates at all only if there was
1099
+ something wrong with the prompt (check
1100
+ ``prompt_feedback``)
1101
+ - Reports feedback on each candidate in
1102
+ ``finish_reason`` and ``safety_ratings``.
1103
+
1104
+ """
1105
+
1106
+ http_options = (
1107
+ _BaseGenerativeServiceRestTransport._BaseStreamGenerateContent._get_http_options()
1108
+ )
1109
+
1110
+ request, metadata = self._interceptor.pre_stream_generate_content(
1111
+ request, metadata
1112
+ )
1113
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseStreamGenerateContent._get_transcoded_request(
1114
+ http_options, request
1115
+ )
1116
+
1117
+ body = _BaseGenerativeServiceRestTransport._BaseStreamGenerateContent._get_request_body_json(
1118
+ transcoded_request
1119
+ )
1120
+
1121
+ # Jsonify the query params
1122
+ query_params = _BaseGenerativeServiceRestTransport._BaseStreamGenerateContent._get_query_params_json(
1123
+ transcoded_request
1124
+ )
1125
+
1126
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
1127
+ logging.DEBUG
1128
+ ): # pragma: NO COVER
1129
+ request_url = "{host}{uri}".format(
1130
+ host=self._host, uri=transcoded_request["uri"]
1131
+ )
1132
+ method = transcoded_request["method"]
1133
+ try:
1134
+ request_payload = type(request).to_json(request)
1135
+ except:
1136
+ request_payload = None
1137
+ http_request = {
1138
+ "payload": request_payload,
1139
+ "requestMethod": method,
1140
+ "requestUrl": request_url,
1141
+ "headers": dict(metadata),
1142
+ }
1143
+ _LOGGER.debug(
1144
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.StreamGenerateContent",
1145
+ extra={
1146
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
1147
+ "rpcName": "StreamGenerateContent",
1148
+ "httpRequest": http_request,
1149
+ "metadata": http_request["headers"],
1150
+ },
1151
+ )
1152
+
1153
+ # Send the request
1154
+ response = (
1155
+ GenerativeServiceRestTransport._StreamGenerateContent._get_response(
1156
+ self._host,
1157
+ metadata,
1158
+ query_params,
1159
+ self._session,
1160
+ timeout,
1161
+ transcoded_request,
1162
+ body,
1163
+ )
1164
+ )
1165
+
1166
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
1167
+ # subclass.
1168
+ if response.status_code >= 400:
1169
+ raise core_exceptions.from_http_response(response)
1170
+
1171
+ # Return the response
1172
+ resp = rest_streaming.ResponseIterator(
1173
+ response, generative_service.GenerateContentResponse
1174
+ )
1175
+
1176
+ resp = self._interceptor.post_stream_generate_content(resp)
1177
+ return resp
1178
+
1179
+ @property
1180
+ def batch_embed_contents(
1181
+ self,
1182
+ ) -> Callable[
1183
+ [generative_service.BatchEmbedContentsRequest],
1184
+ generative_service.BatchEmbedContentsResponse,
1185
+ ]:
1186
+ # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
1187
+ # In C++ this would require a dynamic_cast
1188
+ return self._BatchEmbedContents(self._session, self._host, self._interceptor) # type: ignore
1189
+
1190
+ @property
1191
+ def count_tokens(
1192
+ self,
1193
+ ) -> Callable[
1194
+ [generative_service.CountTokensRequest], generative_service.CountTokensResponse
1195
+ ]:
1196
+ # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
1197
+ # In C++ this would require a dynamic_cast
1198
+ return self._CountTokens(self._session, self._host, self._interceptor) # type: ignore
1199
+
1200
+ @property
1201
+ def embed_content(
1202
+ self,
1203
+ ) -> Callable[
1204
+ [generative_service.EmbedContentRequest],
1205
+ generative_service.EmbedContentResponse,
1206
+ ]:
1207
+ # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
1208
+ # In C++ this would require a dynamic_cast
1209
+ return self._EmbedContent(self._session, self._host, self._interceptor) # type: ignore
1210
+
1211
+ @property
1212
+ def generate_content(
1213
+ self,
1214
+ ) -> Callable[
1215
+ [generative_service.GenerateContentRequest],
1216
+ generative_service.GenerateContentResponse,
1217
+ ]:
1218
+ # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
1219
+ # In C++ this would require a dynamic_cast
1220
+ return self._GenerateContent(self._session, self._host, self._interceptor) # type: ignore
1221
+
1222
+ @property
1223
+ def stream_generate_content(
1224
+ self,
1225
+ ) -> Callable[
1226
+ [generative_service.GenerateContentRequest],
1227
+ generative_service.GenerateContentResponse,
1228
+ ]:
1229
+ # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
1230
+ # In C++ this would require a dynamic_cast
1231
+ return self._StreamGenerateContent(self._session, self._host, self._interceptor) # type: ignore
1232
+
1233
+ @property
1234
+ def cancel_operation(self):
1235
+ return self._CancelOperation(self._session, self._host, self._interceptor) # type: ignore
1236
+
1237
+ class _CancelOperation(
1238
+ _BaseGenerativeServiceRestTransport._BaseCancelOperation,
1239
+ GenerativeServiceRestStub,
1240
+ ):
1241
+ def __hash__(self):
1242
+ return hash("GenerativeServiceRestTransport.CancelOperation")
1243
+
1244
+ @staticmethod
1245
+ def _get_response(
1246
+ host,
1247
+ metadata,
1248
+ query_params,
1249
+ session,
1250
+ timeout,
1251
+ transcoded_request,
1252
+ body=None,
1253
+ ):
1254
+ uri = transcoded_request["uri"]
1255
+ method = transcoded_request["method"]
1256
+ headers = dict(metadata)
1257
+ headers["Content-Type"] = "application/json"
1258
+ response = getattr(session, method)(
1259
+ "{host}{uri}".format(host=host, uri=uri),
1260
+ timeout=timeout,
1261
+ headers=headers,
1262
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
1263
+ data=body,
1264
+ )
1265
+ return response
1266
+
1267
+ def __call__(
1268
+ self,
1269
+ request: operations_pb2.CancelOperationRequest,
1270
+ *,
1271
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1272
+ timeout: Optional[float] = None,
1273
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1274
+ ) -> None:
1275
+ r"""Call the cancel operation method over HTTP.
1276
+
1277
+ Args:
1278
+ request (operations_pb2.CancelOperationRequest):
1279
+ The request object for CancelOperation method.
1280
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
1281
+ should be retried.
1282
+ timeout (float): The timeout for this request.
1283
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1284
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1285
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1286
+ be of type `bytes`.
1287
+ """
1288
+
1289
+ http_options = (
1290
+ _BaseGenerativeServiceRestTransport._BaseCancelOperation._get_http_options()
1291
+ )
1292
+
1293
+ request, metadata = self._interceptor.pre_cancel_operation(
1294
+ request, metadata
1295
+ )
1296
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseCancelOperation._get_transcoded_request(
1297
+ http_options, request
1298
+ )
1299
+
1300
+ body = _BaseGenerativeServiceRestTransport._BaseCancelOperation._get_request_body_json(
1301
+ transcoded_request
1302
+ )
1303
+
1304
+ # Jsonify the query params
1305
+ query_params = _BaseGenerativeServiceRestTransport._BaseCancelOperation._get_query_params_json(
1306
+ transcoded_request
1307
+ )
1308
+
1309
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
1310
+ logging.DEBUG
1311
+ ): # pragma: NO COVER
1312
+ request_url = "{host}{uri}".format(
1313
+ host=self._host, uri=transcoded_request["uri"]
1314
+ )
1315
+ method = transcoded_request["method"]
1316
+ try:
1317
+ request_payload = json_format.MessageToJson(request)
1318
+ except:
1319
+ request_payload = None
1320
+ http_request = {
1321
+ "payload": request_payload,
1322
+ "requestMethod": method,
1323
+ "requestUrl": request_url,
1324
+ "headers": dict(metadata),
1325
+ }
1326
+ _LOGGER.debug(
1327
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.CancelOperation",
1328
+ extra={
1329
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
1330
+ "rpcName": "CancelOperation",
1331
+ "httpRequest": http_request,
1332
+ "metadata": http_request["headers"],
1333
+ },
1334
+ )
1335
+
1336
+ # Send the request
1337
+ response = GenerativeServiceRestTransport._CancelOperation._get_response(
1338
+ self._host,
1339
+ metadata,
1340
+ query_params,
1341
+ self._session,
1342
+ timeout,
1343
+ transcoded_request,
1344
+ body,
1345
+ )
1346
+
1347
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
1348
+ # subclass.
1349
+ if response.status_code >= 400:
1350
+ raise core_exceptions.from_http_response(response)
1351
+
1352
+ return self._interceptor.post_cancel_operation(None)
1353
+
1354
+ @property
1355
+ def get_operation(self):
1356
+ return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore
1357
+
1358
+ class _GetOperation(
1359
+ _BaseGenerativeServiceRestTransport._BaseGetOperation, GenerativeServiceRestStub
1360
+ ):
1361
+ def __hash__(self):
1362
+ return hash("GenerativeServiceRestTransport.GetOperation")
1363
+
1364
+ @staticmethod
1365
+ def _get_response(
1366
+ host,
1367
+ metadata,
1368
+ query_params,
1369
+ session,
1370
+ timeout,
1371
+ transcoded_request,
1372
+ body=None,
1373
+ ):
1374
+ uri = transcoded_request["uri"]
1375
+ method = transcoded_request["method"]
1376
+ headers = dict(metadata)
1377
+ headers["Content-Type"] = "application/json"
1378
+ response = getattr(session, method)(
1379
+ "{host}{uri}".format(host=host, uri=uri),
1380
+ timeout=timeout,
1381
+ headers=headers,
1382
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
1383
+ )
1384
+ return response
1385
+
1386
+ def __call__(
1387
+ self,
1388
+ request: operations_pb2.GetOperationRequest,
1389
+ *,
1390
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1391
+ timeout: Optional[float] = None,
1392
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1393
+ ) -> operations_pb2.Operation:
1394
+ r"""Call the get operation method over HTTP.
1395
+
1396
+ Args:
1397
+ request (operations_pb2.GetOperationRequest):
1398
+ The request object for GetOperation method.
1399
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
1400
+ should be retried.
1401
+ timeout (float): The timeout for this request.
1402
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1403
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1404
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1405
+ be of type `bytes`.
1406
+
1407
+ Returns:
1408
+ operations_pb2.Operation: Response from GetOperation method.
1409
+ """
1410
+
1411
+ http_options = (
1412
+ _BaseGenerativeServiceRestTransport._BaseGetOperation._get_http_options()
1413
+ )
1414
+
1415
+ request, metadata = self._interceptor.pre_get_operation(request, metadata)
1416
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseGetOperation._get_transcoded_request(
1417
+ http_options, request
1418
+ )
1419
+
1420
+ # Jsonify the query params
1421
+ query_params = _BaseGenerativeServiceRestTransport._BaseGetOperation._get_query_params_json(
1422
+ transcoded_request
1423
+ )
1424
+
1425
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
1426
+ logging.DEBUG
1427
+ ): # pragma: NO COVER
1428
+ request_url = "{host}{uri}".format(
1429
+ host=self._host, uri=transcoded_request["uri"]
1430
+ )
1431
+ method = transcoded_request["method"]
1432
+ try:
1433
+ request_payload = json_format.MessageToJson(request)
1434
+ except:
1435
+ request_payload = None
1436
+ http_request = {
1437
+ "payload": request_payload,
1438
+ "requestMethod": method,
1439
+ "requestUrl": request_url,
1440
+ "headers": dict(metadata),
1441
+ }
1442
+ _LOGGER.debug(
1443
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.GetOperation",
1444
+ extra={
1445
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
1446
+ "rpcName": "GetOperation",
1447
+ "httpRequest": http_request,
1448
+ "metadata": http_request["headers"],
1449
+ },
1450
+ )
1451
+
1452
+ # Send the request
1453
+ response = GenerativeServiceRestTransport._GetOperation._get_response(
1454
+ self._host,
1455
+ metadata,
1456
+ query_params,
1457
+ self._session,
1458
+ timeout,
1459
+ transcoded_request,
1460
+ )
1461
+
1462
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
1463
+ # subclass.
1464
+ if response.status_code >= 400:
1465
+ raise core_exceptions.from_http_response(response)
1466
+
1467
+ content = response.content.decode("utf-8")
1468
+ resp = operations_pb2.Operation()
1469
+ resp = json_format.Parse(content, resp)
1470
+ resp = self._interceptor.post_get_operation(resp)
1471
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
1472
+ logging.DEBUG
1473
+ ): # pragma: NO COVER
1474
+ try:
1475
+ response_payload = json_format.MessageToJson(resp)
1476
+ except:
1477
+ response_payload = None
1478
+ http_response = {
1479
+ "payload": response_payload,
1480
+ "headers": dict(response.headers),
1481
+ "status": response.status_code,
1482
+ }
1483
+ _LOGGER.debug(
1484
+ "Received response for google.ai.generativelanguage_v1.GenerativeServiceAsyncClient.GetOperation",
1485
+ extra={
1486
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
1487
+ "rpcName": "GetOperation",
1488
+ "httpResponse": http_response,
1489
+ "metadata": http_response["headers"],
1490
+ },
1491
+ )
1492
+ return resp
1493
+
1494
+ @property
1495
+ def list_operations(self):
1496
+ return self._ListOperations(self._session, self._host, self._interceptor) # type: ignore
1497
+
1498
+ class _ListOperations(
1499
+ _BaseGenerativeServiceRestTransport._BaseListOperations,
1500
+ GenerativeServiceRestStub,
1501
+ ):
1502
+ def __hash__(self):
1503
+ return hash("GenerativeServiceRestTransport.ListOperations")
1504
+
1505
+ @staticmethod
1506
+ def _get_response(
1507
+ host,
1508
+ metadata,
1509
+ query_params,
1510
+ session,
1511
+ timeout,
1512
+ transcoded_request,
1513
+ body=None,
1514
+ ):
1515
+ uri = transcoded_request["uri"]
1516
+ method = transcoded_request["method"]
1517
+ headers = dict(metadata)
1518
+ headers["Content-Type"] = "application/json"
1519
+ response = getattr(session, method)(
1520
+ "{host}{uri}".format(host=host, uri=uri),
1521
+ timeout=timeout,
1522
+ headers=headers,
1523
+ params=rest_helpers.flatten_query_params(query_params, strict=True),
1524
+ )
1525
+ return response
1526
+
1527
+ def __call__(
1528
+ self,
1529
+ request: operations_pb2.ListOperationsRequest,
1530
+ *,
1531
+ retry: OptionalRetry = gapic_v1.method.DEFAULT,
1532
+ timeout: Optional[float] = None,
1533
+ metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
1534
+ ) -> operations_pb2.ListOperationsResponse:
1535
+ r"""Call the list operations method over HTTP.
1536
+
1537
+ Args:
1538
+ request (operations_pb2.ListOperationsRequest):
1539
+ The request object for ListOperations method.
1540
+ retry (google.api_core.retry.Retry): Designation of what errors, if any,
1541
+ should be retried.
1542
+ timeout (float): The timeout for this request.
1543
+ metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be
1544
+ sent along with the request as metadata. Normally, each value must be of type `str`,
1545
+ but for metadata keys ending with the suffix `-bin`, the corresponding values must
1546
+ be of type `bytes`.
1547
+
1548
+ Returns:
1549
+ operations_pb2.ListOperationsResponse: Response from ListOperations method.
1550
+ """
1551
+
1552
+ http_options = (
1553
+ _BaseGenerativeServiceRestTransport._BaseListOperations._get_http_options()
1554
+ )
1555
+
1556
+ request, metadata = self._interceptor.pre_list_operations(request, metadata)
1557
+ transcoded_request = _BaseGenerativeServiceRestTransport._BaseListOperations._get_transcoded_request(
1558
+ http_options, request
1559
+ )
1560
+
1561
+ # Jsonify the query params
1562
+ query_params = _BaseGenerativeServiceRestTransport._BaseListOperations._get_query_params_json(
1563
+ transcoded_request
1564
+ )
1565
+
1566
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
1567
+ logging.DEBUG
1568
+ ): # pragma: NO COVER
1569
+ request_url = "{host}{uri}".format(
1570
+ host=self._host, uri=transcoded_request["uri"]
1571
+ )
1572
+ method = transcoded_request["method"]
1573
+ try:
1574
+ request_payload = json_format.MessageToJson(request)
1575
+ except:
1576
+ request_payload = None
1577
+ http_request = {
1578
+ "payload": request_payload,
1579
+ "requestMethod": method,
1580
+ "requestUrl": request_url,
1581
+ "headers": dict(metadata),
1582
+ }
1583
+ _LOGGER.debug(
1584
+ f"Sending request for google.ai.generativelanguage_v1.GenerativeServiceClient.ListOperations",
1585
+ extra={
1586
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
1587
+ "rpcName": "ListOperations",
1588
+ "httpRequest": http_request,
1589
+ "metadata": http_request["headers"],
1590
+ },
1591
+ )
1592
+
1593
+ # Send the request
1594
+ response = GenerativeServiceRestTransport._ListOperations._get_response(
1595
+ self._host,
1596
+ metadata,
1597
+ query_params,
1598
+ self._session,
1599
+ timeout,
1600
+ transcoded_request,
1601
+ )
1602
+
1603
+ # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception
1604
+ # subclass.
1605
+ if response.status_code >= 400:
1606
+ raise core_exceptions.from_http_response(response)
1607
+
1608
+ content = response.content.decode("utf-8")
1609
+ resp = operations_pb2.ListOperationsResponse()
1610
+ resp = json_format.Parse(content, resp)
1611
+ resp = self._interceptor.post_list_operations(resp)
1612
+ if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor(
1613
+ logging.DEBUG
1614
+ ): # pragma: NO COVER
1615
+ try:
1616
+ response_payload = json_format.MessageToJson(resp)
1617
+ except:
1618
+ response_payload = None
1619
+ http_response = {
1620
+ "payload": response_payload,
1621
+ "headers": dict(response.headers),
1622
+ "status": response.status_code,
1623
+ }
1624
+ _LOGGER.debug(
1625
+ "Received response for google.ai.generativelanguage_v1.GenerativeServiceAsyncClient.ListOperations",
1626
+ extra={
1627
+ "serviceName": "google.ai.generativelanguage.v1.GenerativeService",
1628
+ "rpcName": "ListOperations",
1629
+ "httpResponse": http_response,
1630
+ "metadata": http_response["headers"],
1631
+ },
1632
+ )
1633
+ return resp
1634
+
1635
+ @property
1636
+ def kind(self) -> str:
1637
+ return "rest"
1638
+
1639
+ def close(self):
1640
+ self._session.close()
1641
+
1642
+
1643
+ __all__ = ("GenerativeServiceRestTransport",)
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/generative_service/transports/rest_base.py ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ import json # type: ignore
17
+ import re
18
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
19
+
20
+ from google.api_core import gapic_v1, path_template
21
+ from google.longrunning import operations_pb2 # type: ignore
22
+ from google.protobuf import json_format
23
+
24
+ from google.ai.generativelanguage_v1.types import generative_service
25
+
26
+ from .base import DEFAULT_CLIENT_INFO, GenerativeServiceTransport
27
+
28
+
29
+ class _BaseGenerativeServiceRestTransport(GenerativeServiceTransport):
30
+ """Base REST backend transport for GenerativeService.
31
+
32
+ Note: This class is not meant to be used directly. Use its sync and
33
+ async sub-classes instead.
34
+
35
+ This class defines the same methods as the primary client, so the
36
+ primary client can load the underlying transport implementation
37
+ and call it.
38
+
39
+ It sends JSON representations of protocol buffers over HTTP/1.1
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ *,
45
+ host: str = "generativelanguage.googleapis.com",
46
+ credentials: Optional[Any] = None,
47
+ client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO,
48
+ always_use_jwt_access: Optional[bool] = False,
49
+ url_scheme: str = "https",
50
+ api_audience: Optional[str] = None,
51
+ ) -> None:
52
+ """Instantiate the transport.
53
+ Args:
54
+ host (Optional[str]):
55
+ The hostname to connect to (default: 'generativelanguage.googleapis.com').
56
+ credentials (Optional[Any]): The
57
+ authorization credentials to attach to requests. These
58
+ credentials identify the application to the service; if none
59
+ are specified, the client will attempt to ascertain the
60
+ credentials from the environment.
61
+ client_info (google.api_core.gapic_v1.client_info.ClientInfo):
62
+ The client info used to send a user-agent string along with
63
+ API requests. If ``None``, then default info will be used.
64
+ Generally, you only need to set this if you are developing
65
+ your own client library.
66
+ always_use_jwt_access (Optional[bool]): Whether self signed JWT should
67
+ be used for service account credentials.
68
+ url_scheme: the protocol scheme for the API endpoint. Normally
69
+ "https", but for testing or local servers,
70
+ "http" can be specified.
71
+ """
72
+ # Run the base constructor
73
+ maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host)
74
+ if maybe_url_match is None:
75
+ raise ValueError(
76
+ f"Unexpected hostname structure: {host}"
77
+ ) # pragma: NO COVER
78
+
79
+ url_match_items = maybe_url_match.groupdict()
80
+
81
+ host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host
82
+
83
+ super().__init__(
84
+ host=host,
85
+ credentials=credentials,
86
+ client_info=client_info,
87
+ always_use_jwt_access=always_use_jwt_access,
88
+ api_audience=api_audience,
89
+ )
90
+
91
+ class _BaseBatchEmbedContents:
92
+ def __hash__(self): # pragma: NO COVER
93
+ return NotImplementedError("__hash__ must be implemented.")
94
+
95
+ __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
96
+
97
+ @classmethod
98
+ def _get_unset_required_fields(cls, message_dict):
99
+ return {
100
+ k: v
101
+ for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
102
+ if k not in message_dict
103
+ }
104
+
105
+ @staticmethod
106
+ def _get_http_options():
107
+ http_options: List[Dict[str, str]] = [
108
+ {
109
+ "method": "post",
110
+ "uri": "/v1/{model=models/*}:batchEmbedContents",
111
+ "body": "*",
112
+ },
113
+ ]
114
+ return http_options
115
+
116
+ @staticmethod
117
+ def _get_transcoded_request(http_options, request):
118
+ pb_request = generative_service.BatchEmbedContentsRequest.pb(request)
119
+ transcoded_request = path_template.transcode(http_options, pb_request)
120
+ return transcoded_request
121
+
122
+ @staticmethod
123
+ def _get_request_body_json(transcoded_request):
124
+ # Jsonify the request body
125
+
126
+ body = json_format.MessageToJson(
127
+ transcoded_request["body"], use_integers_for_enums=True
128
+ )
129
+ return body
130
+
131
+ @staticmethod
132
+ def _get_query_params_json(transcoded_request):
133
+ query_params = json.loads(
134
+ json_format.MessageToJson(
135
+ transcoded_request["query_params"],
136
+ use_integers_for_enums=True,
137
+ )
138
+ )
139
+ query_params.update(
140
+ _BaseGenerativeServiceRestTransport._BaseBatchEmbedContents._get_unset_required_fields(
141
+ query_params
142
+ )
143
+ )
144
+
145
+ query_params["$alt"] = "json;enum-encoding=int"
146
+ return query_params
147
+
148
+ class _BaseCountTokens:
149
+ def __hash__(self): # pragma: NO COVER
150
+ return NotImplementedError("__hash__ must be implemented.")
151
+
152
+ __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
153
+
154
+ @classmethod
155
+ def _get_unset_required_fields(cls, message_dict):
156
+ return {
157
+ k: v
158
+ for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
159
+ if k not in message_dict
160
+ }
161
+
162
+ @staticmethod
163
+ def _get_http_options():
164
+ http_options: List[Dict[str, str]] = [
165
+ {
166
+ "method": "post",
167
+ "uri": "/v1/{model=models/*}:countTokens",
168
+ "body": "*",
169
+ },
170
+ ]
171
+ return http_options
172
+
173
+ @staticmethod
174
+ def _get_transcoded_request(http_options, request):
175
+ pb_request = generative_service.CountTokensRequest.pb(request)
176
+ transcoded_request = path_template.transcode(http_options, pb_request)
177
+ return transcoded_request
178
+
179
+ @staticmethod
180
+ def _get_request_body_json(transcoded_request):
181
+ # Jsonify the request body
182
+
183
+ body = json_format.MessageToJson(
184
+ transcoded_request["body"], use_integers_for_enums=True
185
+ )
186
+ return body
187
+
188
+ @staticmethod
189
+ def _get_query_params_json(transcoded_request):
190
+ query_params = json.loads(
191
+ json_format.MessageToJson(
192
+ transcoded_request["query_params"],
193
+ use_integers_for_enums=True,
194
+ )
195
+ )
196
+ query_params.update(
197
+ _BaseGenerativeServiceRestTransport._BaseCountTokens._get_unset_required_fields(
198
+ query_params
199
+ )
200
+ )
201
+
202
+ query_params["$alt"] = "json;enum-encoding=int"
203
+ return query_params
204
+
205
+ class _BaseEmbedContent:
206
+ def __hash__(self): # pragma: NO COVER
207
+ return NotImplementedError("__hash__ must be implemented.")
208
+
209
+ __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
210
+
211
+ @classmethod
212
+ def _get_unset_required_fields(cls, message_dict):
213
+ return {
214
+ k: v
215
+ for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
216
+ if k not in message_dict
217
+ }
218
+
219
+ @staticmethod
220
+ def _get_http_options():
221
+ http_options: List[Dict[str, str]] = [
222
+ {
223
+ "method": "post",
224
+ "uri": "/v1/{model=models/*}:embedContent",
225
+ "body": "*",
226
+ },
227
+ ]
228
+ return http_options
229
+
230
+ @staticmethod
231
+ def _get_transcoded_request(http_options, request):
232
+ pb_request = generative_service.EmbedContentRequest.pb(request)
233
+ transcoded_request = path_template.transcode(http_options, pb_request)
234
+ return transcoded_request
235
+
236
+ @staticmethod
237
+ def _get_request_body_json(transcoded_request):
238
+ # Jsonify the request body
239
+
240
+ body = json_format.MessageToJson(
241
+ transcoded_request["body"], use_integers_for_enums=True
242
+ )
243
+ return body
244
+
245
+ @staticmethod
246
+ def _get_query_params_json(transcoded_request):
247
+ query_params = json.loads(
248
+ json_format.MessageToJson(
249
+ transcoded_request["query_params"],
250
+ use_integers_for_enums=True,
251
+ )
252
+ )
253
+ query_params.update(
254
+ _BaseGenerativeServiceRestTransport._BaseEmbedContent._get_unset_required_fields(
255
+ query_params
256
+ )
257
+ )
258
+
259
+ query_params["$alt"] = "json;enum-encoding=int"
260
+ return query_params
261
+
262
+ class _BaseGenerateContent:
263
+ def __hash__(self): # pragma: NO COVER
264
+ return NotImplementedError("__hash__ must be implemented.")
265
+
266
+ __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
267
+
268
+ @classmethod
269
+ def _get_unset_required_fields(cls, message_dict):
270
+ return {
271
+ k: v
272
+ for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
273
+ if k not in message_dict
274
+ }
275
+
276
+ @staticmethod
277
+ def _get_http_options():
278
+ http_options: List[Dict[str, str]] = [
279
+ {
280
+ "method": "post",
281
+ "uri": "/v1/{model=models/*}:generateContent",
282
+ "body": "*",
283
+ },
284
+ {
285
+ "method": "post",
286
+ "uri": "/v1/{model=tunedModels/*}:generateContent",
287
+ "body": "*",
288
+ },
289
+ ]
290
+ return http_options
291
+
292
+ @staticmethod
293
+ def _get_transcoded_request(http_options, request):
294
+ pb_request = generative_service.GenerateContentRequest.pb(request)
295
+ transcoded_request = path_template.transcode(http_options, pb_request)
296
+ return transcoded_request
297
+
298
+ @staticmethod
299
+ def _get_request_body_json(transcoded_request):
300
+ # Jsonify the request body
301
+
302
+ body = json_format.MessageToJson(
303
+ transcoded_request["body"], use_integers_for_enums=True
304
+ )
305
+ return body
306
+
307
+ @staticmethod
308
+ def _get_query_params_json(transcoded_request):
309
+ query_params = json.loads(
310
+ json_format.MessageToJson(
311
+ transcoded_request["query_params"],
312
+ use_integers_for_enums=True,
313
+ )
314
+ )
315
+ query_params.update(
316
+ _BaseGenerativeServiceRestTransport._BaseGenerateContent._get_unset_required_fields(
317
+ query_params
318
+ )
319
+ )
320
+
321
+ query_params["$alt"] = "json;enum-encoding=int"
322
+ return query_params
323
+
324
+ class _BaseStreamGenerateContent:
325
+ def __hash__(self): # pragma: NO COVER
326
+ return NotImplementedError("__hash__ must be implemented.")
327
+
328
+ __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {}
329
+
330
+ @classmethod
331
+ def _get_unset_required_fields(cls, message_dict):
332
+ return {
333
+ k: v
334
+ for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items()
335
+ if k not in message_dict
336
+ }
337
+
338
+ @staticmethod
339
+ def _get_http_options():
340
+ http_options: List[Dict[str, str]] = [
341
+ {
342
+ "method": "post",
343
+ "uri": "/v1/{model=models/*}:streamGenerateContent",
344
+ "body": "*",
345
+ },
346
+ {
347
+ "method": "post",
348
+ "uri": "/v1/{model=tunedModels/*}:streamGenerateContent",
349
+ "body": "*",
350
+ },
351
+ ]
352
+ return http_options
353
+
354
+ @staticmethod
355
+ def _get_transcoded_request(http_options, request):
356
+ pb_request = generative_service.GenerateContentRequest.pb(request)
357
+ transcoded_request = path_template.transcode(http_options, pb_request)
358
+ return transcoded_request
359
+
360
+ @staticmethod
361
+ def _get_request_body_json(transcoded_request):
362
+ # Jsonify the request body
363
+
364
+ body = json_format.MessageToJson(
365
+ transcoded_request["body"], use_integers_for_enums=True
366
+ )
367
+ return body
368
+
369
+ @staticmethod
370
+ def _get_query_params_json(transcoded_request):
371
+ query_params = json.loads(
372
+ json_format.MessageToJson(
373
+ transcoded_request["query_params"],
374
+ use_integers_for_enums=True,
375
+ )
376
+ )
377
+ query_params.update(
378
+ _BaseGenerativeServiceRestTransport._BaseStreamGenerateContent._get_unset_required_fields(
379
+ query_params
380
+ )
381
+ )
382
+
383
+ query_params["$alt"] = "json;enum-encoding=int"
384
+ return query_params
385
+
386
+ class _BaseCancelOperation:
387
+ def __hash__(self): # pragma: NO COVER
388
+ return NotImplementedError("__hash__ must be implemented.")
389
+
390
+ @staticmethod
391
+ def _get_http_options():
392
+ http_options: List[Dict[str, str]] = [
393
+ {
394
+ "method": "post",
395
+ "uri": "/v1/{name=tunedModels/*/operations/*}:cancel",
396
+ "body": "*",
397
+ },
398
+ ]
399
+ return http_options
400
+
401
+ @staticmethod
402
+ def _get_transcoded_request(http_options, request):
403
+ request_kwargs = json_format.MessageToDict(request)
404
+ transcoded_request = path_template.transcode(http_options, **request_kwargs)
405
+ return transcoded_request
406
+
407
+ @staticmethod
408
+ def _get_request_body_json(transcoded_request):
409
+ body = json.dumps(transcoded_request["body"])
410
+ return body
411
+
412
+ @staticmethod
413
+ def _get_query_params_json(transcoded_request):
414
+ query_params = json.loads(json.dumps(transcoded_request["query_params"]))
415
+ return query_params
416
+
417
+ class _BaseGetOperation:
418
+ def __hash__(self): # pragma: NO COVER
419
+ return NotImplementedError("__hash__ must be implemented.")
420
+
421
+ @staticmethod
422
+ def _get_http_options():
423
+ http_options: List[Dict[str, str]] = [
424
+ {
425
+ "method": "get",
426
+ "uri": "/v1/{name=tunedModels/*/operations/*}",
427
+ },
428
+ {
429
+ "method": "get",
430
+ "uri": "/v1/{name=generatedFiles/*/operations/*}",
431
+ },
432
+ {
433
+ "method": "get",
434
+ "uri": "/v1/{name=models/*/operations/*}",
435
+ },
436
+ ]
437
+ return http_options
438
+
439
+ @staticmethod
440
+ def _get_transcoded_request(http_options, request):
441
+ request_kwargs = json_format.MessageToDict(request)
442
+ transcoded_request = path_template.transcode(http_options, **request_kwargs)
443
+ return transcoded_request
444
+
445
+ @staticmethod
446
+ def _get_query_params_json(transcoded_request):
447
+ query_params = json.loads(json.dumps(transcoded_request["query_params"]))
448
+ return query_params
449
+
450
+ class _BaseListOperations:
451
+ def __hash__(self): # pragma: NO COVER
452
+ return NotImplementedError("__hash__ must be implemented.")
453
+
454
+ @staticmethod
455
+ def _get_http_options():
456
+ http_options: List[Dict[str, str]] = [
457
+ {
458
+ "method": "get",
459
+ "uri": "/v1/{name=operations}",
460
+ },
461
+ {
462
+ "method": "get",
463
+ "uri": "/v1/{name=tunedModels/*}/operations",
464
+ },
465
+ {
466
+ "method": "get",
467
+ "uri": "/v1/{name=models/*}/operations",
468
+ },
469
+ ]
470
+ return http_options
471
+
472
+ @staticmethod
473
+ def _get_transcoded_request(http_options, request):
474
+ request_kwargs = json_format.MessageToDict(request)
475
+ transcoded_request = path_template.transcode(http_options, **request_kwargs)
476
+ return transcoded_request
477
+
478
+ @staticmethod
479
+ def _get_query_params_json(transcoded_request):
480
+ query_params = json.loads(json.dumps(transcoded_request["query_params"]))
481
+ return query_params
482
+
483
+
484
+ __all__ = ("_BaseGenerativeServiceRestTransport",)
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (398 Bytes). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/async_client.cpython-311.pyc ADDED
Binary file (30 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/client.cpython-311.pyc ADDED
Binary file (46.2 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/services/model_service/__pycache__/pagers.cpython-311.pyc ADDED
Binary file (9.99 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (1.66 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/citation.cpython-311.pyc ADDED
Binary file (3.35 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/content.cpython-311.pyc ADDED
Binary file (4.77 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/__pycache__/model.cpython-311.pyc ADDED
Binary file (6.03 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1/types/model.py ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2024 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ from __future__ import annotations
17
+
18
+ from typing import MutableMapping, MutableSequence
19
+
20
+ import proto # type: ignore
21
+
22
+ __protobuf__ = proto.module(
23
+ package="google.ai.generativelanguage.v1",
24
+ manifest={
25
+ "Model",
26
+ },
27
+ )
28
+
29
+
30
+ class Model(proto.Message):
31
+ r"""Information about a Generative Language Model.
32
+
33
+ .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields
34
+
35
+ Attributes:
36
+ name (str):
37
+ Required. The resource name of the ``Model``. Refer to
38
+ `Model
39
+ variants <https://ai.google.dev/gemini-api/docs/models/gemini#model-variations>`__
40
+ for all allowed values.
41
+
42
+ Format: ``models/{model}`` with a ``{model}`` naming
43
+ convention of:
44
+
45
+ - "{base_model_id}-{version}"
46
+
47
+ Examples:
48
+
49
+ - ``models/gemini-1.5-flash-001``
50
+ base_model_id (str):
51
+ Required. The name of the base model, pass this to the
52
+ generation request.
53
+
54
+ Examples:
55
+
56
+ - ``gemini-1.5-flash``
57
+ version (str):
58
+ Required. The version number of the model.
59
+
60
+ This represents the major version (``1.0`` or ``1.5``)
61
+ display_name (str):
62
+ The human-readable name of the model. E.g.
63
+ "Gemini 1.5 Flash".
64
+ The name can be up to 128 characters long and
65
+ can consist of any UTF-8 characters.
66
+ description (str):
67
+ A short description of the model.
68
+ input_token_limit (int):
69
+ Maximum number of input tokens allowed for
70
+ this model.
71
+ output_token_limit (int):
72
+ Maximum number of output tokens available for
73
+ this model.
74
+ supported_generation_methods (MutableSequence[str]):
75
+ The model's supported generation methods.
76
+
77
+ The corresponding API method names are defined as Pascal
78
+ case strings, such as ``generateMessage`` and
79
+ ``generateContent``.
80
+ temperature (float):
81
+ Controls the randomness of the output.
82
+
83
+ Values can range over ``[0.0,max_temperature]``, inclusive.
84
+ A higher value will produce responses that are more varied,
85
+ while a value closer to ``0.0`` will typically result in
86
+ less surprising responses from the model. This value
87
+ specifies default to be used by the backend while making the
88
+ call to the model.
89
+
90
+ This field is a member of `oneof`_ ``_temperature``.
91
+ max_temperature (float):
92
+ The maximum temperature this model can use.
93
+
94
+ This field is a member of `oneof`_ ``_max_temperature``.
95
+ top_p (float):
96
+ For `Nucleus
97
+ sampling <https://ai.google.dev/gemini-api/docs/prompting-strategies#top-p>`__.
98
+
99
+ Nucleus sampling considers the smallest set of tokens whose
100
+ probability sum is at least ``top_p``. This value specifies
101
+ default to be used by the backend while making the call to
102
+ the model.
103
+
104
+ This field is a member of `oneof`_ ``_top_p``.
105
+ top_k (int):
106
+ For Top-k sampling.
107
+
108
+ Top-k sampling considers the set of ``top_k`` most probable
109
+ tokens. This value specifies default to be used by the
110
+ backend while making the call to the model. If empty,
111
+ indicates the model doesn't use top-k sampling, and
112
+ ``top_k`` isn't allowed as a generation parameter.
113
+
114
+ This field is a member of `oneof`_ ``_top_k``.
115
+ """
116
+
117
+ name: str = proto.Field(
118
+ proto.STRING,
119
+ number=1,
120
+ )
121
+ base_model_id: str = proto.Field(
122
+ proto.STRING,
123
+ number=2,
124
+ )
125
+ version: str = proto.Field(
126
+ proto.STRING,
127
+ number=3,
128
+ )
129
+ display_name: str = proto.Field(
130
+ proto.STRING,
131
+ number=4,
132
+ )
133
+ description: str = proto.Field(
134
+ proto.STRING,
135
+ number=5,
136
+ )
137
+ input_token_limit: int = proto.Field(
138
+ proto.INT32,
139
+ number=6,
140
+ )
141
+ output_token_limit: int = proto.Field(
142
+ proto.INT32,
143
+ number=7,
144
+ )
145
+ supported_generation_methods: MutableSequence[str] = proto.RepeatedField(
146
+ proto.STRING,
147
+ number=8,
148
+ )
149
+ temperature: float = proto.Field(
150
+ proto.FLOAT,
151
+ number=9,
152
+ optional=True,
153
+ )
154
+ max_temperature: float = proto.Field(
155
+ proto.FLOAT,
156
+ number=13,
157
+ optional=True,
158
+ )
159
+ top_p: float = proto.Field(
160
+ proto.FLOAT,
161
+ number=10,
162
+ optional=True,
163
+ )
164
+ top_k: int = proto.Field(
165
+ proto.INT32,
166
+ number=11,
167
+ optional=True,
168
+ )
169
+
170
+
171
+ __all__ = tuple(sorted(__protobuf__.manifest))
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (9.01 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/__pycache__/gapic_version.cpython-311.pyc ADDED
Binary file (236 Bytes). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (399 Bytes). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/__pycache__/client.cpython-311.pyc ADDED
Binary file (48.2 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/__pycache__/pagers.cpython-311.pyc ADDED
Binary file (9.99 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/file_service/transports/__pycache__/rest_base.cpython-311.pyc ADDED
Binary file (15.2 kB). View file
 
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/__pycache__/client.cpython-311.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:29614711e49318071f46e91c1f1773fefad2af82e4b546be9ffaa6f36454668c
3
+ size 111238
.venv/lib/python3.11/site-packages/google/ai/generativelanguage_v1beta/services/retriever_service/transports/__pycache__/rest.cpython-311.pyc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b70ca9b3cd7d3d317b4c8538e88bdc259487ef0abc5e814b393f99ebf2523d61
3
+ size 146070
.venv/lib/python3.11/site-packages/google/api_core/__init__.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2017 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Google API Core.
16
+
17
+ This package contains common code and utilities used by Google client libraries.
18
+ """
19
+
20
+ from google.api_core import version as api_core_version
21
+
22
+ __version__ = api_core_version.__version__
.venv/lib/python3.11/site-packages/google/api_core/__pycache__/bidi.cpython-311.pyc ADDED
Binary file (33.5 kB). View file
 
.venv/lib/python3.11/site-packages/google/api_core/__pycache__/client_options.cpython-311.pyc ADDED
Binary file (6.26 kB). View file
 
.venv/lib/python3.11/site-packages/google/api_core/__pycache__/operation.cpython-311.pyc ADDED
Binary file (15.1 kB). View file
 
.venv/lib/python3.11/site-packages/google/api_core/__pycache__/page_iterator.cpython-311.pyc ADDED
Binary file (22.6 kB). View file
 
.venv/lib/python3.11/site-packages/google/api_core/__pycache__/rest_helpers.cpython-311.pyc ADDED
Binary file (4.67 kB). View file
 
.venv/lib/python3.11/site-packages/google/api_core/__pycache__/retry_async.cpython-311.pyc ADDED
Binary file (710 Bytes). View file
 
.venv/lib/python3.11/site-packages/google/api_core/__pycache__/version.cpython-311.pyc ADDED
Binary file (210 Bytes). View file
 
.venv/lib/python3.11/site-packages/google/api_core/_rest_streaming_base.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Helpers for server-side streaming in REST."""
16
+
17
+ from collections import deque
18
+ import string
19
+ from typing import Deque, Union
20
+ import types
21
+
22
+ import proto
23
+ import google.protobuf.message
24
+ from google.protobuf.json_format import Parse
25
+
26
+
27
+ class BaseResponseIterator:
28
+ """Base Iterator over REST API responses. This class should not be used directly.
29
+
30
+ Args:
31
+ response_message_cls (Union[proto.Message, google.protobuf.message.Message]): A response
32
+ class expected to be returned from an API.
33
+
34
+ Raises:
35
+ ValueError: If `response_message_cls` is not a subclass of `proto.Message` or `google.protobuf.message.Message`.
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ response_message_cls: Union[proto.Message, google.protobuf.message.Message],
41
+ ):
42
+ self._response_message_cls = response_message_cls
43
+ # Contains a list of JSON responses ready to be sent to user.
44
+ self._ready_objs: Deque[str] = deque()
45
+ # Current JSON response being built.
46
+ self._obj = ""
47
+ # Keeps track of the nesting level within a JSON object.
48
+ self._level = 0
49
+ # Keeps track whether HTTP response is currently sending values
50
+ # inside of a string value.
51
+ self._in_string = False
52
+ # Whether an escape symbol "\" was encountered.
53
+ self._escape_next = False
54
+
55
+ self._grab = types.MethodType(self._create_grab(), self)
56
+
57
+ def _process_chunk(self, chunk: str):
58
+ if self._level == 0:
59
+ if chunk[0] != "[":
60
+ raise ValueError(
61
+ "Can only parse array of JSON objects, instead got %s" % chunk
62
+ )
63
+ for char in chunk:
64
+ if char == "{":
65
+ if self._level == 1:
66
+ # Level 1 corresponds to the outermost JSON object
67
+ # (i.e. the one we care about).
68
+ self._obj = ""
69
+ if not self._in_string:
70
+ self._level += 1
71
+ self._obj += char
72
+ elif char == "}":
73
+ self._obj += char
74
+ if not self._in_string:
75
+ self._level -= 1
76
+ if not self._in_string and self._level == 1:
77
+ self._ready_objs.append(self._obj)
78
+ elif char == '"':
79
+ # Helps to deal with an escaped quotes inside of a string.
80
+ if not self._escape_next:
81
+ self._in_string = not self._in_string
82
+ self._obj += char
83
+ elif char in string.whitespace:
84
+ if self._in_string:
85
+ self._obj += char
86
+ elif char == "[":
87
+ if self._level == 0:
88
+ self._level += 1
89
+ else:
90
+ self._obj += char
91
+ elif char == "]":
92
+ if self._level == 1:
93
+ self._level -= 1
94
+ else:
95
+ self._obj += char
96
+ else:
97
+ self._obj += char
98
+ self._escape_next = not self._escape_next if char == "\\" else False
99
+
100
+ def _create_grab(self):
101
+ if issubclass(self._response_message_cls, proto.Message):
102
+
103
+ def grab(this):
104
+ return this._response_message_cls.from_json(
105
+ this._ready_objs.popleft(), ignore_unknown_fields=True
106
+ )
107
+
108
+ return grab
109
+ elif issubclass(self._response_message_cls, google.protobuf.message.Message):
110
+
111
+ def grab(this):
112
+ return Parse(this._ready_objs.popleft(), this._response_message_cls())
113
+
114
+ return grab
115
+ else:
116
+ raise ValueError(
117
+ "Response message class must be a subclass of proto.Message or google.protobuf.message.Message."
118
+ )
.venv/lib/python3.11/site-packages/google/api_core/bidi.py ADDED
@@ -0,0 +1,743 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2017, Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Bi-directional streaming RPC helpers."""
16
+
17
+ import collections
18
+ import datetime
19
+ import logging
20
+ import queue as queue_module
21
+ import threading
22
+ import time
23
+
24
+ from google.api_core import exceptions
25
+
26
+ _LOGGER = logging.getLogger(__name__)
27
+ _BIDIRECTIONAL_CONSUMER_NAME = "Thread-ConsumeBidirectionalStream"
28
+
29
+
30
+ class _RequestQueueGenerator(object):
31
+ """A helper for sending requests to a gRPC stream from a Queue.
32
+
33
+ This generator takes requests off a given queue and yields them to gRPC.
34
+
35
+ This helper is useful when you have an indeterminate, indefinite, or
36
+ otherwise open-ended set of requests to send through a request-streaming
37
+ (or bidirectional) RPC.
38
+
39
+ The reason this is necessary is because gRPC takes an iterator as the
40
+ request for request-streaming RPCs. gRPC consumes this iterator in another
41
+ thread to allow it to block while generating requests for the stream.
42
+ However, if the generator blocks indefinitely gRPC will not be able to
43
+ clean up the thread as it'll be blocked on `next(iterator)` and not be able
44
+ to check the channel status to stop iterating. This helper mitigates that
45
+ by waiting on the queue with a timeout and checking the RPC state before
46
+ yielding.
47
+
48
+ Finally, it allows for retrying without swapping queues because if it does
49
+ pull an item off the queue when the RPC is inactive, it'll immediately put
50
+ it back and then exit. This is necessary because yielding the item in this
51
+ case will cause gRPC to discard it. In practice, this means that the order
52
+ of messages is not guaranteed. If such a thing is necessary it would be
53
+ easy to use a priority queue.
54
+
55
+ Example::
56
+
57
+ requests = request_queue_generator(q)
58
+ call = stub.StreamingRequest(iter(requests))
59
+ requests.call = call
60
+
61
+ for response in call:
62
+ print(response)
63
+ q.put(...)
64
+
65
+ Note that it is possible to accomplish this behavior without "spinning"
66
+ (using a queue timeout). One possible way would be to use more threads to
67
+ multiplex the grpc end event with the queue, another possible way is to
68
+ use selectors and a custom event/queue object. Both of these approaches
69
+ are significant from an engineering perspective for small benefit - the
70
+ CPU consumed by spinning is pretty minuscule.
71
+
72
+ Args:
73
+ queue (queue_module.Queue): The request queue.
74
+ period (float): The number of seconds to wait for items from the queue
75
+ before checking if the RPC is cancelled. In practice, this
76
+ determines the maximum amount of time the request consumption
77
+ thread will live after the RPC is cancelled.
78
+ initial_request (Union[protobuf.Message,
79
+ Callable[None, protobuf.Message]]): The initial request to
80
+ yield. This is done independently of the request queue to allow fo
81
+ easily restarting streams that require some initial configuration
82
+ request.
83
+ """
84
+
85
+ def __init__(self, queue, period=1, initial_request=None):
86
+ self._queue = queue
87
+ self._period = period
88
+ self._initial_request = initial_request
89
+ self.call = None
90
+
91
+ def _is_active(self):
92
+ # Note: there is a possibility that this starts *before* the call
93
+ # property is set. So we have to check if self.call is set before
94
+ # seeing if it's active. We need to return True if self.call is None.
95
+ # See https://github.com/googleapis/python-api-core/issues/560.
96
+ return self.call is None or self.call.is_active()
97
+
98
+ def __iter__(self):
99
+ if self._initial_request is not None:
100
+ if callable(self._initial_request):
101
+ yield self._initial_request()
102
+ else:
103
+ yield self._initial_request
104
+
105
+ while True:
106
+ try:
107
+ item = self._queue.get(timeout=self._period)
108
+ except queue_module.Empty:
109
+ if not self._is_active():
110
+ _LOGGER.debug(
111
+ "Empty queue and inactive call, exiting request " "generator."
112
+ )
113
+ return
114
+ else:
115
+ # call is still active, keep waiting for queue items.
116
+ continue
117
+
118
+ # The consumer explicitly sent "None", indicating that the request
119
+ # should end.
120
+ if item is None:
121
+ _LOGGER.debug("Cleanly exiting request generator.")
122
+ return
123
+
124
+ if not self._is_active():
125
+ # We have an item, but the call is closed. We should put the
126
+ # item back on the queue so that the next call can consume it.
127
+ self._queue.put(item)
128
+ _LOGGER.debug(
129
+ "Inactive call, replacing item on queue and exiting "
130
+ "request generator."
131
+ )
132
+ return
133
+
134
+ yield item
135
+
136
+
137
+ class _Throttle(object):
138
+ """A context manager limiting the total entries in a sliding time window.
139
+
140
+ If more than ``access_limit`` attempts are made to enter the context manager
141
+ instance in the last ``time window`` interval, the exceeding requests block
142
+ until enough time elapses.
143
+
144
+ The context manager instances are thread-safe and can be shared between
145
+ multiple threads. If multiple requests are blocked and waiting to enter,
146
+ the exact order in which they are allowed to proceed is not determined.
147
+
148
+ Example::
149
+
150
+ max_three_per_second = _Throttle(
151
+ access_limit=3, time_window=datetime.timedelta(seconds=1)
152
+ )
153
+
154
+ for i in range(5):
155
+ with max_three_per_second as time_waited:
156
+ print("{}: Waited {} seconds to enter".format(i, time_waited))
157
+
158
+ Args:
159
+ access_limit (int): the maximum number of entries allowed in the time window
160
+ time_window (datetime.timedelta): the width of the sliding time window
161
+ """
162
+
163
+ def __init__(self, access_limit, time_window):
164
+ if access_limit < 1:
165
+ raise ValueError("access_limit argument must be positive")
166
+
167
+ if time_window <= datetime.timedelta(0):
168
+ raise ValueError("time_window argument must be a positive timedelta")
169
+
170
+ self._time_window = time_window
171
+ self._access_limit = access_limit
172
+ self._past_entries = collections.deque(
173
+ maxlen=access_limit
174
+ ) # least recent first
175
+ self._entry_lock = threading.Lock()
176
+
177
+ def __enter__(self):
178
+ with self._entry_lock:
179
+ cutoff_time = datetime.datetime.now() - self._time_window
180
+
181
+ # drop the entries that are too old, as they are no longer relevant
182
+ while self._past_entries and self._past_entries[0] < cutoff_time:
183
+ self._past_entries.popleft()
184
+
185
+ if len(self._past_entries) < self._access_limit:
186
+ self._past_entries.append(datetime.datetime.now())
187
+ return 0.0 # no waiting was needed
188
+
189
+ to_wait = (self._past_entries[0] - cutoff_time).total_seconds()
190
+ time.sleep(to_wait)
191
+
192
+ self._past_entries.append(datetime.datetime.now())
193
+ return to_wait
194
+
195
+ def __exit__(self, *_):
196
+ pass
197
+
198
+ def __repr__(self):
199
+ return "{}(access_limit={}, time_window={})".format(
200
+ self.__class__.__name__, self._access_limit, repr(self._time_window)
201
+ )
202
+
203
+
204
+ class BidiRpc(object):
205
+ """A helper for consuming a bi-directional streaming RPC.
206
+
207
+ This maps gRPC's built-in interface which uses a request iterator and a
208
+ response iterator into a socket-like :func:`send` and :func:`recv`. This
209
+ is a more useful pattern for long-running or asymmetric streams (streams
210
+ where there is not a direct correlation between the requests and
211
+ responses).
212
+
213
+ Example::
214
+
215
+ initial_request = example_pb2.StreamingRpcRequest(
216
+ setting='example')
217
+ rpc = BidiRpc(
218
+ stub.StreamingRpc,
219
+ initial_request=initial_request,
220
+ metadata=[('name', 'value')]
221
+ )
222
+
223
+ rpc.open()
224
+
225
+ while rpc.is_active():
226
+ print(rpc.recv())
227
+ rpc.send(example_pb2.StreamingRpcRequest(
228
+ data='example'))
229
+
230
+ This does *not* retry the stream on errors. See :class:`ResumableBidiRpc`.
231
+
232
+ Args:
233
+ start_rpc (grpc.StreamStreamMultiCallable): The gRPC method used to
234
+ start the RPC.
235
+ initial_request (Union[protobuf.Message,
236
+ Callable[None, protobuf.Message]]): The initial request to
237
+ yield. This is useful if an initial request is needed to start the
238
+ stream.
239
+ metadata (Sequence[Tuple(str, str)]): RPC metadata to include in
240
+ the request.
241
+ """
242
+
243
+ def __init__(self, start_rpc, initial_request=None, metadata=None):
244
+ self._start_rpc = start_rpc
245
+ self._initial_request = initial_request
246
+ self._rpc_metadata = metadata
247
+ self._request_queue = queue_module.Queue()
248
+ self._request_generator = None
249
+ self._is_active = False
250
+ self._callbacks = []
251
+ self.call = None
252
+
253
+ def add_done_callback(self, callback):
254
+ """Adds a callback that will be called when the RPC terminates.
255
+
256
+ This occurs when the RPC errors or is successfully terminated.
257
+
258
+ Args:
259
+ callback (Callable[[grpc.Future], None]): The callback to execute.
260
+ It will be provided with the same gRPC future as the underlying
261
+ stream which will also be a :class:`grpc.Call`.
262
+ """
263
+ self._callbacks.append(callback)
264
+
265
+ def _on_call_done(self, future):
266
+ # This occurs when the RPC errors or is successfully terminated.
267
+ # Note that grpc's "future" here can also be a grpc.RpcError.
268
+ # See note in https://github.com/grpc/grpc/issues/10885#issuecomment-302651331
269
+ # that `grpc.RpcError` is also `grpc.call`.
270
+ for callback in self._callbacks:
271
+ callback(future)
272
+
273
+ def open(self):
274
+ """Opens the stream."""
275
+ if self.is_active:
276
+ raise ValueError("Can not open an already open stream.")
277
+
278
+ request_generator = _RequestQueueGenerator(
279
+ self._request_queue, initial_request=self._initial_request
280
+ )
281
+ try:
282
+ call = self._start_rpc(iter(request_generator), metadata=self._rpc_metadata)
283
+ except exceptions.GoogleAPICallError as exc:
284
+ # The original `grpc.RpcError` (which is usually also a `grpc.Call`) is
285
+ # available from the ``response`` property on the mapped exception.
286
+ self._on_call_done(exc.response)
287
+ raise
288
+
289
+ request_generator.call = call
290
+
291
+ # TODO: api_core should expose the future interface for wrapped
292
+ # callables as well.
293
+ if hasattr(call, "_wrapped"): # pragma: NO COVER
294
+ call._wrapped.add_done_callback(self._on_call_done)
295
+ else:
296
+ call.add_done_callback(self._on_call_done)
297
+
298
+ self._request_generator = request_generator
299
+ self.call = call
300
+
301
+ def close(self):
302
+ """Closes the stream."""
303
+ if self.call is None:
304
+ return
305
+
306
+ self._request_queue.put(None)
307
+ self.call.cancel()
308
+ self._request_generator = None
309
+ # Don't set self.call to None. Keep it around so that send/recv can
310
+ # raise the error.
311
+
312
+ def send(self, request):
313
+ """Queue a message to be sent on the stream.
314
+
315
+ Send is non-blocking.
316
+
317
+ If the underlying RPC has been closed, this will raise.
318
+
319
+ Args:
320
+ request (protobuf.Message): The request to send.
321
+ """
322
+ if self.call is None:
323
+ raise ValueError("Can not send() on an RPC that has never been open()ed.")
324
+
325
+ # Don't use self.is_active(), as ResumableBidiRpc will overload it
326
+ # to mean something semantically different.
327
+ if self.call.is_active():
328
+ self._request_queue.put(request)
329
+ else:
330
+ # calling next should cause the call to raise.
331
+ next(self.call)
332
+
333
+ def recv(self):
334
+ """Wait for a message to be returned from the stream.
335
+
336
+ Recv is blocking.
337
+
338
+ If the underlying RPC has been closed, this will raise.
339
+
340
+ Returns:
341
+ protobuf.Message: The received message.
342
+ """
343
+ if self.call is None:
344
+ raise ValueError("Can not recv() on an RPC that has never been open()ed.")
345
+
346
+ return next(self.call)
347
+
348
+ @property
349
+ def is_active(self):
350
+ """bool: True if this stream is currently open and active."""
351
+ return self.call is not None and self.call.is_active()
352
+
353
+ @property
354
+ def pending_requests(self):
355
+ """int: Returns an estimate of the number of queued requests."""
356
+ return self._request_queue.qsize()
357
+
358
+
359
+ def _never_terminate(future_or_error):
360
+ """By default, no errors cause BiDi termination."""
361
+ return False
362
+
363
+
364
+ class ResumableBidiRpc(BidiRpc):
365
+ """A :class:`BidiRpc` that can automatically resume the stream on errors.
366
+
367
+ It uses the ``should_recover`` arg to determine if it should re-establish
368
+ the stream on error.
369
+
370
+ Example::
371
+
372
+ def should_recover(exc):
373
+ return (
374
+ isinstance(exc, grpc.RpcError) and
375
+ exc.code() == grpc.StatusCode.UNAVAILABLE)
376
+
377
+ initial_request = example_pb2.StreamingRpcRequest(
378
+ setting='example')
379
+
380
+ metadata = [('header_name', 'value')]
381
+
382
+ rpc = ResumableBidiRpc(
383
+ stub.StreamingRpc,
384
+ should_recover=should_recover,
385
+ initial_request=initial_request,
386
+ metadata=metadata
387
+ )
388
+
389
+ rpc.open()
390
+
391
+ while rpc.is_active():
392
+ print(rpc.recv())
393
+ rpc.send(example_pb2.StreamingRpcRequest(
394
+ data='example'))
395
+
396
+ Args:
397
+ start_rpc (grpc.StreamStreamMultiCallable): The gRPC method used to
398
+ start the RPC.
399
+ initial_request (Union[protobuf.Message,
400
+ Callable[None, protobuf.Message]]): The initial request to
401
+ yield. This is useful if an initial request is needed to start the
402
+ stream.
403
+ should_recover (Callable[[Exception], bool]): A function that returns
404
+ True if the stream should be recovered. This will be called
405
+ whenever an error is encountered on the stream.
406
+ should_terminate (Callable[[Exception], bool]): A function that returns
407
+ True if the stream should be terminated. This will be called
408
+ whenever an error is encountered on the stream.
409
+ metadata Sequence[Tuple(str, str)]: RPC metadata to include in
410
+ the request.
411
+ throttle_reopen (bool): If ``True``, throttling will be applied to
412
+ stream reopen calls. Defaults to ``False``.
413
+ """
414
+
415
+ def __init__(
416
+ self,
417
+ start_rpc,
418
+ should_recover,
419
+ should_terminate=_never_terminate,
420
+ initial_request=None,
421
+ metadata=None,
422
+ throttle_reopen=False,
423
+ ):
424
+ super(ResumableBidiRpc, self).__init__(start_rpc, initial_request, metadata)
425
+ self._should_recover = should_recover
426
+ self._should_terminate = should_terminate
427
+ self._operational_lock = threading.RLock()
428
+ self._finalized = False
429
+ self._finalize_lock = threading.Lock()
430
+
431
+ if throttle_reopen:
432
+ self._reopen_throttle = _Throttle(
433
+ access_limit=5, time_window=datetime.timedelta(seconds=10)
434
+ )
435
+ else:
436
+ self._reopen_throttle = None
437
+
438
+ def _finalize(self, result):
439
+ with self._finalize_lock:
440
+ if self._finalized:
441
+ return
442
+
443
+ for callback in self._callbacks:
444
+ callback(result)
445
+
446
+ self._finalized = True
447
+
448
+ def _on_call_done(self, future):
449
+ # Unlike the base class, we only execute the callbacks on a terminal
450
+ # error, not for errors that we can recover from. Note that grpc's
451
+ # "future" here is also a grpc.RpcError.
452
+ with self._operational_lock:
453
+ if self._should_terminate(future):
454
+ self._finalize(future)
455
+ elif not self._should_recover(future):
456
+ self._finalize(future)
457
+ else:
458
+ _LOGGER.debug("Re-opening stream from gRPC callback.")
459
+ self._reopen()
460
+
461
+ def _reopen(self):
462
+ with self._operational_lock:
463
+ # Another thread already managed to re-open this stream.
464
+ if self.call is not None and self.call.is_active():
465
+ _LOGGER.debug("Stream was already re-established.")
466
+ return
467
+
468
+ self.call = None
469
+ # Request generator should exit cleanly since the RPC its bound to
470
+ # has exited.
471
+ self._request_generator = None
472
+
473
+ # Note: we do not currently do any sort of backoff here. The
474
+ # assumption is that re-establishing the stream under normal
475
+ # circumstances will happen in intervals greater than 60s.
476
+ # However, it is possible in a degenerative case that the server
477
+ # closes the stream rapidly which would lead to thrashing here,
478
+ # but hopefully in those cases the server would return a non-
479
+ # retryable error.
480
+
481
+ try:
482
+ if self._reopen_throttle:
483
+ with self._reopen_throttle:
484
+ self.open()
485
+ else:
486
+ self.open()
487
+ # If re-opening or re-calling the method fails for any reason,
488
+ # consider it a terminal error and finalize the stream.
489
+ except Exception as exc:
490
+ _LOGGER.debug("Failed to re-open stream due to %s", exc)
491
+ self._finalize(exc)
492
+ raise
493
+
494
+ _LOGGER.info("Re-established stream")
495
+
496
+ def _recoverable(self, method, *args, **kwargs):
497
+ """Wraps a method to recover the stream and retry on error.
498
+
499
+ If a retryable error occurs while making the call, then the stream will
500
+ be re-opened and the method will be retried. This happens indefinitely
501
+ so long as the error is a retryable one. If an error occurs while
502
+ re-opening the stream, then this method will raise immediately and
503
+ trigger finalization of this object.
504
+
505
+ Args:
506
+ method (Callable[..., Any]): The method to call.
507
+ args: The args to pass to the method.
508
+ kwargs: The kwargs to pass to the method.
509
+ """
510
+ while True:
511
+ try:
512
+ return method(*args, **kwargs)
513
+
514
+ except Exception as exc:
515
+ with self._operational_lock:
516
+ _LOGGER.debug("Call to retryable %r caused %s.", method, exc)
517
+
518
+ if self._should_terminate(exc):
519
+ self.close()
520
+ _LOGGER.debug("Terminating %r due to %s.", method, exc)
521
+ self._finalize(exc)
522
+ break
523
+
524
+ if not self._should_recover(exc):
525
+ self.close()
526
+ _LOGGER.debug("Not retrying %r due to %s.", method, exc)
527
+ self._finalize(exc)
528
+ raise exc
529
+
530
+ _LOGGER.debug("Re-opening stream from retryable %r.", method)
531
+ self._reopen()
532
+
533
+ def _send(self, request):
534
+ # Grab a reference to the RPC call. Because another thread (notably
535
+ # the gRPC error thread) can modify self.call (by invoking reopen),
536
+ # we should ensure our reference can not change underneath us.
537
+ # If self.call is modified (such as replaced with a new RPC call) then
538
+ # this will use the "old" RPC, which should result in the same
539
+ # exception passed into gRPC's error handler being raised here, which
540
+ # will be handled by the usual error handling in retryable.
541
+ with self._operational_lock:
542
+ call = self.call
543
+
544
+ if call is None:
545
+ raise ValueError("Can not send() on an RPC that has never been open()ed.")
546
+
547
+ # Don't use self.is_active(), as ResumableBidiRpc will overload it
548
+ # to mean something semantically different.
549
+ if call.is_active():
550
+ self._request_queue.put(request)
551
+ pass
552
+ else:
553
+ # calling next should cause the call to raise.
554
+ next(call)
555
+
556
+ def send(self, request):
557
+ return self._recoverable(self._send, request)
558
+
559
+ def _recv(self):
560
+ with self._operational_lock:
561
+ call = self.call
562
+
563
+ if call is None:
564
+ raise ValueError("Can not recv() on an RPC that has never been open()ed.")
565
+
566
+ return next(call)
567
+
568
+ def recv(self):
569
+ return self._recoverable(self._recv)
570
+
571
+ def close(self):
572
+ self._finalize(None)
573
+ super(ResumableBidiRpc, self).close()
574
+
575
+ @property
576
+ def is_active(self):
577
+ """bool: True if this stream is currently open and active."""
578
+ # Use the operational lock. It's entirely possible for something
579
+ # to check the active state *while* the RPC is being retried.
580
+ # Also, use finalized to track the actual terminal state here.
581
+ # This is because if the stream is re-established by the gRPC thread
582
+ # it's technically possible to check this between when gRPC marks the
583
+ # RPC as inactive and when gRPC executes our callback that re-opens
584
+ # the stream.
585
+ with self._operational_lock:
586
+ return self.call is not None and not self._finalized
587
+
588
+
589
+ class BackgroundConsumer(object):
590
+ """A bi-directional stream consumer that runs in a separate thread.
591
+
592
+ This maps the consumption of a stream into a callback-based model. It also
593
+ provides :func:`pause` and :func:`resume` to allow for flow-control.
594
+
595
+ Example::
596
+
597
+ def should_recover(exc):
598
+ return (
599
+ isinstance(exc, grpc.RpcError) and
600
+ exc.code() == grpc.StatusCode.UNAVAILABLE)
601
+
602
+ initial_request = example_pb2.StreamingRpcRequest(
603
+ setting='example')
604
+
605
+ rpc = ResumeableBidiRpc(
606
+ stub.StreamingRpc,
607
+ initial_request=initial_request,
608
+ should_recover=should_recover)
609
+
610
+ def on_response(response):
611
+ print(response)
612
+
613
+ consumer = BackgroundConsumer(rpc, on_response)
614
+ consumer.start()
615
+
616
+ Note that error handling *must* be done by using the provided
617
+ ``bidi_rpc``'s ``add_done_callback``. This helper will automatically exit
618
+ whenever the RPC itself exits and will not provide any error details.
619
+
620
+ Args:
621
+ bidi_rpc (BidiRpc): The RPC to consume. Should not have been
622
+ ``open()``ed yet.
623
+ on_response (Callable[[protobuf.Message], None]): The callback to
624
+ be called for every response on the stream.
625
+ """
626
+
627
+ def __init__(self, bidi_rpc, on_response):
628
+ self._bidi_rpc = bidi_rpc
629
+ self._on_response = on_response
630
+ self._paused = False
631
+ self._wake = threading.Condition()
632
+ self._thread = None
633
+ self._operational_lock = threading.Lock()
634
+
635
+ def _on_call_done(self, future):
636
+ # Resume the thread if it's paused, this prevents blocking forever
637
+ # when the RPC has terminated.
638
+ self.resume()
639
+
640
+ def _thread_main(self, ready):
641
+ try:
642
+ ready.set()
643
+ self._bidi_rpc.add_done_callback(self._on_call_done)
644
+ self._bidi_rpc.open()
645
+
646
+ while self._bidi_rpc.is_active:
647
+ # Do not allow the paused status to change at all during this
648
+ # section. There is a condition where we could be resumed
649
+ # between checking if we are paused and calling wake.wait(),
650
+ # which means that we will miss the notification to wake up
651
+ # (oops!) and wait for a notification that will never come.
652
+ # Keeping the lock throughout avoids that.
653
+ # In the future, we could use `Condition.wait_for` if we drop
654
+ # Python 2.7.
655
+ # See: https://github.com/googleapis/python-api-core/issues/211
656
+ with self._wake:
657
+ while self._paused:
658
+ _LOGGER.debug("paused, waiting for waking.")
659
+ self._wake.wait()
660
+ _LOGGER.debug("woken.")
661
+
662
+ _LOGGER.debug("waiting for recv.")
663
+ response = self._bidi_rpc.recv()
664
+ _LOGGER.debug("recved response.")
665
+ self._on_response(response)
666
+
667
+ except exceptions.GoogleAPICallError as exc:
668
+ _LOGGER.debug(
669
+ "%s caught error %s and will exit. Generally this is due to "
670
+ "the RPC itself being cancelled and the error will be "
671
+ "surfaced to the calling code.",
672
+ _BIDIRECTIONAL_CONSUMER_NAME,
673
+ exc,
674
+ exc_info=True,
675
+ )
676
+
677
+ except Exception as exc:
678
+ _LOGGER.exception(
679
+ "%s caught unexpected exception %s and will exit.",
680
+ _BIDIRECTIONAL_CONSUMER_NAME,
681
+ exc,
682
+ )
683
+
684
+ _LOGGER.info("%s exiting", _BIDIRECTIONAL_CONSUMER_NAME)
685
+
686
+ def start(self):
687
+ """Start the background thread and begin consuming the thread."""
688
+ with self._operational_lock:
689
+ ready = threading.Event()
690
+ thread = threading.Thread(
691
+ name=_BIDIRECTIONAL_CONSUMER_NAME,
692
+ target=self._thread_main,
693
+ args=(ready,),
694
+ )
695
+ thread.daemon = True
696
+ thread.start()
697
+ # Other parts of the code rely on `thread.is_alive` which
698
+ # isn't sufficient to know if a thread is active, just that it may
699
+ # soon be active. This can cause races. Further protect
700
+ # against races by using a ready event and wait on it to be set.
701
+ ready.wait()
702
+ self._thread = thread
703
+ _LOGGER.debug("Started helper thread %s", thread.name)
704
+
705
+ def stop(self):
706
+ """Stop consuming the stream and shutdown the background thread."""
707
+ with self._operational_lock:
708
+ self._bidi_rpc.close()
709
+
710
+ if self._thread is not None:
711
+ # Resume the thread to wake it up in case it is sleeping.
712
+ self.resume()
713
+ # The daemonized thread may itself block, so don't wait
714
+ # for it longer than a second.
715
+ self._thread.join(1.0)
716
+ if self._thread.is_alive(): # pragma: NO COVER
717
+ _LOGGER.warning("Background thread did not exit.")
718
+
719
+ self._thread = None
720
+
721
+ @property
722
+ def is_active(self):
723
+ """bool: True if the background thread is active."""
724
+ return self._thread is not None and self._thread.is_alive()
725
+
726
+ def pause(self):
727
+ """Pauses the response stream.
728
+
729
+ This does *not* pause the request stream.
730
+ """
731
+ with self._wake:
732
+ self._paused = True
733
+
734
+ def resume(self):
735
+ """Resumes the response stream."""
736
+ with self._wake:
737
+ self._paused = False
738
+ self._wake.notify_all()
739
+
740
+ @property
741
+ def is_paused(self):
742
+ """bool: True if the response stream is paused."""
743
+ return self._paused
.venv/lib/python3.11/site-packages/google/api_core/client_info.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2017 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Helpers for providing client information.
16
+
17
+ Client information is used to send information about the calling client,
18
+ such as the library and Python version, to API services.
19
+ """
20
+
21
+ import platform
22
+ from typing import Union
23
+
24
+ from google.api_core import version as api_core_version
25
+
26
+ _PY_VERSION = platform.python_version()
27
+ _API_CORE_VERSION = api_core_version.__version__
28
+
29
+ _GRPC_VERSION: Union[str, None]
30
+
31
+ try:
32
+ import grpc
33
+
34
+ _GRPC_VERSION = grpc.__version__
35
+ except ImportError: # pragma: NO COVER
36
+ _GRPC_VERSION = None
37
+
38
+
39
+ class ClientInfo(object):
40
+ """Client information used to generate a user-agent for API calls.
41
+
42
+ This user-agent information is sent along with API calls to allow the
43
+ receiving service to do analytics on which versions of Python and Google
44
+ libraries are being used.
45
+
46
+ Args:
47
+ python_version (str): The Python interpreter version, for example,
48
+ ``'3.9.6'``.
49
+ grpc_version (Optional[str]): The gRPC library version.
50
+ api_core_version (str): The google-api-core library version.
51
+ gapic_version (Optional[str]): The version of gapic-generated client
52
+ library, if the library was generated by gapic.
53
+ client_library_version (Optional[str]): The version of the client
54
+ library, generally used if the client library was not generated
55
+ by gapic or if additional functionality was built on top of
56
+ a gapic client library.
57
+ user_agent (Optional[str]): Prefix to the user agent header. This is
58
+ used to supply information such as application name or partner tool.
59
+ Recommended format: ``application-or-tool-ID/major.minor.version``.
60
+ rest_version (Optional[str]): A string with labeled versions of the
61
+ dependencies used for REST transport.
62
+ """
63
+
64
+ def __init__(
65
+ self,
66
+ python_version=_PY_VERSION,
67
+ grpc_version=_GRPC_VERSION,
68
+ api_core_version=_API_CORE_VERSION,
69
+ gapic_version=None,
70
+ client_library_version=None,
71
+ user_agent=None,
72
+ rest_version=None,
73
+ ):
74
+ self.python_version = python_version
75
+ self.grpc_version = grpc_version
76
+ self.api_core_version = api_core_version
77
+ self.gapic_version = gapic_version
78
+ self.client_library_version = client_library_version
79
+ self.user_agent = user_agent
80
+ self.rest_version = rest_version
81
+
82
+ def to_user_agent(self):
83
+ """Returns the user-agent string for this client info."""
84
+
85
+ # Note: the order here is important as the internal metrics system
86
+ # expects these items to be in specific locations.
87
+ ua = ""
88
+
89
+ if self.user_agent is not None:
90
+ ua += "{user_agent} "
91
+
92
+ ua += "gl-python/{python_version} "
93
+
94
+ if self.grpc_version is not None:
95
+ ua += "grpc/{grpc_version} "
96
+
97
+ if self.rest_version is not None:
98
+ ua += "rest/{rest_version} "
99
+
100
+ ua += "gax/{api_core_version} "
101
+
102
+ if self.gapic_version is not None:
103
+ ua += "gapic/{gapic_version} "
104
+
105
+ if self.client_library_version is not None:
106
+ ua += "gccl/{client_library_version} "
107
+
108
+ return ua.format(**self.__dict__).strip()
.venv/lib/python3.11/site-packages/google/api_core/client_logging.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import json
3
+ import os
4
+
5
+ from typing import List, Optional
6
+
7
+ _LOGGING_INITIALIZED = False
8
+ _BASE_LOGGER_NAME = "google"
9
+
10
+ # Fields to be included in the StructuredLogFormatter.
11
+ #
12
+ # TODO(https://github.com/googleapis/python-api-core/issues/761): Update this list to support additional logging fields.
13
+ _recognized_logging_fields = [
14
+ "httpRequest",
15
+ "rpcName",
16
+ "serviceName",
17
+ "credentialsType",
18
+ "credentialsInfo",
19
+ "universeDomain",
20
+ "request",
21
+ "response",
22
+ "metadata",
23
+ "retryAttempt",
24
+ "httpResponse",
25
+ ] # Additional fields to be Logged.
26
+
27
+
28
+ def logger_configured(logger) -> bool:
29
+ """Determines whether `logger` has non-default configuration
30
+
31
+ Args:
32
+ logger: The logger to check.
33
+
34
+ Returns:
35
+ bool: Whether the logger has any non-default configuration.
36
+ """
37
+ return (
38
+ logger.handlers != [] or logger.level != logging.NOTSET or not logger.propagate
39
+ )
40
+
41
+
42
+ def initialize_logging():
43
+ """Initializes "google" loggers, partly based on the environment variable
44
+
45
+ Initializes the "google" logger and any loggers (at the "google"
46
+ level or lower) specified by the environment variable
47
+ GOOGLE_SDK_PYTHON_LOGGING_SCOPE, as long as none of these loggers
48
+ were previously configured. If any such loggers (including the
49
+ "google" logger) are initialized, they are set to NOT propagate
50
+ log events up to their parent loggers.
51
+
52
+ This initialization is executed only once, and hence the
53
+ environment variable is only processed the first time this
54
+ function is called.
55
+ """
56
+ global _LOGGING_INITIALIZED
57
+ if _LOGGING_INITIALIZED:
58
+ return
59
+ scopes = os.getenv("GOOGLE_SDK_PYTHON_LOGGING_SCOPE", "")
60
+ setup_logging(scopes)
61
+ _LOGGING_INITIALIZED = True
62
+
63
+
64
+ def parse_logging_scopes(scopes: Optional[str] = None) -> List[str]:
65
+ """Returns a list of logger names.
66
+
67
+ Splits the single string of comma-separated logger names into a list of individual logger name strings.
68
+
69
+ Args:
70
+ scopes: The name of a single logger. (In the future, this will be a comma-separated list of multiple loggers.)
71
+
72
+ Returns:
73
+ A list of all the logger names in scopes.
74
+ """
75
+ if not scopes:
76
+ return []
77
+ # TODO(https://github.com/googleapis/python-api-core/issues/759): check if the namespace is a valid namespace.
78
+ # TODO(b/380481951): Support logging multiple scopes.
79
+ # TODO(b/380483756): Raise or log a warning for an invalid scope.
80
+ namespaces = [scopes]
81
+ return namespaces
82
+
83
+
84
+ def configure_defaults(logger):
85
+ """Configures `logger` to emit structured info to stdout."""
86
+ if not logger_configured(logger):
87
+ console_handler = logging.StreamHandler()
88
+ logger.setLevel("DEBUG")
89
+ logger.propagate = False
90
+ formatter = StructuredLogFormatter()
91
+ console_handler.setFormatter(formatter)
92
+ logger.addHandler(console_handler)
93
+
94
+
95
+ def setup_logging(scopes: str = ""):
96
+ """Sets up logging for the specified `scopes`.
97
+
98
+ If the loggers specified in `scopes` have not been previously
99
+ configured, this will configure them to emit structured log
100
+ entries to stdout, and to not propagate their log events to their
101
+ parent loggers. Additionally, if the "google" logger (whether it
102
+ was specified in `scopes` or not) was not previously configured,
103
+ it will also configure it to not propagate log events to the root
104
+ logger.
105
+
106
+ Args:
107
+ scopes: The name of a single logger. (In the future, this will be a comma-separated list of multiple loggers.)
108
+
109
+ """
110
+
111
+ # only returns valid logger scopes (namespaces)
112
+ # this list has at most one element.
113
+ logger_names = parse_logging_scopes(scopes)
114
+
115
+ for namespace in logger_names:
116
+ # This will either create a module level logger or get the reference of the base logger instantiated above.
117
+ logger = logging.getLogger(namespace)
118
+
119
+ # Configure default settings.
120
+ configure_defaults(logger)
121
+
122
+ # disable log propagation at base logger level to the root logger only if a base logger is not already configured via code changes.
123
+ base_logger = logging.getLogger(_BASE_LOGGER_NAME)
124
+ if not logger_configured(base_logger):
125
+ base_logger.propagate = False
126
+
127
+
128
+ # TODO(https://github.com/googleapis/python-api-core/issues/763): Expand documentation.
129
+ class StructuredLogFormatter(logging.Formatter):
130
+ # TODO(https://github.com/googleapis/python-api-core/issues/761): ensure that additional fields such as
131
+ # function name, file name, and line no. appear in a log output.
132
+ def format(self, record: logging.LogRecord):
133
+ log_obj = {
134
+ "timestamp": self.formatTime(record),
135
+ "severity": record.levelname,
136
+ "name": record.name,
137
+ "message": record.getMessage(),
138
+ }
139
+
140
+ for field_name in _recognized_logging_fields:
141
+ value = getattr(record, field_name, None)
142
+ if value is not None:
143
+ log_obj[field_name] = value
144
+ return json.dumps(log_obj)
.venv/lib/python3.11/site-packages/google/api_core/client_options.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Client options class.
16
+
17
+ Client options provide a consistent interface for user options to be defined
18
+ across clients.
19
+
20
+ You can pass a client options object to a client.
21
+
22
+ .. code-block:: python
23
+
24
+ from google.api_core.client_options import ClientOptions
25
+ from google.cloud.vision_v1 import ImageAnnotatorClient
26
+
27
+ def get_client_cert():
28
+ # code to load client certificate and private key.
29
+ return client_cert_bytes, client_private_key_bytes
30
+
31
+ options = ClientOptions(api_endpoint="foo.googleapis.com",
32
+ client_cert_source=get_client_cert)
33
+
34
+ client = ImageAnnotatorClient(client_options=options)
35
+
36
+ You can also pass a mapping object.
37
+
38
+ .. code-block:: python
39
+
40
+ from google.cloud.vision_v1 import ImageAnnotatorClient
41
+
42
+ client = ImageAnnotatorClient(
43
+ client_options={
44
+ "api_endpoint": "foo.googleapis.com",
45
+ "client_cert_source" : get_client_cert
46
+ })
47
+
48
+
49
+ """
50
+
51
+ from typing import Callable, Mapping, Optional, Sequence, Tuple
52
+
53
+
54
+ class ClientOptions(object):
55
+ """Client Options used to set options on clients.
56
+
57
+ Args:
58
+ api_endpoint (Optional[str]): The desired API endpoint, e.g.,
59
+ compute.googleapis.com
60
+ client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): A callback
61
+ which returns client certificate bytes and private key bytes both in
62
+ PEM format. ``client_cert_source`` and ``client_encrypted_cert_source``
63
+ are mutually exclusive.
64
+ client_encrypted_cert_source (Optional[Callable[[], Tuple[str, str, bytes]]]):
65
+ A callback which returns client certificate file path, encrypted
66
+ private key file path, and the passphrase bytes.``client_cert_source``
67
+ and ``client_encrypted_cert_source`` are mutually exclusive.
68
+ quota_project_id (Optional[str]): A project name that a client's
69
+ quota belongs to.
70
+ credentials_file (Optional[str]): A path to a file storing credentials.
71
+ ``credentials_file` and ``api_key`` are mutually exclusive.
72
+ scopes (Optional[Sequence[str]]): OAuth access token override scopes.
73
+ api_key (Optional[str]): Google API key. ``credentials_file`` and
74
+ ``api_key`` are mutually exclusive.
75
+ api_audience (Optional[str]): The intended audience for the API calls
76
+ to the service that will be set when using certain 3rd party
77
+ authentication flows. Audience is typically a resource identifier.
78
+ If not set, the service endpoint value will be used as a default.
79
+ An example of a valid ``api_audience`` is: "https://language.googleapis.com".
80
+ universe_domain (Optional[str]): The desired universe domain. This must match
81
+ the one in credentials. If not set, the default universe domain is
82
+ `googleapis.com`. If both `api_endpoint` and `universe_domain` are set,
83
+ then `api_endpoint` is used as the service endpoint. If `api_endpoint` is
84
+ not specified, the format will be `{service}.{universe_domain}`.
85
+
86
+ Raises:
87
+ ValueError: If both ``client_cert_source`` and ``client_encrypted_cert_source``
88
+ are provided, or both ``credentials_file`` and ``api_key`` are provided.
89
+ """
90
+
91
+ def __init__(
92
+ self,
93
+ api_endpoint: Optional[str] = None,
94
+ client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None,
95
+ client_encrypted_cert_source: Optional[
96
+ Callable[[], Tuple[str, str, bytes]]
97
+ ] = None,
98
+ quota_project_id: Optional[str] = None,
99
+ credentials_file: Optional[str] = None,
100
+ scopes: Optional[Sequence[str]] = None,
101
+ api_key: Optional[str] = None,
102
+ api_audience: Optional[str] = None,
103
+ universe_domain: Optional[str] = None,
104
+ ):
105
+ if client_cert_source and client_encrypted_cert_source:
106
+ raise ValueError(
107
+ "client_cert_source and client_encrypted_cert_source are mutually exclusive"
108
+ )
109
+ if api_key and credentials_file:
110
+ raise ValueError("api_key and credentials_file are mutually exclusive")
111
+ self.api_endpoint = api_endpoint
112
+ self.client_cert_source = client_cert_source
113
+ self.client_encrypted_cert_source = client_encrypted_cert_source
114
+ self.quota_project_id = quota_project_id
115
+ self.credentials_file = credentials_file
116
+ self.scopes = scopes
117
+ self.api_key = api_key
118
+ self.api_audience = api_audience
119
+ self.universe_domain = universe_domain
120
+
121
+ def __repr__(self) -> str:
122
+ return "ClientOptions: " + repr(self.__dict__)
123
+
124
+
125
+ def from_dict(options: Mapping[str, object]) -> ClientOptions:
126
+ """Construct a client options object from a mapping object.
127
+
128
+ Args:
129
+ options (collections.abc.Mapping): A mapping object with client options.
130
+ See the docstring for ClientOptions for details on valid arguments.
131
+ """
132
+
133
+ client_options = ClientOptions()
134
+
135
+ for key, value in options.items():
136
+ if hasattr(client_options, key):
137
+ setattr(client_options, key, value)
138
+ else:
139
+ raise ValueError("ClientOptions does not accept an option '" + key + "'")
140
+
141
+ return client_options
.venv/lib/python3.11/site-packages/google/api_core/datetime_helpers.py ADDED
@@ -0,0 +1,298 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2017 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Helpers for :mod:`datetime`."""
16
+
17
+ import calendar
18
+ import datetime
19
+ import re
20
+
21
+ from google.protobuf import timestamp_pb2
22
+
23
+
24
+ _UTC_EPOCH = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)
25
+ _RFC3339_MICROS = "%Y-%m-%dT%H:%M:%S.%fZ"
26
+ _RFC3339_NO_FRACTION = "%Y-%m-%dT%H:%M:%S"
27
+ # datetime.strptime cannot handle nanosecond precision: parse w/ regex
28
+ _RFC3339_NANOS = re.compile(
29
+ r"""
30
+ (?P<no_fraction>
31
+ \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} # YYYY-MM-DDTHH:MM:SS
32
+ )
33
+ ( # Optional decimal part
34
+ \. # decimal point
35
+ (?P<nanos>\d{1,9}) # nanoseconds, maybe truncated
36
+ )?
37
+ Z # Zulu
38
+ """,
39
+ re.VERBOSE,
40
+ )
41
+
42
+
43
+ def utcnow():
44
+ """A :meth:`datetime.datetime.utcnow()` alias to allow mocking in tests."""
45
+ return datetime.datetime.now(tz=datetime.timezone.utc).replace(tzinfo=None)
46
+
47
+
48
+ def to_milliseconds(value):
49
+ """Convert a zone-aware datetime to milliseconds since the unix epoch.
50
+
51
+ Args:
52
+ value (datetime.datetime): The datetime to covert.
53
+
54
+ Returns:
55
+ int: Milliseconds since the unix epoch.
56
+ """
57
+ micros = to_microseconds(value)
58
+ return micros // 1000
59
+
60
+
61
+ def from_microseconds(value):
62
+ """Convert timestamp in microseconds since the unix epoch to datetime.
63
+
64
+ Args:
65
+ value (float): The timestamp to convert, in microseconds.
66
+
67
+ Returns:
68
+ datetime.datetime: The datetime object equivalent to the timestamp in
69
+ UTC.
70
+ """
71
+ return _UTC_EPOCH + datetime.timedelta(microseconds=value)
72
+
73
+
74
+ def to_microseconds(value):
75
+ """Convert a datetime to microseconds since the unix epoch.
76
+
77
+ Args:
78
+ value (datetime.datetime): The datetime to covert.
79
+
80
+ Returns:
81
+ int: Microseconds since the unix epoch.
82
+ """
83
+ if not value.tzinfo:
84
+ value = value.replace(tzinfo=datetime.timezone.utc)
85
+ # Regardless of what timezone is on the value, convert it to UTC.
86
+ value = value.astimezone(datetime.timezone.utc)
87
+ # Convert the datetime to a microsecond timestamp.
88
+ return int(calendar.timegm(value.timetuple()) * 1e6) + value.microsecond
89
+
90
+
91
+ def from_iso8601_date(value):
92
+ """Convert a ISO8601 date string to a date.
93
+
94
+ Args:
95
+ value (str): The ISO8601 date string.
96
+
97
+ Returns:
98
+ datetime.date: A date equivalent to the date string.
99
+ """
100
+ return datetime.datetime.strptime(value, "%Y-%m-%d").date()
101
+
102
+
103
+ def from_iso8601_time(value):
104
+ """Convert a zoneless ISO8601 time string to a time.
105
+
106
+ Args:
107
+ value (str): The ISO8601 time string.
108
+
109
+ Returns:
110
+ datetime.time: A time equivalent to the time string.
111
+ """
112
+ return datetime.datetime.strptime(value, "%H:%M:%S").time()
113
+
114
+
115
+ def from_rfc3339(value):
116
+ """Convert an RFC3339-format timestamp to a native datetime.
117
+
118
+ Supported formats include those without fractional seconds, or with
119
+ any fraction up to nanosecond precision.
120
+
121
+ .. note::
122
+ Python datetimes do not support nanosecond precision; this function
123
+ therefore truncates such values to microseconds.
124
+
125
+ Args:
126
+ value (str): The RFC3339 string to convert.
127
+
128
+ Returns:
129
+ datetime.datetime: The datetime object equivalent to the timestamp
130
+ in UTC.
131
+
132
+ Raises:
133
+ ValueError: If the timestamp does not match the RFC3339
134
+ regular expression.
135
+ """
136
+ with_nanos = _RFC3339_NANOS.match(value)
137
+
138
+ if with_nanos is None:
139
+ raise ValueError(
140
+ "Timestamp: {!r}, does not match pattern: {!r}".format(
141
+ value, _RFC3339_NANOS.pattern
142
+ )
143
+ )
144
+
145
+ bare_seconds = datetime.datetime.strptime(
146
+ with_nanos.group("no_fraction"), _RFC3339_NO_FRACTION
147
+ )
148
+ fraction = with_nanos.group("nanos")
149
+
150
+ if fraction is None:
151
+ micros = 0
152
+ else:
153
+ scale = 9 - len(fraction)
154
+ nanos = int(fraction) * (10**scale)
155
+ micros = nanos // 1000
156
+
157
+ return bare_seconds.replace(microsecond=micros, tzinfo=datetime.timezone.utc)
158
+
159
+
160
+ from_rfc3339_nanos = from_rfc3339 # from_rfc3339_nanos method was deprecated.
161
+
162
+
163
+ def to_rfc3339(value, ignore_zone=True):
164
+ """Convert a datetime to an RFC3339 timestamp string.
165
+
166
+ Args:
167
+ value (datetime.datetime):
168
+ The datetime object to be converted to a string.
169
+ ignore_zone (bool): If True, then the timezone (if any) of the
170
+ datetime object is ignored and the datetime is treated as UTC.
171
+
172
+ Returns:
173
+ str: The RFC3339 formatted string representing the datetime.
174
+ """
175
+ if not ignore_zone and value.tzinfo is not None:
176
+ # Convert to UTC and remove the time zone info.
177
+ value = value.replace(tzinfo=None) - value.utcoffset()
178
+
179
+ return value.strftime(_RFC3339_MICROS)
180
+
181
+
182
+ class DatetimeWithNanoseconds(datetime.datetime):
183
+ """Track nanosecond in addition to normal datetime attrs.
184
+
185
+ Nanosecond can be passed only as a keyword argument.
186
+ """
187
+
188
+ __slots__ = ("_nanosecond",)
189
+
190
+ # pylint: disable=arguments-differ
191
+ def __new__(cls, *args, **kw):
192
+ nanos = kw.pop("nanosecond", 0)
193
+ if nanos > 0:
194
+ if "microsecond" in kw:
195
+ raise TypeError("Specify only one of 'microsecond' or 'nanosecond'")
196
+ kw["microsecond"] = nanos // 1000
197
+ inst = datetime.datetime.__new__(cls, *args, **kw)
198
+ inst._nanosecond = nanos or 0
199
+ return inst
200
+
201
+ # pylint: disable=arguments-differ
202
+
203
+ @property
204
+ def nanosecond(self):
205
+ """Read-only: nanosecond precision."""
206
+ return self._nanosecond
207
+
208
+ def rfc3339(self):
209
+ """Return an RFC3339-compliant timestamp.
210
+
211
+ Returns:
212
+ (str): Timestamp string according to RFC3339 spec.
213
+ """
214
+ if self._nanosecond == 0:
215
+ return to_rfc3339(self)
216
+ nanos = str(self._nanosecond).rjust(9, "0").rstrip("0")
217
+ return "{}.{}Z".format(self.strftime(_RFC3339_NO_FRACTION), nanos)
218
+
219
+ @classmethod
220
+ def from_rfc3339(cls, stamp):
221
+ """Parse RFC3339-compliant timestamp, preserving nanoseconds.
222
+
223
+ Args:
224
+ stamp (str): RFC3339 stamp, with up to nanosecond precision
225
+
226
+ Returns:
227
+ :class:`DatetimeWithNanoseconds`:
228
+ an instance matching the timestamp string
229
+
230
+ Raises:
231
+ ValueError: if `stamp` does not match the expected format
232
+ """
233
+ with_nanos = _RFC3339_NANOS.match(stamp)
234
+ if with_nanos is None:
235
+ raise ValueError(
236
+ "Timestamp: {}, does not match pattern: {}".format(
237
+ stamp, _RFC3339_NANOS.pattern
238
+ )
239
+ )
240
+ bare = datetime.datetime.strptime(
241
+ with_nanos.group("no_fraction"), _RFC3339_NO_FRACTION
242
+ )
243
+ fraction = with_nanos.group("nanos")
244
+ if fraction is None:
245
+ nanos = 0
246
+ else:
247
+ scale = 9 - len(fraction)
248
+ nanos = int(fraction) * (10**scale)
249
+ return cls(
250
+ bare.year,
251
+ bare.month,
252
+ bare.day,
253
+ bare.hour,
254
+ bare.minute,
255
+ bare.second,
256
+ nanosecond=nanos,
257
+ tzinfo=datetime.timezone.utc,
258
+ )
259
+
260
+ def timestamp_pb(self):
261
+ """Return a timestamp message.
262
+
263
+ Returns:
264
+ (:class:`~google.protobuf.timestamp_pb2.Timestamp`): Timestamp message
265
+ """
266
+ inst = (
267
+ self
268
+ if self.tzinfo is not None
269
+ else self.replace(tzinfo=datetime.timezone.utc)
270
+ )
271
+ delta = inst - _UTC_EPOCH
272
+ seconds = int(delta.total_seconds())
273
+ nanos = self._nanosecond or self.microsecond * 1000
274
+ return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
275
+
276
+ @classmethod
277
+ def from_timestamp_pb(cls, stamp):
278
+ """Parse RFC3339-compliant timestamp, preserving nanoseconds.
279
+
280
+ Args:
281
+ stamp (:class:`~google.protobuf.timestamp_pb2.Timestamp`): timestamp message
282
+
283
+ Returns:
284
+ :class:`DatetimeWithNanoseconds`:
285
+ an instance matching the timestamp message
286
+ """
287
+ microseconds = int(stamp.seconds * 1e6)
288
+ bare = from_microseconds(microseconds)
289
+ return cls(
290
+ bare.year,
291
+ bare.month,
292
+ bare.day,
293
+ bare.hour,
294
+ bare.minute,
295
+ bare.second,
296
+ nanosecond=stamp.nanos,
297
+ tzinfo=datetime.timezone.utc,
298
+ )
.venv/lib/python3.11/site-packages/google/api_core/exceptions.py ADDED
@@ -0,0 +1,670 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2014 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Exceptions raised by Google API core & clients.
16
+
17
+ This module provides base classes for all errors raised by libraries based
18
+ on :mod:`google.api_core`, including both HTTP and gRPC clients.
19
+ """
20
+
21
+ from __future__ import absolute_import
22
+ from __future__ import unicode_literals
23
+
24
+ import http.client
25
+ from typing import Optional, Dict
26
+ from typing import Union
27
+ import warnings
28
+
29
+ from google.rpc import error_details_pb2
30
+
31
+
32
+ def _warn_could_not_import_grpcio_status():
33
+ warnings.warn(
34
+ "Please install grpcio-status to obtain helpful grpc error messages.",
35
+ ImportWarning,
36
+ ) # pragma: NO COVER
37
+
38
+
39
+ try:
40
+ import grpc
41
+
42
+ try:
43
+ from grpc_status import rpc_status
44
+ except ImportError: # pragma: NO COVER
45
+ _warn_could_not_import_grpcio_status()
46
+ rpc_status = None
47
+ except ImportError: # pragma: NO COVER
48
+ grpc = None
49
+
50
+ # Lookup tables for mapping exceptions from HTTP and gRPC transports.
51
+ # Populated by _GoogleAPICallErrorMeta
52
+ _HTTP_CODE_TO_EXCEPTION: Dict[int, Exception] = {}
53
+ _GRPC_CODE_TO_EXCEPTION: Dict[int, Exception] = {}
54
+
55
+ # Additional lookup table to map integer status codes to grpc status code
56
+ # grpc does not currently support initializing enums from ints
57
+ # i.e., grpc.StatusCode(5) raises an error
58
+ _INT_TO_GRPC_CODE = {}
59
+ if grpc is not None: # pragma: no branch
60
+ for x in grpc.StatusCode:
61
+ _INT_TO_GRPC_CODE[x.value[0]] = x
62
+
63
+
64
+ class GoogleAPIError(Exception):
65
+ """Base class for all exceptions raised by Google API Clients."""
66
+
67
+ pass
68
+
69
+
70
+ class DuplicateCredentialArgs(GoogleAPIError):
71
+ """Raised when multiple credentials are passed."""
72
+
73
+ pass
74
+
75
+
76
+ class RetryError(GoogleAPIError):
77
+ """Raised when a function has exhausted all of its available retries.
78
+
79
+ Args:
80
+ message (str): The exception message.
81
+ cause (Exception): The last exception raised when retrying the
82
+ function.
83
+ """
84
+
85
+ def __init__(self, message, cause):
86
+ super(RetryError, self).__init__(message)
87
+ self.message = message
88
+ self._cause = cause
89
+
90
+ @property
91
+ def cause(self):
92
+ """The last exception raised when retrying the function."""
93
+ return self._cause
94
+
95
+ def __str__(self):
96
+ return "{}, last exception: {}".format(self.message, self.cause)
97
+
98
+
99
+ class _GoogleAPICallErrorMeta(type):
100
+ """Metaclass for registering GoogleAPICallError subclasses."""
101
+
102
+ def __new__(mcs, name, bases, class_dict):
103
+ cls = type.__new__(mcs, name, bases, class_dict)
104
+ if cls.code is not None:
105
+ _HTTP_CODE_TO_EXCEPTION.setdefault(cls.code, cls)
106
+ if cls.grpc_status_code is not None:
107
+ _GRPC_CODE_TO_EXCEPTION.setdefault(cls.grpc_status_code, cls)
108
+ return cls
109
+
110
+
111
+ class GoogleAPICallError(GoogleAPIError, metaclass=_GoogleAPICallErrorMeta):
112
+ """Base class for exceptions raised by calling API methods.
113
+
114
+ Args:
115
+ message (str): The exception message.
116
+ errors (Sequence[Any]): An optional list of error details.
117
+ details (Sequence[Any]): An optional list of objects defined in google.rpc.error_details.
118
+ response (Union[requests.Request, grpc.Call]): The response or
119
+ gRPC call metadata.
120
+ error_info (Union[error_details_pb2.ErrorInfo, None]): An optional object containing error info
121
+ (google.rpc.error_details.ErrorInfo).
122
+ """
123
+
124
+ code: Union[int, None] = None
125
+ """Optional[int]: The HTTP status code associated with this error.
126
+
127
+ This may be ``None`` if the exception does not have a direct mapping
128
+ to an HTTP error.
129
+
130
+ See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
131
+ """
132
+
133
+ grpc_status_code = None
134
+ """Optional[grpc.StatusCode]: The gRPC status code associated with this
135
+ error.
136
+
137
+ This may be ``None`` if the exception does not match up to a gRPC error.
138
+ """
139
+
140
+ def __init__(self, message, errors=(), details=(), response=None, error_info=None):
141
+ super(GoogleAPICallError, self).__init__(message)
142
+ self.message = message
143
+ """str: The exception message."""
144
+ self._errors = errors
145
+ self._details = details
146
+ self._response = response
147
+ self._error_info = error_info
148
+
149
+ def __str__(self):
150
+ error_msg = "{} {}".format(self.code, self.message)
151
+ if self.details:
152
+ error_msg = "{} {}".format(error_msg, self.details)
153
+ # Note: This else condition can be removed once proposal A from
154
+ # b/284179390 is implemented.
155
+ else:
156
+ if self.errors:
157
+ errors = [
158
+ f"{error.code}: {error.message}"
159
+ for error in self.errors
160
+ if hasattr(error, "code") and hasattr(error, "message")
161
+ ]
162
+ if errors:
163
+ error_msg = "{} {}".format(error_msg, "\n".join(errors))
164
+ return error_msg
165
+
166
+ @property
167
+ def reason(self):
168
+ """The reason of the error.
169
+
170
+ Reference:
171
+ https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112
172
+
173
+ Returns:
174
+ Union[str, None]: An optional string containing reason of the error.
175
+ """
176
+ return self._error_info.reason if self._error_info else None
177
+
178
+ @property
179
+ def domain(self):
180
+ """The logical grouping to which the "reason" belongs.
181
+
182
+ Reference:
183
+ https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112
184
+
185
+ Returns:
186
+ Union[str, None]: An optional string containing a logical grouping to which the "reason" belongs.
187
+ """
188
+ return self._error_info.domain if self._error_info else None
189
+
190
+ @property
191
+ def metadata(self):
192
+ """Additional structured details about this error.
193
+
194
+ Reference:
195
+ https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L112
196
+
197
+ Returns:
198
+ Union[Dict[str, str], None]: An optional object containing structured details about the error.
199
+ """
200
+ return self._error_info.metadata if self._error_info else None
201
+
202
+ @property
203
+ def errors(self):
204
+ """Detailed error information.
205
+
206
+ Returns:
207
+ Sequence[Any]: A list of additional error details.
208
+ """
209
+ return list(self._errors)
210
+
211
+ @property
212
+ def details(self):
213
+ """Information contained in google.rpc.status.details.
214
+
215
+ Reference:
216
+ https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto
217
+ https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto
218
+
219
+ Returns:
220
+ Sequence[Any]: A list of structured objects from error_details.proto
221
+ """
222
+ return list(self._details)
223
+
224
+ @property
225
+ def response(self):
226
+ """Optional[Union[requests.Request, grpc.Call]]: The response or
227
+ gRPC call metadata."""
228
+ return self._response
229
+
230
+
231
+ class Redirection(GoogleAPICallError):
232
+ """Base class for for all redirection (HTTP 3xx) responses."""
233
+
234
+
235
+ class MovedPermanently(Redirection):
236
+ """Exception mapping a ``301 Moved Permanently`` response."""
237
+
238
+ code = http.client.MOVED_PERMANENTLY
239
+
240
+
241
+ class NotModified(Redirection):
242
+ """Exception mapping a ``304 Not Modified`` response."""
243
+
244
+ code = http.client.NOT_MODIFIED
245
+
246
+
247
+ class TemporaryRedirect(Redirection):
248
+ """Exception mapping a ``307 Temporary Redirect`` response."""
249
+
250
+ code = http.client.TEMPORARY_REDIRECT
251
+
252
+
253
+ class ResumeIncomplete(Redirection):
254
+ """Exception mapping a ``308 Resume Incomplete`` response.
255
+
256
+ .. note:: :attr:`http.client.PERMANENT_REDIRECT` is ``308``, but Google
257
+ APIs differ in their use of this status code.
258
+ """
259
+
260
+ code = 308
261
+
262
+
263
+ class ClientError(GoogleAPICallError):
264
+ """Base class for all client error (HTTP 4xx) responses."""
265
+
266
+
267
+ class BadRequest(ClientError):
268
+ """Exception mapping a ``400 Bad Request`` response."""
269
+
270
+ code = http.client.BAD_REQUEST
271
+
272
+
273
+ class InvalidArgument(BadRequest):
274
+ """Exception mapping a :attr:`grpc.StatusCode.INVALID_ARGUMENT` error."""
275
+
276
+ grpc_status_code = grpc.StatusCode.INVALID_ARGUMENT if grpc is not None else None
277
+
278
+
279
+ class FailedPrecondition(BadRequest):
280
+ """Exception mapping a :attr:`grpc.StatusCode.FAILED_PRECONDITION`
281
+ error."""
282
+
283
+ grpc_status_code = grpc.StatusCode.FAILED_PRECONDITION if grpc is not None else None
284
+
285
+
286
+ class OutOfRange(BadRequest):
287
+ """Exception mapping a :attr:`grpc.StatusCode.OUT_OF_RANGE` error."""
288
+
289
+ grpc_status_code = grpc.StatusCode.OUT_OF_RANGE if grpc is not None else None
290
+
291
+
292
+ class Unauthorized(ClientError):
293
+ """Exception mapping a ``401 Unauthorized`` response."""
294
+
295
+ code = http.client.UNAUTHORIZED
296
+
297
+
298
+ class Unauthenticated(Unauthorized):
299
+ """Exception mapping a :attr:`grpc.StatusCode.UNAUTHENTICATED` error."""
300
+
301
+ grpc_status_code = grpc.StatusCode.UNAUTHENTICATED if grpc is not None else None
302
+
303
+
304
+ class Forbidden(ClientError):
305
+ """Exception mapping a ``403 Forbidden`` response."""
306
+
307
+ code = http.client.FORBIDDEN
308
+
309
+
310
+ class PermissionDenied(Forbidden):
311
+ """Exception mapping a :attr:`grpc.StatusCode.PERMISSION_DENIED` error."""
312
+
313
+ grpc_status_code = grpc.StatusCode.PERMISSION_DENIED if grpc is not None else None
314
+
315
+
316
+ class NotFound(ClientError):
317
+ """Exception mapping a ``404 Not Found`` response or a
318
+ :attr:`grpc.StatusCode.NOT_FOUND` error."""
319
+
320
+ code = http.client.NOT_FOUND
321
+ grpc_status_code = grpc.StatusCode.NOT_FOUND if grpc is not None else None
322
+
323
+
324
+ class MethodNotAllowed(ClientError):
325
+ """Exception mapping a ``405 Method Not Allowed`` response."""
326
+
327
+ code = http.client.METHOD_NOT_ALLOWED
328
+
329
+
330
+ class Conflict(ClientError):
331
+ """Exception mapping a ``409 Conflict`` response."""
332
+
333
+ code = http.client.CONFLICT
334
+
335
+
336
+ class AlreadyExists(Conflict):
337
+ """Exception mapping a :attr:`grpc.StatusCode.ALREADY_EXISTS` error."""
338
+
339
+ grpc_status_code = grpc.StatusCode.ALREADY_EXISTS if grpc is not None else None
340
+
341
+
342
+ class Aborted(Conflict):
343
+ """Exception mapping a :attr:`grpc.StatusCode.ABORTED` error."""
344
+
345
+ grpc_status_code = grpc.StatusCode.ABORTED if grpc is not None else None
346
+
347
+
348
+ class LengthRequired(ClientError):
349
+ """Exception mapping a ``411 Length Required`` response."""
350
+
351
+ code = http.client.LENGTH_REQUIRED
352
+
353
+
354
+ class PreconditionFailed(ClientError):
355
+ """Exception mapping a ``412 Precondition Failed`` response."""
356
+
357
+ code = http.client.PRECONDITION_FAILED
358
+
359
+
360
+ class RequestRangeNotSatisfiable(ClientError):
361
+ """Exception mapping a ``416 Request Range Not Satisfiable`` response."""
362
+
363
+ code = http.client.REQUESTED_RANGE_NOT_SATISFIABLE
364
+
365
+
366
+ class TooManyRequests(ClientError):
367
+ """Exception mapping a ``429 Too Many Requests`` response."""
368
+
369
+ code = http.client.TOO_MANY_REQUESTS
370
+
371
+
372
+ class ResourceExhausted(TooManyRequests):
373
+ """Exception mapping a :attr:`grpc.StatusCode.RESOURCE_EXHAUSTED` error."""
374
+
375
+ grpc_status_code = grpc.StatusCode.RESOURCE_EXHAUSTED if grpc is not None else None
376
+
377
+
378
+ class Cancelled(ClientError):
379
+ """Exception mapping a :attr:`grpc.StatusCode.CANCELLED` error."""
380
+
381
+ # This maps to HTTP status code 499. See
382
+ # https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
383
+ code = 499
384
+ grpc_status_code = grpc.StatusCode.CANCELLED if grpc is not None else None
385
+
386
+
387
+ class ServerError(GoogleAPICallError):
388
+ """Base for 5xx responses."""
389
+
390
+
391
+ class InternalServerError(ServerError):
392
+ """Exception mapping a ``500 Internal Server Error`` response. or a
393
+ :attr:`grpc.StatusCode.INTERNAL` error."""
394
+
395
+ code = http.client.INTERNAL_SERVER_ERROR
396
+ grpc_status_code = grpc.StatusCode.INTERNAL if grpc is not None else None
397
+
398
+
399
+ class Unknown(ServerError):
400
+ """Exception mapping a :attr:`grpc.StatusCode.UNKNOWN` error."""
401
+
402
+ grpc_status_code = grpc.StatusCode.UNKNOWN if grpc is not None else None
403
+
404
+
405
+ class DataLoss(ServerError):
406
+ """Exception mapping a :attr:`grpc.StatusCode.DATA_LOSS` error."""
407
+
408
+ grpc_status_code = grpc.StatusCode.DATA_LOSS if grpc is not None else None
409
+
410
+
411
+ class MethodNotImplemented(ServerError):
412
+ """Exception mapping a ``501 Not Implemented`` response or a
413
+ :attr:`grpc.StatusCode.UNIMPLEMENTED` error."""
414
+
415
+ code = http.client.NOT_IMPLEMENTED
416
+ grpc_status_code = grpc.StatusCode.UNIMPLEMENTED if grpc is not None else None
417
+
418
+
419
+ class BadGateway(ServerError):
420
+ """Exception mapping a ``502 Bad Gateway`` response."""
421
+
422
+ code = http.client.BAD_GATEWAY
423
+
424
+
425
+ class ServiceUnavailable(ServerError):
426
+ """Exception mapping a ``503 Service Unavailable`` response or a
427
+ :attr:`grpc.StatusCode.UNAVAILABLE` error."""
428
+
429
+ code = http.client.SERVICE_UNAVAILABLE
430
+ grpc_status_code = grpc.StatusCode.UNAVAILABLE if grpc is not None else None
431
+
432
+
433
+ class GatewayTimeout(ServerError):
434
+ """Exception mapping a ``504 Gateway Timeout`` response."""
435
+
436
+ code = http.client.GATEWAY_TIMEOUT
437
+
438
+
439
+ class DeadlineExceeded(GatewayTimeout):
440
+ """Exception mapping a :attr:`grpc.StatusCode.DEADLINE_EXCEEDED` error."""
441
+
442
+ grpc_status_code = grpc.StatusCode.DEADLINE_EXCEEDED if grpc is not None else None
443
+
444
+
445
+ class AsyncRestUnsupportedParameterError(NotImplementedError):
446
+ """Raised when an unsupported parameter is configured against async rest transport."""
447
+
448
+ pass
449
+
450
+
451
+ def exception_class_for_http_status(status_code):
452
+ """Return the exception class for a specific HTTP status code.
453
+
454
+ Args:
455
+ status_code (int): The HTTP status code.
456
+
457
+ Returns:
458
+ :func:`type`: the appropriate subclass of :class:`GoogleAPICallError`.
459
+ """
460
+ return _HTTP_CODE_TO_EXCEPTION.get(status_code, GoogleAPICallError)
461
+
462
+
463
+ def from_http_status(status_code, message, **kwargs):
464
+ """Create a :class:`GoogleAPICallError` from an HTTP status code.
465
+
466
+ Args:
467
+ status_code (int): The HTTP status code.
468
+ message (str): The exception message.
469
+ kwargs: Additional arguments passed to the :class:`GoogleAPICallError`
470
+ constructor.
471
+
472
+ Returns:
473
+ GoogleAPICallError: An instance of the appropriate subclass of
474
+ :class:`GoogleAPICallError`.
475
+ """
476
+ error_class = exception_class_for_http_status(status_code)
477
+ error = error_class(message, **kwargs)
478
+
479
+ if error.code is None:
480
+ error.code = status_code
481
+
482
+ return error
483
+
484
+
485
+ def _format_rest_error_message(error, method, url):
486
+ method = method.upper() if method else None
487
+ message = "{method} {url}: {error}".format(
488
+ method=method,
489
+ url=url,
490
+ error=error,
491
+ )
492
+ return message
493
+
494
+
495
+ # NOTE: We're moving away from `from_http_status` because it expects an aiohttp response compared
496
+ # to `format_http_response_error` which expects a more abstract response from google.auth and is
497
+ # compatible with both sync and async response types.
498
+ # TODO(https://github.com/googleapis/python-api-core/issues/691): Add type hint for response.
499
+ def format_http_response_error(
500
+ response, method: str, url: str, payload: Optional[Dict] = None
501
+ ):
502
+ """Create a :class:`GoogleAPICallError` from a google auth rest response.
503
+
504
+ Args:
505
+ response Union[google.auth.transport.Response, google.auth.aio.transport.Response]: The HTTP response.
506
+ method Optional(str): The HTTP request method.
507
+ url Optional(str): The HTTP request url.
508
+ payload Optional(dict): The HTTP response payload. If not passed in, it is read from response for a response type of google.auth.transport.Response.
509
+
510
+ Returns:
511
+ GoogleAPICallError: An instance of the appropriate subclass of
512
+ :class:`GoogleAPICallError`, with the message and errors populated
513
+ from the response.
514
+ """
515
+ payload = {} if not payload else payload
516
+ error_message = payload.get("error", {}).get("message", "unknown error")
517
+ errors = payload.get("error", {}).get("errors", ())
518
+ # In JSON, details are already formatted in developer-friendly way.
519
+ details = payload.get("error", {}).get("details", ())
520
+ error_info = list(
521
+ filter(
522
+ lambda detail: detail.get("@type", "")
523
+ == "type.googleapis.com/google.rpc.ErrorInfo",
524
+ details,
525
+ )
526
+ )
527
+ error_info = error_info[0] if error_info else None
528
+ message = _format_rest_error_message(error_message, method, url)
529
+
530
+ exception = from_http_status(
531
+ response.status_code,
532
+ message,
533
+ errors=errors,
534
+ details=details,
535
+ response=response,
536
+ error_info=error_info,
537
+ )
538
+ return exception
539
+
540
+
541
+ def from_http_response(response):
542
+ """Create a :class:`GoogleAPICallError` from a :class:`requests.Response`.
543
+
544
+ Args:
545
+ response (requests.Response): The HTTP response.
546
+
547
+ Returns:
548
+ GoogleAPICallError: An instance of the appropriate subclass of
549
+ :class:`GoogleAPICallError`, with the message and errors populated
550
+ from the response.
551
+ """
552
+ try:
553
+ payload = response.json()
554
+ except ValueError:
555
+ payload = {"error": {"message": response.text or "unknown error"}}
556
+ return format_http_response_error(
557
+ response, response.request.method, response.request.url, payload
558
+ )
559
+
560
+
561
+ def exception_class_for_grpc_status(status_code):
562
+ """Return the exception class for a specific :class:`grpc.StatusCode`.
563
+
564
+ Args:
565
+ status_code (grpc.StatusCode): The gRPC status code.
566
+
567
+ Returns:
568
+ :func:`type`: the appropriate subclass of :class:`GoogleAPICallError`.
569
+ """
570
+ return _GRPC_CODE_TO_EXCEPTION.get(status_code, GoogleAPICallError)
571
+
572
+
573
+ def from_grpc_status(status_code, message, **kwargs):
574
+ """Create a :class:`GoogleAPICallError` from a :class:`grpc.StatusCode`.
575
+
576
+ Args:
577
+ status_code (Union[grpc.StatusCode, int]): The gRPC status code.
578
+ message (str): The exception message.
579
+ kwargs: Additional arguments passed to the :class:`GoogleAPICallError`
580
+ constructor.
581
+
582
+ Returns:
583
+ GoogleAPICallError: An instance of the appropriate subclass of
584
+ :class:`GoogleAPICallError`.
585
+ """
586
+
587
+ if isinstance(status_code, int):
588
+ status_code = _INT_TO_GRPC_CODE.get(status_code, status_code)
589
+
590
+ error_class = exception_class_for_grpc_status(status_code)
591
+ error = error_class(message, **kwargs)
592
+
593
+ if error.grpc_status_code is None:
594
+ error.grpc_status_code = status_code
595
+
596
+ return error
597
+
598
+
599
+ def _is_informative_grpc_error(rpc_exc):
600
+ return hasattr(rpc_exc, "code") and hasattr(rpc_exc, "details")
601
+
602
+
603
+ def _parse_grpc_error_details(rpc_exc):
604
+ if not rpc_status: # pragma: NO COVER
605
+ _warn_could_not_import_grpcio_status()
606
+ return [], None
607
+ try:
608
+ status = rpc_status.from_call(rpc_exc)
609
+ except NotImplementedError: # workaround
610
+ return [], None
611
+
612
+ if not status:
613
+ return [], None
614
+
615
+ possible_errors = [
616
+ error_details_pb2.BadRequest,
617
+ error_details_pb2.PreconditionFailure,
618
+ error_details_pb2.QuotaFailure,
619
+ error_details_pb2.ErrorInfo,
620
+ error_details_pb2.RetryInfo,
621
+ error_details_pb2.ResourceInfo,
622
+ error_details_pb2.RequestInfo,
623
+ error_details_pb2.DebugInfo,
624
+ error_details_pb2.Help,
625
+ error_details_pb2.LocalizedMessage,
626
+ ]
627
+ error_info = None
628
+ error_details = []
629
+ for detail in status.details:
630
+ matched_detail_cls = list(
631
+ filter(lambda x: detail.Is(x.DESCRIPTOR), possible_errors)
632
+ )
633
+ # If nothing matched, use detail directly.
634
+ if len(matched_detail_cls) == 0:
635
+ info = detail
636
+ else:
637
+ info = matched_detail_cls[0]()
638
+ detail.Unpack(info)
639
+ error_details.append(info)
640
+ if isinstance(info, error_details_pb2.ErrorInfo):
641
+ error_info = info
642
+ return error_details, error_info
643
+
644
+
645
+ def from_grpc_error(rpc_exc):
646
+ """Create a :class:`GoogleAPICallError` from a :class:`grpc.RpcError`.
647
+
648
+ Args:
649
+ rpc_exc (grpc.RpcError): The gRPC error.
650
+
651
+ Returns:
652
+ GoogleAPICallError: An instance of the appropriate subclass of
653
+ :class:`GoogleAPICallError`.
654
+ """
655
+ # NOTE(lidiz) All gRPC error shares the parent class grpc.RpcError.
656
+ # However, check for grpc.RpcError breaks backward compatibility.
657
+ if (
658
+ grpc is not None and isinstance(rpc_exc, grpc.Call)
659
+ ) or _is_informative_grpc_error(rpc_exc):
660
+ details, err_info = _parse_grpc_error_details(rpc_exc)
661
+ return from_grpc_status(
662
+ rpc_exc.code(),
663
+ rpc_exc.details(),
664
+ errors=(rpc_exc,),
665
+ details=details,
666
+ response=rpc_exc,
667
+ error_info=err_info,
668
+ )
669
+ else:
670
+ return GoogleAPICallError(str(rpc_exc), errors=(rpc_exc,), response=rpc_exc)
.venv/lib/python3.11/site-packages/google/api_core/extended_operation.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2022 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Futures for extended long-running operations returned from Google Cloud APIs.
16
+
17
+ These futures can be used to synchronously wait for the result of a
18
+ long-running operations using :meth:`ExtendedOperation.result`:
19
+
20
+ .. code-block:: python
21
+
22
+ extended_operation = my_api_client.long_running_method()
23
+
24
+ extended_operation.result()
25
+
26
+ Or asynchronously using callbacks and :meth:`Operation.add_done_callback`:
27
+
28
+ .. code-block:: python
29
+
30
+ extended_operation = my_api_client.long_running_method()
31
+
32
+ def my_callback(ex_op):
33
+ print(f"Operation {ex_op.name} completed")
34
+
35
+ extended_operation.add_done_callback(my_callback)
36
+
37
+ """
38
+
39
+ import threading
40
+
41
+ from google.api_core import exceptions
42
+ from google.api_core.future import polling
43
+
44
+
45
+ class ExtendedOperation(polling.PollingFuture):
46
+ """An ExtendedOperation future for interacting with a Google API Long-Running Operation.
47
+
48
+ Args:
49
+ extended_operation (proto.Message): The initial operation.
50
+ refresh (Callable[[], type(extended_operation)]): A callable that returns
51
+ the latest state of the operation.
52
+ cancel (Callable[[], None]): A callable that tries to cancel the operation.
53
+ polling Optional(google.api_core.retry.Retry): The configuration used
54
+ for polling. This can be used to control how often :meth:`done`
55
+ is polled. If the ``timeout`` argument to :meth:`result` is
56
+ specified it will override the ``polling.timeout`` property.
57
+ retry Optional(google.api_core.retry.Retry): DEPRECATED use ``polling``
58
+ instead. If specified it will override ``polling`` parameter to
59
+ maintain backward compatibility.
60
+
61
+ Note: Most long-running API methods use google.api_core.operation.Operation
62
+ This class is a wrapper for a subset of methods that use alternative
63
+ Long-Running Operation (LRO) semantics.
64
+
65
+ Note: there is not a concrete type the extended operation must be.
66
+ It MUST have fields that correspond to the following, POSSIBLY WITH DIFFERENT NAMES:
67
+ * name: str
68
+ * status: Union[str, bool, enum.Enum]
69
+ * error_code: int
70
+ * error_message: str
71
+ """
72
+
73
+ def __init__(
74
+ self,
75
+ extended_operation,
76
+ refresh,
77
+ cancel,
78
+ polling=polling.DEFAULT_POLLING,
79
+ **kwargs,
80
+ ):
81
+ super().__init__(polling=polling, **kwargs)
82
+ self._extended_operation = extended_operation
83
+ self._refresh = refresh
84
+ self._cancel = cancel
85
+ # Note: the extended operation does not give a good way to indicate cancellation.
86
+ # We make do with manually tracking cancellation and checking for doneness.
87
+ self._cancelled = False
88
+ self._completion_lock = threading.Lock()
89
+ # Invoke in case the operation came back already complete.
90
+ self._handle_refreshed_operation()
91
+
92
+ # Note: the following four properties MUST be overridden in a subclass
93
+ # if, and only if, the fields in the corresponding extended operation message
94
+ # have different names.
95
+ #
96
+ # E.g. we have an extended operation class that looks like
97
+ #
98
+ # class MyOperation(proto.Message):
99
+ # moniker = proto.Field(proto.STRING, number=1)
100
+ # status_msg = proto.Field(proto.STRING, number=2)
101
+ # optional http_error_code = proto.Field(proto.INT32, number=3)
102
+ # optional http_error_msg = proto.Field(proto.STRING, number=4)
103
+ #
104
+ # the ExtendedOperation subclass would provide property overrides that map
105
+ # to these (poorly named) fields.
106
+ @property
107
+ def name(self):
108
+ return self._extended_operation.name
109
+
110
+ @property
111
+ def status(self):
112
+ return self._extended_operation.status
113
+
114
+ @property
115
+ def error_code(self):
116
+ return self._extended_operation.error_code
117
+
118
+ @property
119
+ def error_message(self):
120
+ return self._extended_operation.error_message
121
+
122
+ def __getattr__(self, name):
123
+ return getattr(self._extended_operation, name)
124
+
125
+ def done(self, retry=None):
126
+ self._refresh_and_update(retry)
127
+ return self._extended_operation.done
128
+
129
+ def cancel(self):
130
+ if self.done():
131
+ return False
132
+
133
+ self._cancel()
134
+ self._cancelled = True
135
+ return True
136
+
137
+ def cancelled(self):
138
+ # TODO(dovs): there is not currently a good way to determine whether the
139
+ # operation has been cancelled.
140
+ # The best we can do is manually keep track of cancellation
141
+ # and check for doneness.
142
+ if not self._cancelled:
143
+ return False
144
+
145
+ self._refresh_and_update()
146
+ return self._extended_operation.done
147
+
148
+ def _refresh_and_update(self, retry=None):
149
+ if not self._extended_operation.done:
150
+ self._extended_operation = (
151
+ self._refresh(retry=retry) if retry else self._refresh()
152
+ )
153
+ self._handle_refreshed_operation()
154
+
155
+ def _handle_refreshed_operation(self):
156
+ with self._completion_lock:
157
+ if not self._extended_operation.done:
158
+ return
159
+
160
+ if self.error_code and self.error_message:
161
+ # Note: `errors` can be removed once proposal A from
162
+ # b/284179390 is implemented.
163
+ errors = []
164
+ if hasattr(self, "error") and hasattr(self.error, "errors"):
165
+ errors = self.error.errors
166
+ exception = exceptions.from_http_status(
167
+ status_code=self.error_code,
168
+ message=self.error_message,
169
+ response=self._extended_operation,
170
+ errors=errors,
171
+ )
172
+ self.set_exception(exception)
173
+ elif self.error_code or self.error_message:
174
+ exception = exceptions.GoogleAPICallError(
175
+ f"Unexpected error {self.error_code}: {self.error_message}"
176
+ )
177
+ self.set_exception(exception)
178
+ else:
179
+ # Extended operations have no payload.
180
+ self.set_result(None)
181
+
182
+ @classmethod
183
+ def make(cls, refresh, cancel, extended_operation, **kwargs):
184
+ """
185
+ Return an instantiated ExtendedOperation (or child) that wraps
186
+ * a refresh callable
187
+ * a cancel callable (can be a no-op)
188
+ * an initial result
189
+
190
+ .. note::
191
+ It is the caller's responsibility to set up refresh and cancel
192
+ with their correct request argument.
193
+ The reason for this is that the services that use Extended Operations
194
+ have rpcs that look something like the following:
195
+
196
+ // service.proto
197
+ service MyLongService {
198
+ rpc StartLongTask(StartLongTaskRequest) returns (ExtendedOperation) {
199
+ option (google.cloud.operation_service) = "CustomOperationService";
200
+ }
201
+ }
202
+
203
+ service CustomOperationService {
204
+ rpc Get(GetOperationRequest) returns (ExtendedOperation) {
205
+ option (google.cloud.operation_polling_method) = true;
206
+ }
207
+ }
208
+
209
+ Any info needed for the poll, e.g. a name, path params, etc.
210
+ is held in the request, which the initial client method is in a much
211
+ better position to make made because the caller made the initial request.
212
+
213
+ TL;DR: the caller sets up closures for refresh and cancel that carry
214
+ the properly configured requests.
215
+
216
+ Args:
217
+ refresh (Callable[Optional[Retry]][type(extended_operation)]): A callable that
218
+ returns the latest state of the operation.
219
+ cancel (Callable[][Any]): A callable that tries to cancel the operation
220
+ on a best effort basis.
221
+ extended_operation (Any): The initial response of the long running method.
222
+ See the docstring for ExtendedOperation.__init__ for requirements on
223
+ the type and fields of extended_operation
224
+ """
225
+ return cls(extended_operation, refresh, cancel, **kwargs)
.venv/lib/python3.11/site-packages/google/api_core/general_helpers.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2017 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # This import for backward compatibility only.
16
+ from functools import wraps # noqa: F401 pragma: NO COVER
.venv/lib/python3.11/site-packages/google/api_core/grpc_helpers.py ADDED
@@ -0,0 +1,622 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2017 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Helpers for :mod:`grpc`."""
16
+ from typing import Generic, Iterator, Optional, TypeVar
17
+
18
+ import collections
19
+ import functools
20
+ import warnings
21
+
22
+ import grpc
23
+
24
+ from google.api_core import exceptions
25
+ import google.auth
26
+ import google.auth.credentials
27
+ import google.auth.transport.grpc
28
+ import google.auth.transport.requests
29
+ import google.protobuf
30
+
31
+ PROTOBUF_VERSION = google.protobuf.__version__
32
+
33
+ # The grpcio-gcp package only has support for protobuf < 4
34
+ if PROTOBUF_VERSION[0:2] == "3.": # pragma: NO COVER
35
+ try:
36
+ import grpc_gcp
37
+
38
+ warnings.warn(
39
+ """Support for grpcio-gcp is deprecated. This feature will be
40
+ removed from `google-api-core` after January 1, 2024. If you need to
41
+ continue to use this feature, please pin to a specific version of
42
+ `google-api-core`.""",
43
+ DeprecationWarning,
44
+ )
45
+ HAS_GRPC_GCP = True
46
+ except ImportError:
47
+ HAS_GRPC_GCP = False
48
+ else:
49
+ HAS_GRPC_GCP = False
50
+
51
+
52
+ # The list of gRPC Callable interfaces that return iterators.
53
+ _STREAM_WRAP_CLASSES = (grpc.UnaryStreamMultiCallable, grpc.StreamStreamMultiCallable)
54
+
55
+ # denotes the proto response type for grpc calls
56
+ P = TypeVar("P")
57
+
58
+
59
+ def _patch_callable_name(callable_):
60
+ """Fix-up gRPC callable attributes.
61
+
62
+ gRPC callable lack the ``__name__`` attribute which causes
63
+ :func:`functools.wraps` to error. This adds the attribute if needed.
64
+ """
65
+ if not hasattr(callable_, "__name__"):
66
+ callable_.__name__ = callable_.__class__.__name__
67
+
68
+
69
+ def _wrap_unary_errors(callable_):
70
+ """Map errors for Unary-Unary and Stream-Unary gRPC callables."""
71
+ _patch_callable_name(callable_)
72
+
73
+ @functools.wraps(callable_)
74
+ def error_remapped_callable(*args, **kwargs):
75
+ try:
76
+ return callable_(*args, **kwargs)
77
+ except grpc.RpcError as exc:
78
+ raise exceptions.from_grpc_error(exc) from exc
79
+
80
+ return error_remapped_callable
81
+
82
+
83
+ class _StreamingResponseIterator(Generic[P], grpc.Call):
84
+ def __init__(self, wrapped, prefetch_first_result=True):
85
+ self._wrapped = wrapped
86
+
87
+ # This iterator is used in a retry context, and returned outside after init.
88
+ # gRPC will not throw an exception until the stream is consumed, so we need
89
+ # to retrieve the first result, in order to fail, in order to trigger a retry.
90
+ try:
91
+ if prefetch_first_result:
92
+ self._stored_first_result = next(self._wrapped)
93
+ except TypeError:
94
+ # It is possible the wrapped method isn't an iterable (a grpc.Call
95
+ # for instance). If this happens don't store the first result.
96
+ pass
97
+ except StopIteration:
98
+ # ignore stop iteration at this time. This should be handled outside of retry.
99
+ pass
100
+
101
+ def __iter__(self) -> Iterator[P]:
102
+ """This iterator is also an iterable that returns itself."""
103
+ return self
104
+
105
+ def __next__(self) -> P:
106
+ """Get the next response from the stream.
107
+
108
+ Returns:
109
+ protobuf.Message: A single response from the stream.
110
+ """
111
+ try:
112
+ if hasattr(self, "_stored_first_result"):
113
+ result = self._stored_first_result
114
+ del self._stored_first_result
115
+ return result
116
+ return next(self._wrapped)
117
+ except grpc.RpcError as exc:
118
+ # If the stream has already returned data, we cannot recover here.
119
+ raise exceptions.from_grpc_error(exc) from exc
120
+
121
+ # grpc.Call & grpc.RpcContext interface
122
+
123
+ def add_callback(self, callback):
124
+ return self._wrapped.add_callback(callback)
125
+
126
+ def cancel(self):
127
+ return self._wrapped.cancel()
128
+
129
+ def code(self):
130
+ return self._wrapped.code()
131
+
132
+ def details(self):
133
+ return self._wrapped.details()
134
+
135
+ def initial_metadata(self):
136
+ return self._wrapped.initial_metadata()
137
+
138
+ def is_active(self):
139
+ return self._wrapped.is_active()
140
+
141
+ def time_remaining(self):
142
+ return self._wrapped.time_remaining()
143
+
144
+ def trailing_metadata(self):
145
+ return self._wrapped.trailing_metadata()
146
+
147
+
148
+ # public type alias denoting the return type of streaming gapic calls
149
+ GrpcStream = _StreamingResponseIterator[P]
150
+
151
+
152
+ def _wrap_stream_errors(callable_):
153
+ """Wrap errors for Unary-Stream and Stream-Stream gRPC callables.
154
+
155
+ The callables that return iterators require a bit more logic to re-map
156
+ errors when iterating. This wraps both the initial invocation and the
157
+ iterator of the return value to re-map errors.
158
+ """
159
+ _patch_callable_name(callable_)
160
+
161
+ @functools.wraps(callable_)
162
+ def error_remapped_callable(*args, **kwargs):
163
+ try:
164
+ result = callable_(*args, **kwargs)
165
+ # Auto-fetching the first result causes PubSub client's streaming pull
166
+ # to hang when re-opening the stream, thus we need examine the hacky
167
+ # hidden flag to see if pre-fetching is disabled.
168
+ # https://github.com/googleapis/python-pubsub/issues/93#issuecomment-630762257
169
+ prefetch_first = getattr(callable_, "_prefetch_first_result_", True)
170
+ return _StreamingResponseIterator(
171
+ result, prefetch_first_result=prefetch_first
172
+ )
173
+ except grpc.RpcError as exc:
174
+ raise exceptions.from_grpc_error(exc) from exc
175
+
176
+ return error_remapped_callable
177
+
178
+
179
+ def wrap_errors(callable_):
180
+ """Wrap a gRPC callable and map :class:`grpc.RpcErrors` to friendly error
181
+ classes.
182
+
183
+ Errors raised by the gRPC callable are mapped to the appropriate
184
+ :class:`google.api_core.exceptions.GoogleAPICallError` subclasses.
185
+ The original `grpc.RpcError` (which is usually also a `grpc.Call`) is
186
+ available from the ``response`` property on the mapped exception. This
187
+ is useful for extracting metadata from the original error.
188
+
189
+ Args:
190
+ callable_ (Callable): A gRPC callable.
191
+
192
+ Returns:
193
+ Callable: The wrapped gRPC callable.
194
+ """
195
+ if isinstance(callable_, _STREAM_WRAP_CLASSES):
196
+ return _wrap_stream_errors(callable_)
197
+ else:
198
+ return _wrap_unary_errors(callable_)
199
+
200
+
201
+ def _create_composite_credentials(
202
+ credentials=None,
203
+ credentials_file=None,
204
+ default_scopes=None,
205
+ scopes=None,
206
+ ssl_credentials=None,
207
+ quota_project_id=None,
208
+ default_host=None,
209
+ ):
210
+ """Create the composite credentials for secure channels.
211
+
212
+ Args:
213
+ credentials (google.auth.credentials.Credentials): The credentials. If
214
+ not specified, then this function will attempt to ascertain the
215
+ credentials from the environment using :func:`google.auth.default`.
216
+ credentials_file (str): A file with credentials that can be loaded with
217
+ :func:`google.auth.load_credentials_from_file`. This argument is
218
+ mutually exclusive with credentials.
219
+ default_scopes (Sequence[str]): A optional list of scopes needed for this
220
+ service. These are only used when credentials are not specified and
221
+ are passed to :func:`google.auth.default`.
222
+ scopes (Sequence[str]): A optional list of scopes needed for this
223
+ service. These are only used when credentials are not specified and
224
+ are passed to :func:`google.auth.default`.
225
+ ssl_credentials (grpc.ChannelCredentials): Optional SSL channel
226
+ credentials. This can be used to specify different certificates.
227
+ quota_project_id (str): An optional project to use for billing and quota.
228
+ default_host (str): The default endpoint. e.g., "pubsub.googleapis.com".
229
+
230
+ Returns:
231
+ grpc.ChannelCredentials: The composed channel credentials object.
232
+
233
+ Raises:
234
+ google.api_core.DuplicateCredentialArgs: If both a credentials object and credentials_file are passed.
235
+ """
236
+ if credentials and credentials_file:
237
+ raise exceptions.DuplicateCredentialArgs(
238
+ "'credentials' and 'credentials_file' are mutually exclusive."
239
+ )
240
+
241
+ if credentials_file:
242
+ credentials, _ = google.auth.load_credentials_from_file(
243
+ credentials_file, scopes=scopes, default_scopes=default_scopes
244
+ )
245
+ elif credentials:
246
+ credentials = google.auth.credentials.with_scopes_if_required(
247
+ credentials, scopes=scopes, default_scopes=default_scopes
248
+ )
249
+ else:
250
+ credentials, _ = google.auth.default(
251
+ scopes=scopes, default_scopes=default_scopes
252
+ )
253
+
254
+ if quota_project_id and isinstance(
255
+ credentials, google.auth.credentials.CredentialsWithQuotaProject
256
+ ):
257
+ credentials = credentials.with_quota_project(quota_project_id)
258
+
259
+ request = google.auth.transport.requests.Request()
260
+
261
+ # Create the metadata plugin for inserting the authorization header.
262
+ metadata_plugin = google.auth.transport.grpc.AuthMetadataPlugin(
263
+ credentials,
264
+ request,
265
+ default_host=default_host,
266
+ )
267
+
268
+ # Create a set of grpc.CallCredentials using the metadata plugin.
269
+ google_auth_credentials = grpc.metadata_call_credentials(metadata_plugin)
270
+
271
+ # if `ssl_credentials` is set, use `grpc.composite_channel_credentials` instead of
272
+ # `grpc.compute_engine_channel_credentials` as the former supports passing
273
+ # `ssl_credentials` via `channel_credentials` which is needed for mTLS.
274
+ if ssl_credentials:
275
+ # Combine the ssl credentials and the authorization credentials.
276
+ # See https://grpc.github.io/grpc/python/grpc.html#grpc.composite_channel_credentials
277
+ return grpc.composite_channel_credentials(
278
+ ssl_credentials, google_auth_credentials
279
+ )
280
+ else:
281
+ # Use grpc.compute_engine_channel_credentials in order to support Direct Path.
282
+ # See https://grpc.github.io/grpc/python/grpc.html#grpc.compute_engine_channel_credentials
283
+ # TODO(https://github.com/googleapis/python-api-core/issues/598):
284
+ # Although `grpc.compute_engine_channel_credentials` returns channel credentials
285
+ # outside of a Google Compute Engine environment (GCE), we should determine if
286
+ # there is a way to reliably detect a GCE environment so that
287
+ # `grpc.compute_engine_channel_credentials` is not called outside of GCE.
288
+ return grpc.compute_engine_channel_credentials(google_auth_credentials)
289
+
290
+
291
+ def create_channel(
292
+ target,
293
+ credentials=None,
294
+ scopes=None,
295
+ ssl_credentials=None,
296
+ credentials_file=None,
297
+ quota_project_id=None,
298
+ default_scopes=None,
299
+ default_host=None,
300
+ compression=None,
301
+ attempt_direct_path: Optional[bool] = False,
302
+ **kwargs,
303
+ ):
304
+ """Create a secure channel with credentials.
305
+
306
+ Args:
307
+ target (str): The target service address in the format 'hostname:port'.
308
+ credentials (google.auth.credentials.Credentials): The credentials. If
309
+ not specified, then this function will attempt to ascertain the
310
+ credentials from the environment using :func:`google.auth.default`.
311
+ scopes (Sequence[str]): A optional list of scopes needed for this
312
+ service. These are only used when credentials are not specified and
313
+ are passed to :func:`google.auth.default`.
314
+ ssl_credentials (grpc.ChannelCredentials): Optional SSL channel
315
+ credentials. This can be used to specify different certificates.
316
+ credentials_file (str): A file with credentials that can be loaded with
317
+ :func:`google.auth.load_credentials_from_file`. This argument is
318
+ mutually exclusive with credentials.
319
+ quota_project_id (str): An optional project to use for billing and quota.
320
+ default_scopes (Sequence[str]): Default scopes passed by a Google client
321
+ library. Use 'scopes' for user-defined scopes.
322
+ default_host (str): The default endpoint. e.g., "pubsub.googleapis.com".
323
+ compression (grpc.Compression): An optional value indicating the
324
+ compression method to be used over the lifetime of the channel.
325
+ attempt_direct_path (Optional[bool]): If set, Direct Path will be attempted
326
+ when the request is made. Direct Path is only available within a Google
327
+ Compute Engine (GCE) environment and provides a proxyless connection
328
+ which increases the available throughput, reduces latency, and increases
329
+ reliability. Note:
330
+
331
+ - This argument should only be set in a GCE environment and for Services
332
+ that are known to support Direct Path.
333
+ - If this argument is set outside of GCE, then this request will fail
334
+ unless the back-end service happens to have configured fall-back to DNS.
335
+ - If the request causes a `ServiceUnavailable` response, it is recommended
336
+ that the client repeat the request with `attempt_direct_path` set to
337
+ `False` as the Service may not support Direct Path.
338
+ - Using `ssl_credentials` with `attempt_direct_path` set to `True` will
339
+ result in `ValueError` as this combination is not yet supported.
340
+
341
+ kwargs: Additional key-word args passed to
342
+ :func:`grpc_gcp.secure_channel` or :func:`grpc.secure_channel`.
343
+ Note: `grpc_gcp` is only supported in environments with protobuf < 4.0.0.
344
+
345
+ Returns:
346
+ grpc.Channel: The created channel.
347
+
348
+ Raises:
349
+ google.api_core.DuplicateCredentialArgs: If both a credentials object and credentials_file are passed.
350
+ ValueError: If `ssl_credentials` is set and `attempt_direct_path` is set to `True`.
351
+ """
352
+
353
+ # If `ssl_credentials` is set and `attempt_direct_path` is set to `True`,
354
+ # raise ValueError as this is not yet supported.
355
+ # See https://github.com/googleapis/python-api-core/issues/590
356
+ if ssl_credentials and attempt_direct_path:
357
+ raise ValueError("Using ssl_credentials with Direct Path is not supported")
358
+
359
+ composite_credentials = _create_composite_credentials(
360
+ credentials=credentials,
361
+ credentials_file=credentials_file,
362
+ default_scopes=default_scopes,
363
+ scopes=scopes,
364
+ ssl_credentials=ssl_credentials,
365
+ quota_project_id=quota_project_id,
366
+ default_host=default_host,
367
+ )
368
+
369
+ # Note that grpcio-gcp is deprecated
370
+ if HAS_GRPC_GCP: # pragma: NO COVER
371
+ if compression is not None and compression != grpc.Compression.NoCompression:
372
+ warnings.warn(
373
+ "The `compression` argument is ignored for grpc_gcp.secure_channel creation.",
374
+ DeprecationWarning,
375
+ )
376
+ if attempt_direct_path:
377
+ warnings.warn(
378
+ """The `attempt_direct_path` argument is ignored for grpc_gcp.secure_channel creation.""",
379
+ DeprecationWarning,
380
+ )
381
+ return grpc_gcp.secure_channel(target, composite_credentials, **kwargs)
382
+
383
+ if attempt_direct_path:
384
+ target = _modify_target_for_direct_path(target)
385
+
386
+ return grpc.secure_channel(
387
+ target, composite_credentials, compression=compression, **kwargs
388
+ )
389
+
390
+
391
+ def _modify_target_for_direct_path(target: str) -> str:
392
+ """
393
+ Given a target, return a modified version which is compatible with Direct Path.
394
+
395
+ Args:
396
+ target (str): The target service address in the format 'hostname[:port]' or
397
+ 'dns://hostname[:port]'.
398
+
399
+ Returns:
400
+ target (str): The target service address which is converted into a format compatible with Direct Path.
401
+ If the target contains `dns:///` or does not contain `:///`, the target will be converted in
402
+ a format compatible with Direct Path; otherwise the original target will be returned as the
403
+ original target may already denote Direct Path.
404
+ """
405
+
406
+ # A DNS prefix may be included with the target to indicate the endpoint is living in the Internet,
407
+ # outside of Google Cloud Platform.
408
+ dns_prefix = "dns:///"
409
+ # Remove "dns:///" if `attempt_direct_path` is set to True as
410
+ # the Direct Path prefix `google-c2p:///` will be used instead.
411
+ target = target.replace(dns_prefix, "")
412
+
413
+ direct_path_separator = ":///"
414
+ if direct_path_separator not in target:
415
+ target_without_port = target.split(":")[0]
416
+ # Modify the target to use Direct Path by adding the `google-c2p:///` prefix
417
+ target = f"google-c2p{direct_path_separator}{target_without_port}"
418
+ return target
419
+
420
+
421
+ _MethodCall = collections.namedtuple(
422
+ "_MethodCall", ("request", "timeout", "metadata", "credentials", "compression")
423
+ )
424
+
425
+ _ChannelRequest = collections.namedtuple("_ChannelRequest", ("method", "request"))
426
+
427
+
428
+ class _CallableStub(object):
429
+ """Stub for the grpc.*MultiCallable interfaces."""
430
+
431
+ def __init__(self, method, channel):
432
+ self._method = method
433
+ self._channel = channel
434
+ self.response = None
435
+ """Union[protobuf.Message, Callable[protobuf.Message], exception]:
436
+ The response to give when invoking this callable. If this is a
437
+ callable, it will be invoked with the request protobuf. If it's an
438
+ exception, the exception will be raised when this is invoked.
439
+ """
440
+ self.responses = None
441
+ """Iterator[
442
+ Union[protobuf.Message, Callable[protobuf.Message], exception]]:
443
+ An iterator of responses. If specified, self.response will be populated
444
+ on each invocation by calling ``next(self.responses)``."""
445
+ self.requests = []
446
+ """List[protobuf.Message]: All requests sent to this callable."""
447
+ self.calls = []
448
+ """List[Tuple]: All invocations of this callable. Each tuple is the
449
+ request, timeout, metadata, compression, and credentials."""
450
+
451
+ def __call__(
452
+ self, request, timeout=None, metadata=None, credentials=None, compression=None
453
+ ):
454
+ self._channel.requests.append(_ChannelRequest(self._method, request))
455
+ self.calls.append(
456
+ _MethodCall(request, timeout, metadata, credentials, compression)
457
+ )
458
+ self.requests.append(request)
459
+
460
+ response = self.response
461
+ if self.responses is not None:
462
+ if response is None:
463
+ response = next(self.responses)
464
+ else:
465
+ raise ValueError(
466
+ "{method}.response and {method}.responses are mutually "
467
+ "exclusive.".format(method=self._method)
468
+ )
469
+
470
+ if callable(response):
471
+ return response(request)
472
+
473
+ if isinstance(response, Exception):
474
+ raise response
475
+
476
+ if response is not None:
477
+ return response
478
+
479
+ raise ValueError('Method stub for "{}" has no response.'.format(self._method))
480
+
481
+
482
+ def _simplify_method_name(method):
483
+ """Simplifies a gRPC method name.
484
+
485
+ When gRPC invokes the channel to create a callable, it gives a full
486
+ method name like "/google.pubsub.v1.Publisher/CreateTopic". This
487
+ returns just the name of the method, in this case "CreateTopic".
488
+
489
+ Args:
490
+ method (str): The name of the method.
491
+
492
+ Returns:
493
+ str: The simplified name of the method.
494
+ """
495
+ return method.rsplit("/", 1).pop()
496
+
497
+
498
+ class ChannelStub(grpc.Channel):
499
+ """A testing stub for the grpc.Channel interface.
500
+
501
+ This can be used to test any client that eventually uses a gRPC channel
502
+ to communicate. By passing in a channel stub, you can configure which
503
+ responses are returned and track which requests are made.
504
+
505
+ For example:
506
+
507
+ .. code-block:: python
508
+
509
+ channel_stub = grpc_helpers.ChannelStub()
510
+ client = FooClient(channel=channel_stub)
511
+
512
+ channel_stub.GetFoo.response = foo_pb2.Foo(name='bar')
513
+
514
+ foo = client.get_foo(labels=['baz'])
515
+
516
+ assert foo.name == 'bar'
517
+ assert channel_stub.GetFoo.requests[0].labels = ['baz']
518
+
519
+ Each method on the stub can be accessed and configured on the channel.
520
+ Here's some examples of various configurations:
521
+
522
+ .. code-block:: python
523
+
524
+ # Return a basic response:
525
+
526
+ channel_stub.GetFoo.response = foo_pb2.Foo(name='bar')
527
+ assert client.get_foo().name == 'bar'
528
+
529
+ # Raise an exception:
530
+ channel_stub.GetFoo.response = NotFound('...')
531
+
532
+ with pytest.raises(NotFound):
533
+ client.get_foo()
534
+
535
+ # Use a sequence of responses:
536
+ channel_stub.GetFoo.responses = iter([
537
+ foo_pb2.Foo(name='bar'),
538
+ foo_pb2.Foo(name='baz'),
539
+ ])
540
+
541
+ assert client.get_foo().name == 'bar'
542
+ assert client.get_foo().name == 'baz'
543
+
544
+ # Use a callable
545
+
546
+ def on_get_foo(request):
547
+ return foo_pb2.Foo(name='bar' + request.id)
548
+
549
+ channel_stub.GetFoo.response = on_get_foo
550
+
551
+ assert client.get_foo(id='123').name == 'bar123'
552
+ """
553
+
554
+ def __init__(self, responses=[]):
555
+ self.requests = []
556
+ """Sequence[Tuple[str, protobuf.Message]]: A list of all requests made
557
+ on this channel in order. The tuple is of method name, request
558
+ message."""
559
+ self._method_stubs = {}
560
+
561
+ def _stub_for_method(self, method):
562
+ method = _simplify_method_name(method)
563
+ self._method_stubs[method] = _CallableStub(method, self)
564
+ return self._method_stubs[method]
565
+
566
+ def __getattr__(self, key):
567
+ try:
568
+ return self._method_stubs[key]
569
+ except KeyError:
570
+ raise AttributeError
571
+
572
+ def unary_unary(
573
+ self,
574
+ method,
575
+ request_serializer=None,
576
+ response_deserializer=None,
577
+ _registered_method=False,
578
+ ):
579
+ """grpc.Channel.unary_unary implementation."""
580
+ return self._stub_for_method(method)
581
+
582
+ def unary_stream(
583
+ self,
584
+ method,
585
+ request_serializer=None,
586
+ response_deserializer=None,
587
+ _registered_method=False,
588
+ ):
589
+ """grpc.Channel.unary_stream implementation."""
590
+ return self._stub_for_method(method)
591
+
592
+ def stream_unary(
593
+ self,
594
+ method,
595
+ request_serializer=None,
596
+ response_deserializer=None,
597
+ _registered_method=False,
598
+ ):
599
+ """grpc.Channel.stream_unary implementation."""
600
+ return self._stub_for_method(method)
601
+
602
+ def stream_stream(
603
+ self,
604
+ method,
605
+ request_serializer=None,
606
+ response_deserializer=None,
607
+ _registered_method=False,
608
+ ):
609
+ """grpc.Channel.stream_stream implementation."""
610
+ return self._stub_for_method(method)
611
+
612
+ def subscribe(self, callback, try_to_connect=False):
613
+ """grpc.Channel.subscribe implementation."""
614
+ pass
615
+
616
+ def unsubscribe(self, callback):
617
+ """grpc.Channel.unsubscribe implementation."""
618
+ pass
619
+
620
+ def close(self):
621
+ """grpc.Channel.close implementation."""
622
+ pass
.venv/lib/python3.11/site-packages/google/api_core/grpc_helpers_async.py ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """AsyncIO helpers for :mod:`grpc` supporting 3.7+.
16
+
17
+ Please combine more detailed docstring in grpc_helpers.py to use following
18
+ functions. This module is implementing the same surface with AsyncIO semantics.
19
+ """
20
+
21
+ import asyncio
22
+ import functools
23
+
24
+ from typing import AsyncGenerator, Generic, Iterator, Optional, TypeVar
25
+
26
+ import grpc
27
+ from grpc import aio
28
+
29
+ from google.api_core import exceptions, grpc_helpers
30
+
31
+ # denotes the proto response type for grpc calls
32
+ P = TypeVar("P")
33
+
34
+ # NOTE(lidiz) Alternatively, we can hack "__getattribute__" to perform
35
+ # automatic patching for us. But that means the overhead of creating an
36
+ # extra Python function spreads to every single send and receive.
37
+
38
+
39
+ class _WrappedCall(aio.Call):
40
+ def __init__(self):
41
+ self._call = None
42
+
43
+ def with_call(self, call):
44
+ """Supplies the call object separately to keep __init__ clean."""
45
+ self._call = call
46
+ return self
47
+
48
+ async def initial_metadata(self):
49
+ return await self._call.initial_metadata()
50
+
51
+ async def trailing_metadata(self):
52
+ return await self._call.trailing_metadata()
53
+
54
+ async def code(self):
55
+ return await self._call.code()
56
+
57
+ async def details(self):
58
+ return await self._call.details()
59
+
60
+ def cancelled(self):
61
+ return self._call.cancelled()
62
+
63
+ def done(self):
64
+ return self._call.done()
65
+
66
+ def time_remaining(self):
67
+ return self._call.time_remaining()
68
+
69
+ def cancel(self):
70
+ return self._call.cancel()
71
+
72
+ def add_done_callback(self, callback):
73
+ self._call.add_done_callback(callback)
74
+
75
+ async def wait_for_connection(self):
76
+ try:
77
+ await self._call.wait_for_connection()
78
+ except grpc.RpcError as rpc_error:
79
+ raise exceptions.from_grpc_error(rpc_error) from rpc_error
80
+
81
+
82
+ class _WrappedUnaryResponseMixin(Generic[P], _WrappedCall):
83
+ def __await__(self) -> Iterator[P]:
84
+ try:
85
+ response = yield from self._call.__await__()
86
+ return response
87
+ except grpc.RpcError as rpc_error:
88
+ raise exceptions.from_grpc_error(rpc_error) from rpc_error
89
+
90
+
91
+ class _WrappedStreamResponseMixin(Generic[P], _WrappedCall):
92
+ def __init__(self):
93
+ self._wrapped_async_generator = None
94
+
95
+ async def read(self) -> P:
96
+ try:
97
+ return await self._call.read()
98
+ except grpc.RpcError as rpc_error:
99
+ raise exceptions.from_grpc_error(rpc_error) from rpc_error
100
+
101
+ async def _wrapped_aiter(self) -> AsyncGenerator[P, None]:
102
+ try:
103
+ # NOTE(lidiz) coverage doesn't understand the exception raised from
104
+ # __anext__ method. It is covered by test case:
105
+ # test_wrap_stream_errors_aiter_non_rpc_error
106
+ async for response in self._call: # pragma: no branch
107
+ yield response
108
+ except grpc.RpcError as rpc_error:
109
+ raise exceptions.from_grpc_error(rpc_error) from rpc_error
110
+
111
+ def __aiter__(self) -> AsyncGenerator[P, None]:
112
+ if not self._wrapped_async_generator:
113
+ self._wrapped_async_generator = self._wrapped_aiter()
114
+ return self._wrapped_async_generator
115
+
116
+
117
+ class _WrappedStreamRequestMixin(_WrappedCall):
118
+ async def write(self, request):
119
+ try:
120
+ await self._call.write(request)
121
+ except grpc.RpcError as rpc_error:
122
+ raise exceptions.from_grpc_error(rpc_error) from rpc_error
123
+
124
+ async def done_writing(self):
125
+ try:
126
+ await self._call.done_writing()
127
+ except grpc.RpcError as rpc_error:
128
+ raise exceptions.from_grpc_error(rpc_error) from rpc_error
129
+
130
+
131
+ # NOTE(lidiz) Implementing each individual class separately, so we don't
132
+ # expose any API that should not be seen. E.g., __aiter__ in unary-unary
133
+ # RPC, or __await__ in stream-stream RPC.
134
+ class _WrappedUnaryUnaryCall(_WrappedUnaryResponseMixin[P], aio.UnaryUnaryCall):
135
+ """Wrapped UnaryUnaryCall to map exceptions."""
136
+
137
+
138
+ class _WrappedUnaryStreamCall(_WrappedStreamResponseMixin[P], aio.UnaryStreamCall):
139
+ """Wrapped UnaryStreamCall to map exceptions."""
140
+
141
+
142
+ class _WrappedStreamUnaryCall(
143
+ _WrappedUnaryResponseMixin[P], _WrappedStreamRequestMixin, aio.StreamUnaryCall
144
+ ):
145
+ """Wrapped StreamUnaryCall to map exceptions."""
146
+
147
+
148
+ class _WrappedStreamStreamCall(
149
+ _WrappedStreamRequestMixin, _WrappedStreamResponseMixin[P], aio.StreamStreamCall
150
+ ):
151
+ """Wrapped StreamStreamCall to map exceptions."""
152
+
153
+
154
+ # public type alias denoting the return type of async streaming gapic calls
155
+ GrpcAsyncStream = _WrappedStreamResponseMixin[P]
156
+ # public type alias denoting the return type of unary gapic calls
157
+ AwaitableGrpcCall = _WrappedUnaryResponseMixin[P]
158
+
159
+
160
+ def _wrap_unary_errors(callable_):
161
+ """Map errors for Unary-Unary async callables."""
162
+
163
+ @functools.wraps(callable_)
164
+ def error_remapped_callable(*args, **kwargs):
165
+ call = callable_(*args, **kwargs)
166
+ return _WrappedUnaryUnaryCall().with_call(call)
167
+
168
+ return error_remapped_callable
169
+
170
+
171
+ def _wrap_stream_errors(callable_, wrapper_type):
172
+ """Map errors for streaming RPC async callables."""
173
+
174
+ @functools.wraps(callable_)
175
+ async def error_remapped_callable(*args, **kwargs):
176
+ call = callable_(*args, **kwargs)
177
+ call = wrapper_type().with_call(call)
178
+ await call.wait_for_connection()
179
+ return call
180
+
181
+ return error_remapped_callable
182
+
183
+
184
+ def wrap_errors(callable_):
185
+ """Wrap a gRPC async callable and map :class:`grpc.RpcErrors` to
186
+ friendly error classes.
187
+
188
+ Errors raised by the gRPC callable are mapped to the appropriate
189
+ :class:`google.api_core.exceptions.GoogleAPICallError` subclasses. The
190
+ original `grpc.RpcError` (which is usually also a `grpc.Call`) is
191
+ available from the ``response`` property on the mapped exception. This
192
+ is useful for extracting metadata from the original error.
193
+
194
+ Args:
195
+ callable_ (Callable): A gRPC callable.
196
+
197
+ Returns: Callable: The wrapped gRPC callable.
198
+ """
199
+ grpc_helpers._patch_callable_name(callable_)
200
+
201
+ if isinstance(callable_, aio.UnaryStreamMultiCallable):
202
+ return _wrap_stream_errors(callable_, _WrappedUnaryStreamCall)
203
+ elif isinstance(callable_, aio.StreamUnaryMultiCallable):
204
+ return _wrap_stream_errors(callable_, _WrappedStreamUnaryCall)
205
+ elif isinstance(callable_, aio.StreamStreamMultiCallable):
206
+ return _wrap_stream_errors(callable_, _WrappedStreamStreamCall)
207
+ else:
208
+ return _wrap_unary_errors(callable_)
209
+
210
+
211
+ def create_channel(
212
+ target,
213
+ credentials=None,
214
+ scopes=None,
215
+ ssl_credentials=None,
216
+ credentials_file=None,
217
+ quota_project_id=None,
218
+ default_scopes=None,
219
+ default_host=None,
220
+ compression=None,
221
+ attempt_direct_path: Optional[bool] = False,
222
+ **kwargs
223
+ ):
224
+ """Create an AsyncIO secure channel with credentials.
225
+
226
+ Args:
227
+ target (str): The target service address in the format 'hostname:port'.
228
+ credentials (google.auth.credentials.Credentials): The credentials. If
229
+ not specified, then this function will attempt to ascertain the
230
+ credentials from the environment using :func:`google.auth.default`.
231
+ scopes (Sequence[str]): A optional list of scopes needed for this
232
+ service. These are only used when credentials are not specified and
233
+ are passed to :func:`google.auth.default`.
234
+ ssl_credentials (grpc.ChannelCredentials): Optional SSL channel
235
+ credentials. This can be used to specify different certificates.
236
+ credentials_file (str): A file with credentials that can be loaded with
237
+ :func:`google.auth.load_credentials_from_file`. This argument is
238
+ mutually exclusive with credentials.
239
+ quota_project_id (str): An optional project to use for billing and quota.
240
+ default_scopes (Sequence[str]): Default scopes passed by a Google client
241
+ library. Use 'scopes' for user-defined scopes.
242
+ default_host (str): The default endpoint. e.g., "pubsub.googleapis.com".
243
+ compression (grpc.Compression): An optional value indicating the
244
+ compression method to be used over the lifetime of the channel.
245
+ attempt_direct_path (Optional[bool]): If set, Direct Path will be attempted
246
+ when the request is made. Direct Path is only available within a Google
247
+ Compute Engine (GCE) environment and provides a proxyless connection
248
+ which increases the available throughput, reduces latency, and increases
249
+ reliability. Note:
250
+
251
+ - This argument should only be set in a GCE environment and for Services
252
+ that are known to support Direct Path.
253
+ - If this argument is set outside of GCE, then this request will fail
254
+ unless the back-end service happens to have configured fall-back to DNS.
255
+ - If the request causes a `ServiceUnavailable` response, it is recommended
256
+ that the client repeat the request with `attempt_direct_path` set to
257
+ `False` as the Service may not support Direct Path.
258
+ - Using `ssl_credentials` with `attempt_direct_path` set to `True` will
259
+ result in `ValueError` as this combination is not yet supported.
260
+
261
+ kwargs: Additional key-word args passed to :func:`aio.secure_channel`.
262
+
263
+ Returns:
264
+ aio.Channel: The created channel.
265
+
266
+ Raises:
267
+ google.api_core.DuplicateCredentialArgs: If both a credentials object and credentials_file are passed.
268
+ ValueError: If `ssl_credentials` is set and `attempt_direct_path` is set to `True`.
269
+ """
270
+
271
+ # If `ssl_credentials` is set and `attempt_direct_path` is set to `True`,
272
+ # raise ValueError as this is not yet supported.
273
+ # See https://github.com/googleapis/python-api-core/issues/590
274
+ if ssl_credentials and attempt_direct_path:
275
+ raise ValueError("Using ssl_credentials with Direct Path is not supported")
276
+
277
+ composite_credentials = grpc_helpers._create_composite_credentials(
278
+ credentials=credentials,
279
+ credentials_file=credentials_file,
280
+ scopes=scopes,
281
+ default_scopes=default_scopes,
282
+ ssl_credentials=ssl_credentials,
283
+ quota_project_id=quota_project_id,
284
+ default_host=default_host,
285
+ )
286
+
287
+ if attempt_direct_path:
288
+ target = grpc_helpers._modify_target_for_direct_path(target)
289
+
290
+ return aio.secure_channel(
291
+ target, composite_credentials, compression=compression, **kwargs
292
+ )
293
+
294
+
295
+ class FakeUnaryUnaryCall(_WrappedUnaryUnaryCall):
296
+ """Fake implementation for unary-unary RPCs.
297
+
298
+ It is a dummy object for response message. Supply the intended response
299
+ upon the initialization, and the coroutine will return the exact response
300
+ message.
301
+ """
302
+
303
+ def __init__(self, response=object()):
304
+ self.response = response
305
+ self._future = asyncio.get_event_loop().create_future()
306
+ self._future.set_result(self.response)
307
+
308
+ def __await__(self):
309
+ response = yield from self._future.__await__()
310
+ return response
311
+
312
+
313
+ class FakeStreamUnaryCall(_WrappedStreamUnaryCall):
314
+ """Fake implementation for stream-unary RPCs.
315
+
316
+ It is a dummy object for response message. Supply the intended response
317
+ upon the initialization, and the coroutine will return the exact response
318
+ message.
319
+ """
320
+
321
+ def __init__(self, response=object()):
322
+ self.response = response
323
+ self._future = asyncio.get_event_loop().create_future()
324
+ self._future.set_result(self.response)
325
+
326
+ def __await__(self):
327
+ response = yield from self._future.__await__()
328
+ return response
329
+
330
+ async def wait_for_connection(self):
331
+ pass