airbyte-agent-google-drive 0.1.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airbyte_agent_google_drive/__init__.py +151 -0
- airbyte_agent_google_drive/_vendored/__init__.py +1 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/__init__.py +82 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/auth_strategies.py +1120 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/auth_template.py +135 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/cloud_utils/__init__.py +5 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/cloud_utils/client.py +213 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/connector_model_loader.py +965 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/constants.py +78 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/exceptions.py +23 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/executor/__init__.py +31 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/executor/hosted_executor.py +196 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/executor/local_executor.py +1633 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/executor/models.py +190 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/extensions.py +693 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http/__init__.py +37 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http/adapters/__init__.py +9 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http/adapters/httpx_adapter.py +251 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http/config.py +98 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http/exceptions.py +119 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http/protocols.py +114 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http/response.py +104 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/http_client.py +686 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/introspection.py +262 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/logging/__init__.py +11 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/logging/logger.py +264 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/logging/types.py +92 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/observability/__init__.py +11 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/observability/config.py +179 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/observability/models.py +19 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/observability/redactor.py +81 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/observability/session.py +103 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/performance/__init__.py +6 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/performance/instrumentation.py +57 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/performance/metrics.py +93 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/schema/__init__.py +75 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/schema/base.py +164 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/schema/components.py +239 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/schema/connector.py +120 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/schema/extensions.py +230 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/schema/operations.py +146 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/schema/security.py +223 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/secrets.py +182 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/telemetry/__init__.py +10 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/telemetry/config.py +32 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/telemetry/events.py +59 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/telemetry/tracker.py +155 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/types.py +245 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/utils.py +60 -0
- airbyte_agent_google_drive/_vendored/connector_sdk/validation.py +822 -0
- airbyte_agent_google_drive/connector.py +1318 -0
- airbyte_agent_google_drive/connector_model.py +4966 -0
- airbyte_agent_google_drive/models.py +579 -0
- airbyte_agent_google_drive/types.py +141 -0
- airbyte_agent_google_drive-0.1.15.dist-info/METADATA +123 -0
- airbyte_agent_google_drive-0.1.15.dist-info/RECORD +57 -0
- airbyte_agent_google_drive-0.1.15.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,1318 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Google-Drive connector.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Callable, TypeVar, AsyncIterator, overload
|
|
9
|
+
try:
|
|
10
|
+
from typing import Literal
|
|
11
|
+
except ImportError:
|
|
12
|
+
from typing_extensions import Literal
|
|
13
|
+
|
|
14
|
+
from .connector_model import GoogleDriveConnectorModel
|
|
15
|
+
from ._vendored.connector_sdk.introspection import describe_entities, generate_tool_description
|
|
16
|
+
from .types import (
|
|
17
|
+
AboutGetParams,
|
|
18
|
+
ChangesListParams,
|
|
19
|
+
ChangesStartPageTokenGetParams,
|
|
20
|
+
CommentsGetParams,
|
|
21
|
+
CommentsListParams,
|
|
22
|
+
DrivesGetParams,
|
|
23
|
+
DrivesListParams,
|
|
24
|
+
FilesDownloadParams,
|
|
25
|
+
FilesExportDownloadParams,
|
|
26
|
+
FilesGetParams,
|
|
27
|
+
FilesListParams,
|
|
28
|
+
PermissionsGetParams,
|
|
29
|
+
PermissionsListParams,
|
|
30
|
+
RepliesGetParams,
|
|
31
|
+
RepliesListParams,
|
|
32
|
+
RevisionsGetParams,
|
|
33
|
+
RevisionsListParams,
|
|
34
|
+
)
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from .models import GoogleDriveAuthConfig
|
|
37
|
+
# Import response models and envelope models at runtime
|
|
38
|
+
from .models import (
|
|
39
|
+
GoogleDriveExecuteResult,
|
|
40
|
+
GoogleDriveExecuteResultWithMeta,
|
|
41
|
+
FilesListResult,
|
|
42
|
+
DrivesListResult,
|
|
43
|
+
PermissionsListResult,
|
|
44
|
+
CommentsListResult,
|
|
45
|
+
RepliesListResult,
|
|
46
|
+
RevisionsListResult,
|
|
47
|
+
ChangesListResult,
|
|
48
|
+
About,
|
|
49
|
+
Change,
|
|
50
|
+
Comment,
|
|
51
|
+
Drive,
|
|
52
|
+
File,
|
|
53
|
+
Permission,
|
|
54
|
+
Reply,
|
|
55
|
+
Revision,
|
|
56
|
+
StartPageToken,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# TypeVar for decorator type preservation
|
|
60
|
+
_F = TypeVar("_F", bound=Callable[..., Any])
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class GoogleDriveConnector:
|
|
64
|
+
"""
|
|
65
|
+
Type-safe Google-Drive API connector.
|
|
66
|
+
|
|
67
|
+
Auto-generated from OpenAPI specification with full type safety.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
connector_name = "google-drive"
|
|
71
|
+
connector_version = "0.1.1"
|
|
72
|
+
vendored_sdk_version = "0.1.0" # Version of vendored connector-sdk
|
|
73
|
+
|
|
74
|
+
# Map of (entity, action) -> needs_envelope for envelope wrapping decision
|
|
75
|
+
_ENVELOPE_MAP = {
|
|
76
|
+
("files", "list"): True,
|
|
77
|
+
("files", "get"): None,
|
|
78
|
+
("files", "download"): None,
|
|
79
|
+
("files_export", "download"): None,
|
|
80
|
+
("drives", "list"): True,
|
|
81
|
+
("drives", "get"): None,
|
|
82
|
+
("permissions", "list"): True,
|
|
83
|
+
("permissions", "get"): None,
|
|
84
|
+
("comments", "list"): True,
|
|
85
|
+
("comments", "get"): None,
|
|
86
|
+
("replies", "list"): True,
|
|
87
|
+
("replies", "get"): None,
|
|
88
|
+
("revisions", "list"): True,
|
|
89
|
+
("revisions", "get"): None,
|
|
90
|
+
("changes", "list"): True,
|
|
91
|
+
("changes_start_page_token", "get"): None,
|
|
92
|
+
("about", "get"): None,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Map of (entity, action) -> {python_param_name: api_param_name}
|
|
96
|
+
# Used to convert snake_case TypedDict keys to API parameter names in execute()
|
|
97
|
+
_PARAM_MAP = {
|
|
98
|
+
('files', 'list'): {'page_size': 'pageSize', 'page_token': 'pageToken', 'q': 'q', 'order_by': 'orderBy', 'fields': 'fields', 'spaces': 'spaces', 'corpora': 'corpora', 'drive_id': 'driveId', 'include_items_from_all_drives': 'includeItemsFromAllDrives', 'supports_all_drives': 'supportsAllDrives'},
|
|
99
|
+
('files', 'get'): {'file_id': 'fileId', 'fields': 'fields', 'supports_all_drives': 'supportsAllDrives'},
|
|
100
|
+
('files', 'download'): {'file_id': 'fileId', 'alt': 'alt', 'acknowledge_abuse': 'acknowledgeAbuse', 'supports_all_drives': 'supportsAllDrives', 'range_header': 'range_header'},
|
|
101
|
+
('files_export', 'download'): {'file_id': 'fileId', 'mime_type': 'mimeType', 'range_header': 'range_header'},
|
|
102
|
+
('drives', 'list'): {'page_size': 'pageSize', 'page_token': 'pageToken', 'q': 'q', 'use_domain_admin_access': 'useDomainAdminAccess'},
|
|
103
|
+
('drives', 'get'): {'drive_id': 'driveId', 'use_domain_admin_access': 'useDomainAdminAccess'},
|
|
104
|
+
('permissions', 'list'): {'file_id': 'fileId', 'page_size': 'pageSize', 'page_token': 'pageToken', 'supports_all_drives': 'supportsAllDrives', 'use_domain_admin_access': 'useDomainAdminAccess'},
|
|
105
|
+
('permissions', 'get'): {'file_id': 'fileId', 'permission_id': 'permissionId', 'supports_all_drives': 'supportsAllDrives', 'use_domain_admin_access': 'useDomainAdminAccess'},
|
|
106
|
+
('comments', 'list'): {'file_id': 'fileId', 'page_size': 'pageSize', 'page_token': 'pageToken', 'start_modified_time': 'startModifiedTime', 'include_deleted': 'includeDeleted', 'fields': 'fields'},
|
|
107
|
+
('comments', 'get'): {'file_id': 'fileId', 'comment_id': 'commentId', 'include_deleted': 'includeDeleted', 'fields': 'fields'},
|
|
108
|
+
('replies', 'list'): {'file_id': 'fileId', 'comment_id': 'commentId', 'page_size': 'pageSize', 'page_token': 'pageToken', 'include_deleted': 'includeDeleted', 'fields': 'fields'},
|
|
109
|
+
('replies', 'get'): {'file_id': 'fileId', 'comment_id': 'commentId', 'reply_id': 'replyId', 'include_deleted': 'includeDeleted', 'fields': 'fields'},
|
|
110
|
+
('revisions', 'list'): {'file_id': 'fileId', 'page_size': 'pageSize', 'page_token': 'pageToken'},
|
|
111
|
+
('revisions', 'get'): {'file_id': 'fileId', 'revision_id': 'revisionId'},
|
|
112
|
+
('changes', 'list'): {'page_token': 'pageToken', 'page_size': 'pageSize', 'drive_id': 'driveId', 'include_items_from_all_drives': 'includeItemsFromAllDrives', 'supports_all_drives': 'supportsAllDrives', 'spaces': 'spaces', 'include_removed': 'includeRemoved', 'restrict_to_my_drive': 'restrictToMyDrive'},
|
|
113
|
+
('changes_start_page_token', 'get'): {'drive_id': 'driveId', 'supports_all_drives': 'supportsAllDrives'},
|
|
114
|
+
('about', 'get'): {'fields': 'fields'},
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
def __init__(
|
|
118
|
+
self,
|
|
119
|
+
auth_config: GoogleDriveAuthConfig | None = None,
|
|
120
|
+
external_user_id: str | None = None,
|
|
121
|
+
airbyte_client_id: str | None = None,
|
|
122
|
+
airbyte_client_secret: str | None = None,
|
|
123
|
+
on_token_refresh: Any | None = None ):
|
|
124
|
+
"""
|
|
125
|
+
Initialize a new google-drive connector instance.
|
|
126
|
+
|
|
127
|
+
Supports both local and hosted execution modes:
|
|
128
|
+
- Local mode: Provide `auth_config` for direct API calls
|
|
129
|
+
- Hosted mode: Provide `external_user_id`, `airbyte_client_id`, and `airbyte_client_secret` for hosted execution
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
auth_config: Typed authentication configuration (required for local mode)
|
|
133
|
+
external_user_id: External user ID (required for hosted mode)
|
|
134
|
+
airbyte_client_id: Airbyte OAuth client ID (required for hosted mode)
|
|
135
|
+
airbyte_client_secret: Airbyte OAuth client secret (required for hosted mode)
|
|
136
|
+
on_token_refresh: Optional callback for OAuth2 token refresh persistence.
|
|
137
|
+
Called with new_tokens dict when tokens are refreshed. Can be sync or async.
|
|
138
|
+
Example: lambda tokens: save_to_database(tokens)
|
|
139
|
+
Examples:
|
|
140
|
+
# Local mode (direct API calls)
|
|
141
|
+
connector = GoogleDriveConnector(auth_config=GoogleDriveAuthConfig(access_token="...", refresh_token="...", client_id="...", client_secret="..."))
|
|
142
|
+
# Hosted mode (executed on Airbyte cloud)
|
|
143
|
+
connector = GoogleDriveConnector(
|
|
144
|
+
external_user_id="user-123",
|
|
145
|
+
airbyte_client_id="client_abc123",
|
|
146
|
+
airbyte_client_secret="secret_xyz789"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Local mode with OAuth2 token refresh callback
|
|
150
|
+
def save_tokens(new_tokens: dict) -> None:
|
|
151
|
+
# Persist updated tokens to your storage (file, database, etc.)
|
|
152
|
+
with open("tokens.json", "w") as f:
|
|
153
|
+
json.dump(new_tokens, f)
|
|
154
|
+
|
|
155
|
+
connector = GoogleDriveConnector(
|
|
156
|
+
auth_config=GoogleDriveAuthConfig(access_token="...", refresh_token="..."),
|
|
157
|
+
on_token_refresh=save_tokens
|
|
158
|
+
)
|
|
159
|
+
"""
|
|
160
|
+
# Hosted mode: external_user_id, airbyte_client_id, and airbyte_client_secret provided
|
|
161
|
+
if external_user_id and airbyte_client_id and airbyte_client_secret:
|
|
162
|
+
from ._vendored.connector_sdk.executor import HostedExecutor
|
|
163
|
+
self._executor = HostedExecutor(
|
|
164
|
+
external_user_id=external_user_id,
|
|
165
|
+
airbyte_client_id=airbyte_client_id,
|
|
166
|
+
airbyte_client_secret=airbyte_client_secret,
|
|
167
|
+
connector_definition_id=str(GoogleDriveConnectorModel.id),
|
|
168
|
+
)
|
|
169
|
+
else:
|
|
170
|
+
# Local mode: auth_config required
|
|
171
|
+
if not auth_config:
|
|
172
|
+
raise ValueError(
|
|
173
|
+
"Either provide (external_user_id, airbyte_client_id, airbyte_client_secret) for hosted mode "
|
|
174
|
+
"or auth_config for local mode"
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
from ._vendored.connector_sdk.executor import LocalExecutor
|
|
178
|
+
|
|
179
|
+
# Build config_values dict from server variables
|
|
180
|
+
config_values = None
|
|
181
|
+
|
|
182
|
+
self._executor = LocalExecutor(
|
|
183
|
+
model=GoogleDriveConnectorModel,
|
|
184
|
+
auth_config=auth_config.model_dump() if auth_config else None,
|
|
185
|
+
config_values=config_values,
|
|
186
|
+
on_token_refresh=on_token_refresh
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Update base_url with server variables if provided
|
|
190
|
+
|
|
191
|
+
# Initialize entity query objects
|
|
192
|
+
self.files = FilesQuery(self)
|
|
193
|
+
self.files_export = FilesExportQuery(self)
|
|
194
|
+
self.drives = DrivesQuery(self)
|
|
195
|
+
self.permissions = PermissionsQuery(self)
|
|
196
|
+
self.comments = CommentsQuery(self)
|
|
197
|
+
self.replies = RepliesQuery(self)
|
|
198
|
+
self.revisions = RevisionsQuery(self)
|
|
199
|
+
self.changes = ChangesQuery(self)
|
|
200
|
+
self.changes_start_page_token = ChangesStartPageTokenQuery(self)
|
|
201
|
+
self.about = AboutQuery(self)
|
|
202
|
+
|
|
203
|
+
# ===== TYPED EXECUTE METHOD (Recommended Interface) =====
|
|
204
|
+
|
|
205
|
+
@overload
|
|
206
|
+
async def execute(
|
|
207
|
+
self,
|
|
208
|
+
entity: Literal["files"],
|
|
209
|
+
action: Literal["list"],
|
|
210
|
+
params: "FilesListParams"
|
|
211
|
+
) -> "FilesListResult": ...
|
|
212
|
+
|
|
213
|
+
@overload
|
|
214
|
+
async def execute(
|
|
215
|
+
self,
|
|
216
|
+
entity: Literal["files"],
|
|
217
|
+
action: Literal["get"],
|
|
218
|
+
params: "FilesGetParams"
|
|
219
|
+
) -> "File": ...
|
|
220
|
+
|
|
221
|
+
@overload
|
|
222
|
+
async def execute(
|
|
223
|
+
self,
|
|
224
|
+
entity: Literal["files"],
|
|
225
|
+
action: Literal["download"],
|
|
226
|
+
params: "FilesDownloadParams"
|
|
227
|
+
) -> "AsyncIterator[bytes]": ...
|
|
228
|
+
|
|
229
|
+
@overload
|
|
230
|
+
async def execute(
|
|
231
|
+
self,
|
|
232
|
+
entity: Literal["files_export"],
|
|
233
|
+
action: Literal["download"],
|
|
234
|
+
params: "FilesExportDownloadParams"
|
|
235
|
+
) -> "AsyncIterator[bytes]": ...
|
|
236
|
+
|
|
237
|
+
@overload
|
|
238
|
+
async def execute(
|
|
239
|
+
self,
|
|
240
|
+
entity: Literal["drives"],
|
|
241
|
+
action: Literal["list"],
|
|
242
|
+
params: "DrivesListParams"
|
|
243
|
+
) -> "DrivesListResult": ...
|
|
244
|
+
|
|
245
|
+
@overload
|
|
246
|
+
async def execute(
|
|
247
|
+
self,
|
|
248
|
+
entity: Literal["drives"],
|
|
249
|
+
action: Literal["get"],
|
|
250
|
+
params: "DrivesGetParams"
|
|
251
|
+
) -> "Drive": ...
|
|
252
|
+
|
|
253
|
+
@overload
|
|
254
|
+
async def execute(
|
|
255
|
+
self,
|
|
256
|
+
entity: Literal["permissions"],
|
|
257
|
+
action: Literal["list"],
|
|
258
|
+
params: "PermissionsListParams"
|
|
259
|
+
) -> "PermissionsListResult": ...
|
|
260
|
+
|
|
261
|
+
@overload
|
|
262
|
+
async def execute(
|
|
263
|
+
self,
|
|
264
|
+
entity: Literal["permissions"],
|
|
265
|
+
action: Literal["get"],
|
|
266
|
+
params: "PermissionsGetParams"
|
|
267
|
+
) -> "Permission": ...
|
|
268
|
+
|
|
269
|
+
@overload
|
|
270
|
+
async def execute(
|
|
271
|
+
self,
|
|
272
|
+
entity: Literal["comments"],
|
|
273
|
+
action: Literal["list"],
|
|
274
|
+
params: "CommentsListParams"
|
|
275
|
+
) -> "CommentsListResult": ...
|
|
276
|
+
|
|
277
|
+
@overload
|
|
278
|
+
async def execute(
|
|
279
|
+
self,
|
|
280
|
+
entity: Literal["comments"],
|
|
281
|
+
action: Literal["get"],
|
|
282
|
+
params: "CommentsGetParams"
|
|
283
|
+
) -> "Comment": ...
|
|
284
|
+
|
|
285
|
+
@overload
|
|
286
|
+
async def execute(
|
|
287
|
+
self,
|
|
288
|
+
entity: Literal["replies"],
|
|
289
|
+
action: Literal["list"],
|
|
290
|
+
params: "RepliesListParams"
|
|
291
|
+
) -> "RepliesListResult": ...
|
|
292
|
+
|
|
293
|
+
@overload
|
|
294
|
+
async def execute(
|
|
295
|
+
self,
|
|
296
|
+
entity: Literal["replies"],
|
|
297
|
+
action: Literal["get"],
|
|
298
|
+
params: "RepliesGetParams"
|
|
299
|
+
) -> "Reply": ...
|
|
300
|
+
|
|
301
|
+
@overload
|
|
302
|
+
async def execute(
|
|
303
|
+
self,
|
|
304
|
+
entity: Literal["revisions"],
|
|
305
|
+
action: Literal["list"],
|
|
306
|
+
params: "RevisionsListParams"
|
|
307
|
+
) -> "RevisionsListResult": ...
|
|
308
|
+
|
|
309
|
+
@overload
|
|
310
|
+
async def execute(
|
|
311
|
+
self,
|
|
312
|
+
entity: Literal["revisions"],
|
|
313
|
+
action: Literal["get"],
|
|
314
|
+
params: "RevisionsGetParams"
|
|
315
|
+
) -> "Revision": ...
|
|
316
|
+
|
|
317
|
+
@overload
|
|
318
|
+
async def execute(
|
|
319
|
+
self,
|
|
320
|
+
entity: Literal["changes"],
|
|
321
|
+
action: Literal["list"],
|
|
322
|
+
params: "ChangesListParams"
|
|
323
|
+
) -> "ChangesListResult": ...
|
|
324
|
+
|
|
325
|
+
@overload
|
|
326
|
+
async def execute(
|
|
327
|
+
self,
|
|
328
|
+
entity: Literal["changes_start_page_token"],
|
|
329
|
+
action: Literal["get"],
|
|
330
|
+
params: "ChangesStartPageTokenGetParams"
|
|
331
|
+
) -> "StartPageToken": ...
|
|
332
|
+
|
|
333
|
+
@overload
|
|
334
|
+
async def execute(
|
|
335
|
+
self,
|
|
336
|
+
entity: Literal["about"],
|
|
337
|
+
action: Literal["get"],
|
|
338
|
+
params: "AboutGetParams"
|
|
339
|
+
) -> "About": ...
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@overload
|
|
343
|
+
async def execute(
|
|
344
|
+
self,
|
|
345
|
+
entity: str,
|
|
346
|
+
action: str,
|
|
347
|
+
params: dict[str, Any]
|
|
348
|
+
) -> GoogleDriveExecuteResult[Any] | GoogleDriveExecuteResultWithMeta[Any, Any] | Any: ...
|
|
349
|
+
|
|
350
|
+
async def execute(
|
|
351
|
+
self,
|
|
352
|
+
entity: str,
|
|
353
|
+
action: str,
|
|
354
|
+
params: dict[str, Any] | None = None
|
|
355
|
+
) -> Any:
|
|
356
|
+
"""
|
|
357
|
+
Execute an entity operation with full type safety.
|
|
358
|
+
|
|
359
|
+
This is the recommended interface for blessed connectors as it:
|
|
360
|
+
- Uses the same signature as non-blessed connectors
|
|
361
|
+
- Provides full IDE autocomplete for entity/action/params
|
|
362
|
+
- Makes migration from generic to blessed connectors seamless
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
entity: Entity name (e.g., "customers")
|
|
366
|
+
action: Operation action (e.g., "create", "get", "list")
|
|
367
|
+
params: Operation parameters (typed based on entity+action)
|
|
368
|
+
|
|
369
|
+
Returns:
|
|
370
|
+
Typed response based on the operation
|
|
371
|
+
|
|
372
|
+
Example:
|
|
373
|
+
customer = await connector.execute(
|
|
374
|
+
entity="customers",
|
|
375
|
+
action="get",
|
|
376
|
+
params={"id": "cus_123"}
|
|
377
|
+
)
|
|
378
|
+
"""
|
|
379
|
+
from ._vendored.connector_sdk.executor import ExecutionConfig
|
|
380
|
+
|
|
381
|
+
# Remap parameter names from snake_case (TypedDict keys) to API parameter names
|
|
382
|
+
if params:
|
|
383
|
+
param_map = self._PARAM_MAP.get((entity, action), {})
|
|
384
|
+
if param_map:
|
|
385
|
+
params = {param_map.get(k, k): v for k, v in params.items()}
|
|
386
|
+
|
|
387
|
+
# Use ExecutionConfig for both local and hosted executors
|
|
388
|
+
config = ExecutionConfig(
|
|
389
|
+
entity=entity,
|
|
390
|
+
action=action,
|
|
391
|
+
params=params
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
result = await self._executor.execute(config)
|
|
395
|
+
|
|
396
|
+
if not result.success:
|
|
397
|
+
raise RuntimeError(f"Execution failed: {result.error}")
|
|
398
|
+
|
|
399
|
+
# Check if this operation has extractors configured
|
|
400
|
+
has_extractors = self._ENVELOPE_MAP.get((entity, action), False)
|
|
401
|
+
|
|
402
|
+
if has_extractors:
|
|
403
|
+
# With extractors - return Pydantic envelope with data and meta
|
|
404
|
+
if result.meta is not None:
|
|
405
|
+
return GoogleDriveExecuteResultWithMeta[Any, Any](
|
|
406
|
+
data=result.data,
|
|
407
|
+
meta=result.meta
|
|
408
|
+
)
|
|
409
|
+
else:
|
|
410
|
+
return GoogleDriveExecuteResult[Any](data=result.data)
|
|
411
|
+
else:
|
|
412
|
+
# No extractors - return raw response data
|
|
413
|
+
return result.data
|
|
414
|
+
|
|
415
|
+
# ===== INTROSPECTION METHODS =====
|
|
416
|
+
|
|
417
|
+
@classmethod
|
|
418
|
+
def describe(cls, func: _F) -> _F:
|
|
419
|
+
"""
|
|
420
|
+
Decorator that populates a function's docstring with connector capabilities.
|
|
421
|
+
|
|
422
|
+
This class method can be used as a decorator to automatically generate
|
|
423
|
+
comprehensive documentation for AI tool functions.
|
|
424
|
+
|
|
425
|
+
Usage:
|
|
426
|
+
@mcp.tool()
|
|
427
|
+
@GoogleDriveConnector.describe
|
|
428
|
+
async def execute(entity: str, action: str, params: dict):
|
|
429
|
+
'''Execute operations.'''
|
|
430
|
+
...
|
|
431
|
+
|
|
432
|
+
The decorated function's __doc__ will be updated with:
|
|
433
|
+
- Available entities and their actions
|
|
434
|
+
- Parameter signatures with required (*) and optional (?) markers
|
|
435
|
+
- Response structure documentation
|
|
436
|
+
- Example questions (if available in OpenAPI spec)
|
|
437
|
+
|
|
438
|
+
Args:
|
|
439
|
+
func: The function to decorate
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
The same function with updated __doc__
|
|
443
|
+
"""
|
|
444
|
+
description = generate_tool_description(GoogleDriveConnectorModel)
|
|
445
|
+
|
|
446
|
+
original_doc = func.__doc__ or ""
|
|
447
|
+
if original_doc.strip():
|
|
448
|
+
func.__doc__ = f"{original_doc.strip()}\n{description}"
|
|
449
|
+
else:
|
|
450
|
+
func.__doc__ = description
|
|
451
|
+
|
|
452
|
+
return func
|
|
453
|
+
|
|
454
|
+
def list_entities(self) -> list[dict[str, Any]]:
|
|
455
|
+
"""
|
|
456
|
+
Get structured data about available entities, actions, and parameters.
|
|
457
|
+
|
|
458
|
+
Returns a list of entity descriptions with:
|
|
459
|
+
- entity_name: Name of the entity (e.g., "contacts", "deals")
|
|
460
|
+
- description: Entity description from the first endpoint
|
|
461
|
+
- available_actions: List of actions (e.g., ["list", "get", "create"])
|
|
462
|
+
- parameters: Dict mapping action -> list of parameter dicts
|
|
463
|
+
|
|
464
|
+
Example:
|
|
465
|
+
entities = connector.list_entities()
|
|
466
|
+
for entity in entities:
|
|
467
|
+
print(f"{entity['entity_name']}: {entity['available_actions']}")
|
|
468
|
+
"""
|
|
469
|
+
return describe_entities(GoogleDriveConnectorModel)
|
|
470
|
+
|
|
471
|
+
def entity_schema(self, entity: str) -> dict[str, Any] | None:
|
|
472
|
+
"""
|
|
473
|
+
Get the JSON schema for an entity.
|
|
474
|
+
|
|
475
|
+
Args:
|
|
476
|
+
entity: Entity name (e.g., "contacts", "companies")
|
|
477
|
+
|
|
478
|
+
Returns:
|
|
479
|
+
JSON schema dict describing the entity structure, or None if not found.
|
|
480
|
+
|
|
481
|
+
Example:
|
|
482
|
+
schema = connector.entity_schema("contacts")
|
|
483
|
+
if schema:
|
|
484
|
+
print(f"Contact properties: {list(schema.get('properties', {}).keys())}")
|
|
485
|
+
"""
|
|
486
|
+
entity_def = next(
|
|
487
|
+
(e for e in GoogleDriveConnectorModel.entities if e.name == entity),
|
|
488
|
+
None
|
|
489
|
+
)
|
|
490
|
+
if entity_def is None:
|
|
491
|
+
logging.getLogger(__name__).warning(
|
|
492
|
+
f"Entity '{entity}' not found. Available entities: "
|
|
493
|
+
f"{[e.name for e in GoogleDriveConnectorModel.entities]}"
|
|
494
|
+
)
|
|
495
|
+
return entity_def.entity_schema if entity_def else None
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
class FilesQuery:
|
|
500
|
+
"""
|
|
501
|
+
Query class for Files entity operations.
|
|
502
|
+
"""
|
|
503
|
+
|
|
504
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
505
|
+
"""Initialize query with connector reference."""
|
|
506
|
+
self._connector = connector
|
|
507
|
+
|
|
508
|
+
async def list(
|
|
509
|
+
self,
|
|
510
|
+
page_size: int | None = None,
|
|
511
|
+
page_token: str | None = None,
|
|
512
|
+
q: str | None = None,
|
|
513
|
+
order_by: str | None = None,
|
|
514
|
+
fields: str | None = None,
|
|
515
|
+
spaces: str | None = None,
|
|
516
|
+
corpora: str | None = None,
|
|
517
|
+
drive_id: str | None = None,
|
|
518
|
+
include_items_from_all_drives: bool | None = None,
|
|
519
|
+
supports_all_drives: bool | None = None,
|
|
520
|
+
**kwargs
|
|
521
|
+
) -> FilesListResult:
|
|
522
|
+
"""
|
|
523
|
+
Lists the user's files. Returns a paginated list of files.
|
|
524
|
+
|
|
525
|
+
Args:
|
|
526
|
+
page_size: Maximum number of files to return per page (1-1000)
|
|
527
|
+
page_token: Token for continuing a previous list request
|
|
528
|
+
q: Query string for searching files
|
|
529
|
+
order_by: Sort order (e.g., 'modifiedTime desc', 'name')
|
|
530
|
+
fields: Fields to include in the response
|
|
531
|
+
spaces: Comma-separated list of spaces to query (drive, appDataFolder)
|
|
532
|
+
corpora: Bodies of items to search (user, drive, allDrives)
|
|
533
|
+
drive_id: ID of the shared drive to search
|
|
534
|
+
include_items_from_all_drives: Whether to include items from all drives
|
|
535
|
+
supports_all_drives: Whether the requesting application supports both My Drives and shared drives
|
|
536
|
+
**kwargs: Additional parameters
|
|
537
|
+
|
|
538
|
+
Returns:
|
|
539
|
+
FilesListResult
|
|
540
|
+
"""
|
|
541
|
+
params = {k: v for k, v in {
|
|
542
|
+
"pageSize": page_size,
|
|
543
|
+
"pageToken": page_token,
|
|
544
|
+
"q": q,
|
|
545
|
+
"orderBy": order_by,
|
|
546
|
+
"fields": fields,
|
|
547
|
+
"spaces": spaces,
|
|
548
|
+
"corpora": corpora,
|
|
549
|
+
"driveId": drive_id,
|
|
550
|
+
"includeItemsFromAllDrives": include_items_from_all_drives,
|
|
551
|
+
"supportsAllDrives": supports_all_drives,
|
|
552
|
+
**kwargs
|
|
553
|
+
}.items() if v is not None}
|
|
554
|
+
|
|
555
|
+
result = await self._connector.execute("files", "list", params)
|
|
556
|
+
# Cast generic envelope to concrete typed result
|
|
557
|
+
return FilesListResult(
|
|
558
|
+
data=result.data,
|
|
559
|
+
meta=result.meta
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
async def get(
|
|
565
|
+
self,
|
|
566
|
+
file_id: str,
|
|
567
|
+
fields: str | None = None,
|
|
568
|
+
supports_all_drives: bool | None = None,
|
|
569
|
+
**kwargs
|
|
570
|
+
) -> File:
|
|
571
|
+
"""
|
|
572
|
+
Gets a file's metadata by ID
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
file_id: The ID of the file
|
|
576
|
+
fields: Fields to include in the response
|
|
577
|
+
supports_all_drives: Whether the requesting application supports both My Drives and shared drives
|
|
578
|
+
**kwargs: Additional parameters
|
|
579
|
+
|
|
580
|
+
Returns:
|
|
581
|
+
File
|
|
582
|
+
"""
|
|
583
|
+
params = {k: v for k, v in {
|
|
584
|
+
"fileId": file_id,
|
|
585
|
+
"fields": fields,
|
|
586
|
+
"supportsAllDrives": supports_all_drives,
|
|
587
|
+
**kwargs
|
|
588
|
+
}.items() if v is not None}
|
|
589
|
+
|
|
590
|
+
result = await self._connector.execute("files", "get", params)
|
|
591
|
+
return result
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
async def download(
|
|
596
|
+
self,
|
|
597
|
+
file_id: str,
|
|
598
|
+
alt: str,
|
|
599
|
+
acknowledge_abuse: bool | None = None,
|
|
600
|
+
supports_all_drives: bool | None = None,
|
|
601
|
+
range_header: str | None = None,
|
|
602
|
+
**kwargs
|
|
603
|
+
) -> AsyncIterator[bytes]:
|
|
604
|
+
"""
|
|
605
|
+
Downloads the binary content of a file. This works for non-Google Workspace files
|
|
606
|
+
(PDFs, images, zip files, etc.). For Google Docs, Sheets, Slides, or Drawings,
|
|
607
|
+
use the export action instead.
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
Args:
|
|
611
|
+
file_id: The ID of the file to download
|
|
612
|
+
alt: Must be set to 'media' to download file content
|
|
613
|
+
acknowledge_abuse: Whether the user is acknowledging the risk of downloading known malware or other abusive files
|
|
614
|
+
supports_all_drives: Whether the requesting application supports both My Drives and shared drives
|
|
615
|
+
range_header: Optional Range header for partial downloads (e.g., 'bytes=0-99')
|
|
616
|
+
**kwargs: Additional parameters
|
|
617
|
+
|
|
618
|
+
Returns:
|
|
619
|
+
AsyncIterator[bytes]
|
|
620
|
+
"""
|
|
621
|
+
params = {k: v for k, v in {
|
|
622
|
+
"fileId": file_id,
|
|
623
|
+
"alt": alt,
|
|
624
|
+
"acknowledgeAbuse": acknowledge_abuse,
|
|
625
|
+
"supportsAllDrives": supports_all_drives,
|
|
626
|
+
"range_header": range_header,
|
|
627
|
+
**kwargs
|
|
628
|
+
}.items() if v is not None}
|
|
629
|
+
|
|
630
|
+
result = await self._connector.execute("files", "download", params)
|
|
631
|
+
return result
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
async def download_local(
|
|
635
|
+
self,
|
|
636
|
+
fileId: str,
|
|
637
|
+
alt: str,
|
|
638
|
+
path: str,
|
|
639
|
+
acknowledgeAbuse: bool | None = None,
|
|
640
|
+
supportsAllDrives: bool | None = None,
|
|
641
|
+
range_header: str | None = None,
|
|
642
|
+
**kwargs
|
|
643
|
+
) -> Path:
|
|
644
|
+
"""
|
|
645
|
+
Downloads the binary content of a file. This works for non-Google Workspace files
|
|
646
|
+
(PDFs, images, zip files, etc.). For Google Docs, Sheets, Slides, or Drawings,
|
|
647
|
+
use the export action instead.
|
|
648
|
+
and save to file.
|
|
649
|
+
|
|
650
|
+
Args:
|
|
651
|
+
fileId: The ID of the file to download
|
|
652
|
+
alt: Must be set to 'media' to download file content
|
|
653
|
+
acknowledgeAbuse: Whether the user is acknowledging the risk of downloading known malware or other abusive files
|
|
654
|
+
supportsAllDrives: Whether the requesting application supports both My Drives and shared drives
|
|
655
|
+
range_header: Optional Range header for partial downloads (e.g., 'bytes=0-99')
|
|
656
|
+
path: File path to save downloaded content
|
|
657
|
+
**kwargs: Additional parameters
|
|
658
|
+
|
|
659
|
+
Returns:
|
|
660
|
+
str: Path to the downloaded file
|
|
661
|
+
"""
|
|
662
|
+
from ._vendored.connector_sdk import save_download
|
|
663
|
+
|
|
664
|
+
# Get the async iterator
|
|
665
|
+
content_iterator = await self.download(
|
|
666
|
+
fileId=fileId,
|
|
667
|
+
alt=alt,
|
|
668
|
+
acknowledgeAbuse=acknowledgeAbuse,
|
|
669
|
+
supportsAllDrives=supportsAllDrives,
|
|
670
|
+
range_header=range_header,
|
|
671
|
+
**kwargs
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
return await save_download(content_iterator, path)
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
class FilesExportQuery:
|
|
678
|
+
"""
|
|
679
|
+
Query class for FilesExport entity operations.
|
|
680
|
+
"""
|
|
681
|
+
|
|
682
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
683
|
+
"""Initialize query with connector reference."""
|
|
684
|
+
self._connector = connector
|
|
685
|
+
|
|
686
|
+
async def download(
|
|
687
|
+
self,
|
|
688
|
+
file_id: str,
|
|
689
|
+
mime_type: str,
|
|
690
|
+
range_header: str | None = None,
|
|
691
|
+
**kwargs
|
|
692
|
+
) -> AsyncIterator[bytes]:
|
|
693
|
+
"""
|
|
694
|
+
Exports a Google Workspace file (Docs, Sheets, Slides, Drawings) to a specified format.
|
|
695
|
+
Common export formats:
|
|
696
|
+
- application/pdf (all types)
|
|
697
|
+
- text/plain (Docs)
|
|
698
|
+
- text/csv (Sheets)
|
|
699
|
+
- application/vnd.openxmlformats-officedocument.wordprocessingml.document (Docs to .docx)
|
|
700
|
+
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (Sheets to .xlsx)
|
|
701
|
+
- application/vnd.openxmlformats-officedocument.presentationml.presentation (Slides to .pptx)
|
|
702
|
+
Note: Export has a 10MB limit. For larger files, use the Drive UI.
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
Args:
|
|
706
|
+
file_id: The ID of the Google Workspace file to export
|
|
707
|
+
mime_type: The MIME type of the format to export to. Common values:
|
|
708
|
+
- application/pdf
|
|
709
|
+
- text/plain
|
|
710
|
+
- text/csv
|
|
711
|
+
- application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
|
712
|
+
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
|
713
|
+
- application/vnd.openxmlformats-officedocument.presentationml.presentation
|
|
714
|
+
|
|
715
|
+
range_header: Optional Range header for partial downloads (e.g., 'bytes=0-99')
|
|
716
|
+
**kwargs: Additional parameters
|
|
717
|
+
|
|
718
|
+
Returns:
|
|
719
|
+
AsyncIterator[bytes]
|
|
720
|
+
"""
|
|
721
|
+
params = {k: v for k, v in {
|
|
722
|
+
"fileId": file_id,
|
|
723
|
+
"mimeType": mime_type,
|
|
724
|
+
"range_header": range_header,
|
|
725
|
+
**kwargs
|
|
726
|
+
}.items() if v is not None}
|
|
727
|
+
|
|
728
|
+
result = await self._connector.execute("files_export", "download", params)
|
|
729
|
+
return result
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
async def download_local(
|
|
733
|
+
self,
|
|
734
|
+
fileId: str,
|
|
735
|
+
mimeType: str,
|
|
736
|
+
path: str,
|
|
737
|
+
range_header: str | None = None,
|
|
738
|
+
**kwargs
|
|
739
|
+
) -> Path:
|
|
740
|
+
"""
|
|
741
|
+
Exports a Google Workspace file (Docs, Sheets, Slides, Drawings) to a specified format.
|
|
742
|
+
Common export formats:
|
|
743
|
+
- application/pdf (all types)
|
|
744
|
+
- text/plain (Docs)
|
|
745
|
+
- text/csv (Sheets)
|
|
746
|
+
- application/vnd.openxmlformats-officedocument.wordprocessingml.document (Docs to .docx)
|
|
747
|
+
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (Sheets to .xlsx)
|
|
748
|
+
- application/vnd.openxmlformats-officedocument.presentationml.presentation (Slides to .pptx)
|
|
749
|
+
Note: Export has a 10MB limit. For larger files, use the Drive UI.
|
|
750
|
+
and save to file.
|
|
751
|
+
|
|
752
|
+
Args:
|
|
753
|
+
fileId: The ID of the Google Workspace file to export
|
|
754
|
+
mimeType: The MIME type of the format to export to. Common values:
|
|
755
|
+
- application/pdf
|
|
756
|
+
- text/plain
|
|
757
|
+
- text/csv
|
|
758
|
+
- application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
|
759
|
+
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
|
760
|
+
- application/vnd.openxmlformats-officedocument.presentationml.presentation
|
|
761
|
+
|
|
762
|
+
range_header: Optional Range header for partial downloads (e.g., 'bytes=0-99')
|
|
763
|
+
path: File path to save downloaded content
|
|
764
|
+
**kwargs: Additional parameters
|
|
765
|
+
|
|
766
|
+
Returns:
|
|
767
|
+
str: Path to the downloaded file
|
|
768
|
+
"""
|
|
769
|
+
from ._vendored.connector_sdk import save_download
|
|
770
|
+
|
|
771
|
+
# Get the async iterator
|
|
772
|
+
content_iterator = await self.download(
|
|
773
|
+
fileId=fileId,
|
|
774
|
+
mimeType=mimeType,
|
|
775
|
+
range_header=range_header,
|
|
776
|
+
**kwargs
|
|
777
|
+
)
|
|
778
|
+
|
|
779
|
+
return await save_download(content_iterator, path)
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
class DrivesQuery:
|
|
783
|
+
"""
|
|
784
|
+
Query class for Drives entity operations.
|
|
785
|
+
"""
|
|
786
|
+
|
|
787
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
788
|
+
"""Initialize query with connector reference."""
|
|
789
|
+
self._connector = connector
|
|
790
|
+
|
|
791
|
+
async def list(
|
|
792
|
+
self,
|
|
793
|
+
page_size: int | None = None,
|
|
794
|
+
page_token: str | None = None,
|
|
795
|
+
q: str | None = None,
|
|
796
|
+
use_domain_admin_access: bool | None = None,
|
|
797
|
+
**kwargs
|
|
798
|
+
) -> DrivesListResult:
|
|
799
|
+
"""
|
|
800
|
+
Lists the user's shared drives
|
|
801
|
+
|
|
802
|
+
Args:
|
|
803
|
+
page_size: Maximum number of shared drives to return (1-100)
|
|
804
|
+
page_token: Token for continuing a previous list request
|
|
805
|
+
q: Query string for searching shared drives
|
|
806
|
+
use_domain_admin_access: Issue the request as a domain administrator
|
|
807
|
+
**kwargs: Additional parameters
|
|
808
|
+
|
|
809
|
+
Returns:
|
|
810
|
+
DrivesListResult
|
|
811
|
+
"""
|
|
812
|
+
params = {k: v for k, v in {
|
|
813
|
+
"pageSize": page_size,
|
|
814
|
+
"pageToken": page_token,
|
|
815
|
+
"q": q,
|
|
816
|
+
"useDomainAdminAccess": use_domain_admin_access,
|
|
817
|
+
**kwargs
|
|
818
|
+
}.items() if v is not None}
|
|
819
|
+
|
|
820
|
+
result = await self._connector.execute("drives", "list", params)
|
|
821
|
+
# Cast generic envelope to concrete typed result
|
|
822
|
+
return DrivesListResult(
|
|
823
|
+
data=result.data,
|
|
824
|
+
meta=result.meta
|
|
825
|
+
)
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
async def get(
|
|
830
|
+
self,
|
|
831
|
+
drive_id: str,
|
|
832
|
+
use_domain_admin_access: bool | None = None,
|
|
833
|
+
**kwargs
|
|
834
|
+
) -> Drive:
|
|
835
|
+
"""
|
|
836
|
+
Gets a shared drive's metadata by ID
|
|
837
|
+
|
|
838
|
+
Args:
|
|
839
|
+
drive_id: The ID of the shared drive
|
|
840
|
+
use_domain_admin_access: Issue the request as a domain administrator
|
|
841
|
+
**kwargs: Additional parameters
|
|
842
|
+
|
|
843
|
+
Returns:
|
|
844
|
+
Drive
|
|
845
|
+
"""
|
|
846
|
+
params = {k: v for k, v in {
|
|
847
|
+
"driveId": drive_id,
|
|
848
|
+
"useDomainAdminAccess": use_domain_admin_access,
|
|
849
|
+
**kwargs
|
|
850
|
+
}.items() if v is not None}
|
|
851
|
+
|
|
852
|
+
result = await self._connector.execute("drives", "get", params)
|
|
853
|
+
return result
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
class PermissionsQuery:
|
|
858
|
+
"""
|
|
859
|
+
Query class for Permissions entity operations.
|
|
860
|
+
"""
|
|
861
|
+
|
|
862
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
863
|
+
"""Initialize query with connector reference."""
|
|
864
|
+
self._connector = connector
|
|
865
|
+
|
|
866
|
+
async def list(
|
|
867
|
+
self,
|
|
868
|
+
file_id: str,
|
|
869
|
+
page_size: int | None = None,
|
|
870
|
+
page_token: str | None = None,
|
|
871
|
+
supports_all_drives: bool | None = None,
|
|
872
|
+
use_domain_admin_access: bool | None = None,
|
|
873
|
+
**kwargs
|
|
874
|
+
) -> PermissionsListResult:
|
|
875
|
+
"""
|
|
876
|
+
Lists a file's or shared drive's permissions
|
|
877
|
+
|
|
878
|
+
Args:
|
|
879
|
+
file_id: The ID of the file or shared drive
|
|
880
|
+
page_size: Maximum number of permissions to return (1-100)
|
|
881
|
+
page_token: Token for continuing a previous list request
|
|
882
|
+
supports_all_drives: Whether the requesting application supports both My Drives and shared drives
|
|
883
|
+
use_domain_admin_access: Issue the request as a domain administrator
|
|
884
|
+
**kwargs: Additional parameters
|
|
885
|
+
|
|
886
|
+
Returns:
|
|
887
|
+
PermissionsListResult
|
|
888
|
+
"""
|
|
889
|
+
params = {k: v for k, v in {
|
|
890
|
+
"fileId": file_id,
|
|
891
|
+
"pageSize": page_size,
|
|
892
|
+
"pageToken": page_token,
|
|
893
|
+
"supportsAllDrives": supports_all_drives,
|
|
894
|
+
"useDomainAdminAccess": use_domain_admin_access,
|
|
895
|
+
**kwargs
|
|
896
|
+
}.items() if v is not None}
|
|
897
|
+
|
|
898
|
+
result = await self._connector.execute("permissions", "list", params)
|
|
899
|
+
# Cast generic envelope to concrete typed result
|
|
900
|
+
return PermissionsListResult(
|
|
901
|
+
data=result.data,
|
|
902
|
+
meta=result.meta
|
|
903
|
+
)
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
async def get(
|
|
908
|
+
self,
|
|
909
|
+
file_id: str,
|
|
910
|
+
permission_id: str,
|
|
911
|
+
supports_all_drives: bool | None = None,
|
|
912
|
+
use_domain_admin_access: bool | None = None,
|
|
913
|
+
**kwargs
|
|
914
|
+
) -> Permission:
|
|
915
|
+
"""
|
|
916
|
+
Gets a permission by ID
|
|
917
|
+
|
|
918
|
+
Args:
|
|
919
|
+
file_id: The ID of the file
|
|
920
|
+
permission_id: The ID of the permission
|
|
921
|
+
supports_all_drives: Whether the requesting application supports both My Drives and shared drives
|
|
922
|
+
use_domain_admin_access: Issue the request as a domain administrator
|
|
923
|
+
**kwargs: Additional parameters
|
|
924
|
+
|
|
925
|
+
Returns:
|
|
926
|
+
Permission
|
|
927
|
+
"""
|
|
928
|
+
params = {k: v for k, v in {
|
|
929
|
+
"fileId": file_id,
|
|
930
|
+
"permissionId": permission_id,
|
|
931
|
+
"supportsAllDrives": supports_all_drives,
|
|
932
|
+
"useDomainAdminAccess": use_domain_admin_access,
|
|
933
|
+
**kwargs
|
|
934
|
+
}.items() if v is not None}
|
|
935
|
+
|
|
936
|
+
result = await self._connector.execute("permissions", "get", params)
|
|
937
|
+
return result
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
class CommentsQuery:
|
|
942
|
+
"""
|
|
943
|
+
Query class for Comments entity operations.
|
|
944
|
+
"""
|
|
945
|
+
|
|
946
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
947
|
+
"""Initialize query with connector reference."""
|
|
948
|
+
self._connector = connector
|
|
949
|
+
|
|
950
|
+
async def list(
|
|
951
|
+
self,
|
|
952
|
+
file_id: str,
|
|
953
|
+
page_size: int | None = None,
|
|
954
|
+
page_token: str | None = None,
|
|
955
|
+
start_modified_time: str | None = None,
|
|
956
|
+
include_deleted: bool | None = None,
|
|
957
|
+
fields: str | None = None,
|
|
958
|
+
**kwargs
|
|
959
|
+
) -> CommentsListResult:
|
|
960
|
+
"""
|
|
961
|
+
Lists a file's comments
|
|
962
|
+
|
|
963
|
+
Args:
|
|
964
|
+
file_id: The ID of the file
|
|
965
|
+
page_size: Maximum number of comments to return (1-100)
|
|
966
|
+
page_token: Token for continuing a previous list request
|
|
967
|
+
start_modified_time: Minimum value of modifiedTime to filter by (RFC 3339)
|
|
968
|
+
include_deleted: Whether to include deleted comments
|
|
969
|
+
fields: Fields to include in the response (required for comments)
|
|
970
|
+
**kwargs: Additional parameters
|
|
971
|
+
|
|
972
|
+
Returns:
|
|
973
|
+
CommentsListResult
|
|
974
|
+
"""
|
|
975
|
+
params = {k: v for k, v in {
|
|
976
|
+
"fileId": file_id,
|
|
977
|
+
"pageSize": page_size,
|
|
978
|
+
"pageToken": page_token,
|
|
979
|
+
"startModifiedTime": start_modified_time,
|
|
980
|
+
"includeDeleted": include_deleted,
|
|
981
|
+
"fields": fields,
|
|
982
|
+
**kwargs
|
|
983
|
+
}.items() if v is not None}
|
|
984
|
+
|
|
985
|
+
result = await self._connector.execute("comments", "list", params)
|
|
986
|
+
# Cast generic envelope to concrete typed result
|
|
987
|
+
return CommentsListResult(
|
|
988
|
+
data=result.data,
|
|
989
|
+
meta=result.meta
|
|
990
|
+
)
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
async def get(
|
|
995
|
+
self,
|
|
996
|
+
file_id: str,
|
|
997
|
+
comment_id: str,
|
|
998
|
+
include_deleted: bool | None = None,
|
|
999
|
+
fields: str | None = None,
|
|
1000
|
+
**kwargs
|
|
1001
|
+
) -> Comment:
|
|
1002
|
+
"""
|
|
1003
|
+
Gets a comment by ID
|
|
1004
|
+
|
|
1005
|
+
Args:
|
|
1006
|
+
file_id: The ID of the file
|
|
1007
|
+
comment_id: The ID of the comment
|
|
1008
|
+
include_deleted: Whether to return deleted comments
|
|
1009
|
+
fields: Fields to include in the response (required for comments)
|
|
1010
|
+
**kwargs: Additional parameters
|
|
1011
|
+
|
|
1012
|
+
Returns:
|
|
1013
|
+
Comment
|
|
1014
|
+
"""
|
|
1015
|
+
params = {k: v for k, v in {
|
|
1016
|
+
"fileId": file_id,
|
|
1017
|
+
"commentId": comment_id,
|
|
1018
|
+
"includeDeleted": include_deleted,
|
|
1019
|
+
"fields": fields,
|
|
1020
|
+
**kwargs
|
|
1021
|
+
}.items() if v is not None}
|
|
1022
|
+
|
|
1023
|
+
result = await self._connector.execute("comments", "get", params)
|
|
1024
|
+
return result
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
class RepliesQuery:
|
|
1029
|
+
"""
|
|
1030
|
+
Query class for Replies entity operations.
|
|
1031
|
+
"""
|
|
1032
|
+
|
|
1033
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
1034
|
+
"""Initialize query with connector reference."""
|
|
1035
|
+
self._connector = connector
|
|
1036
|
+
|
|
1037
|
+
async def list(
|
|
1038
|
+
self,
|
|
1039
|
+
file_id: str,
|
|
1040
|
+
comment_id: str,
|
|
1041
|
+
page_size: int | None = None,
|
|
1042
|
+
page_token: str | None = None,
|
|
1043
|
+
include_deleted: bool | None = None,
|
|
1044
|
+
fields: str | None = None,
|
|
1045
|
+
**kwargs
|
|
1046
|
+
) -> RepliesListResult:
|
|
1047
|
+
"""
|
|
1048
|
+
Lists a comment's replies
|
|
1049
|
+
|
|
1050
|
+
Args:
|
|
1051
|
+
file_id: The ID of the file
|
|
1052
|
+
comment_id: The ID of the comment
|
|
1053
|
+
page_size: Maximum number of replies to return (1-100)
|
|
1054
|
+
page_token: Token for continuing a previous list request
|
|
1055
|
+
include_deleted: Whether to include deleted replies
|
|
1056
|
+
fields: Fields to include in the response (required for replies)
|
|
1057
|
+
**kwargs: Additional parameters
|
|
1058
|
+
|
|
1059
|
+
Returns:
|
|
1060
|
+
RepliesListResult
|
|
1061
|
+
"""
|
|
1062
|
+
params = {k: v for k, v in {
|
|
1063
|
+
"fileId": file_id,
|
|
1064
|
+
"commentId": comment_id,
|
|
1065
|
+
"pageSize": page_size,
|
|
1066
|
+
"pageToken": page_token,
|
|
1067
|
+
"includeDeleted": include_deleted,
|
|
1068
|
+
"fields": fields,
|
|
1069
|
+
**kwargs
|
|
1070
|
+
}.items() if v is not None}
|
|
1071
|
+
|
|
1072
|
+
result = await self._connector.execute("replies", "list", params)
|
|
1073
|
+
# Cast generic envelope to concrete typed result
|
|
1074
|
+
return RepliesListResult(
|
|
1075
|
+
data=result.data,
|
|
1076
|
+
meta=result.meta
|
|
1077
|
+
)
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
async def get(
|
|
1082
|
+
self,
|
|
1083
|
+
file_id: str,
|
|
1084
|
+
comment_id: str,
|
|
1085
|
+
reply_id: str,
|
|
1086
|
+
include_deleted: bool | None = None,
|
|
1087
|
+
fields: str | None = None,
|
|
1088
|
+
**kwargs
|
|
1089
|
+
) -> Reply:
|
|
1090
|
+
"""
|
|
1091
|
+
Gets a reply by ID
|
|
1092
|
+
|
|
1093
|
+
Args:
|
|
1094
|
+
file_id: The ID of the file
|
|
1095
|
+
comment_id: The ID of the comment
|
|
1096
|
+
reply_id: The ID of the reply
|
|
1097
|
+
include_deleted: Whether to return deleted replies
|
|
1098
|
+
fields: Fields to include in the response (required for replies)
|
|
1099
|
+
**kwargs: Additional parameters
|
|
1100
|
+
|
|
1101
|
+
Returns:
|
|
1102
|
+
Reply
|
|
1103
|
+
"""
|
|
1104
|
+
params = {k: v for k, v in {
|
|
1105
|
+
"fileId": file_id,
|
|
1106
|
+
"commentId": comment_id,
|
|
1107
|
+
"replyId": reply_id,
|
|
1108
|
+
"includeDeleted": include_deleted,
|
|
1109
|
+
"fields": fields,
|
|
1110
|
+
**kwargs
|
|
1111
|
+
}.items() if v is not None}
|
|
1112
|
+
|
|
1113
|
+
result = await self._connector.execute("replies", "get", params)
|
|
1114
|
+
return result
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
class RevisionsQuery:
|
|
1119
|
+
"""
|
|
1120
|
+
Query class for Revisions entity operations.
|
|
1121
|
+
"""
|
|
1122
|
+
|
|
1123
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
1124
|
+
"""Initialize query with connector reference."""
|
|
1125
|
+
self._connector = connector
|
|
1126
|
+
|
|
1127
|
+
async def list(
|
|
1128
|
+
self,
|
|
1129
|
+
file_id: str,
|
|
1130
|
+
page_size: int | None = None,
|
|
1131
|
+
page_token: str | None = None,
|
|
1132
|
+
**kwargs
|
|
1133
|
+
) -> RevisionsListResult:
|
|
1134
|
+
"""
|
|
1135
|
+
Lists a file's revisions
|
|
1136
|
+
|
|
1137
|
+
Args:
|
|
1138
|
+
file_id: The ID of the file
|
|
1139
|
+
page_size: Maximum number of revisions to return (1-1000)
|
|
1140
|
+
page_token: Token for continuing a previous list request
|
|
1141
|
+
**kwargs: Additional parameters
|
|
1142
|
+
|
|
1143
|
+
Returns:
|
|
1144
|
+
RevisionsListResult
|
|
1145
|
+
"""
|
|
1146
|
+
params = {k: v for k, v in {
|
|
1147
|
+
"fileId": file_id,
|
|
1148
|
+
"pageSize": page_size,
|
|
1149
|
+
"pageToken": page_token,
|
|
1150
|
+
**kwargs
|
|
1151
|
+
}.items() if v is not None}
|
|
1152
|
+
|
|
1153
|
+
result = await self._connector.execute("revisions", "list", params)
|
|
1154
|
+
# Cast generic envelope to concrete typed result
|
|
1155
|
+
return RevisionsListResult(
|
|
1156
|
+
data=result.data,
|
|
1157
|
+
meta=result.meta
|
|
1158
|
+
)
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
async def get(
|
|
1163
|
+
self,
|
|
1164
|
+
file_id: str,
|
|
1165
|
+
revision_id: str,
|
|
1166
|
+
**kwargs
|
|
1167
|
+
) -> Revision:
|
|
1168
|
+
"""
|
|
1169
|
+
Gets a revision's metadata by ID
|
|
1170
|
+
|
|
1171
|
+
Args:
|
|
1172
|
+
file_id: The ID of the file
|
|
1173
|
+
revision_id: The ID of the revision
|
|
1174
|
+
**kwargs: Additional parameters
|
|
1175
|
+
|
|
1176
|
+
Returns:
|
|
1177
|
+
Revision
|
|
1178
|
+
"""
|
|
1179
|
+
params = {k: v for k, v in {
|
|
1180
|
+
"fileId": file_id,
|
|
1181
|
+
"revisionId": revision_id,
|
|
1182
|
+
**kwargs
|
|
1183
|
+
}.items() if v is not None}
|
|
1184
|
+
|
|
1185
|
+
result = await self._connector.execute("revisions", "get", params)
|
|
1186
|
+
return result
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
class ChangesQuery:
|
|
1191
|
+
"""
|
|
1192
|
+
Query class for Changes entity operations.
|
|
1193
|
+
"""
|
|
1194
|
+
|
|
1195
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
1196
|
+
"""Initialize query with connector reference."""
|
|
1197
|
+
self._connector = connector
|
|
1198
|
+
|
|
1199
|
+
async def list(
|
|
1200
|
+
self,
|
|
1201
|
+
page_token: str,
|
|
1202
|
+
page_size: int | None = None,
|
|
1203
|
+
drive_id: str | None = None,
|
|
1204
|
+
include_items_from_all_drives: bool | None = None,
|
|
1205
|
+
supports_all_drives: bool | None = None,
|
|
1206
|
+
spaces: str | None = None,
|
|
1207
|
+
include_removed: bool | None = None,
|
|
1208
|
+
restrict_to_my_drive: bool | None = None,
|
|
1209
|
+
**kwargs
|
|
1210
|
+
) -> ChangesListResult:
|
|
1211
|
+
"""
|
|
1212
|
+
Lists the changes for a user or shared drive
|
|
1213
|
+
|
|
1214
|
+
Args:
|
|
1215
|
+
page_token: Token for the page of changes to retrieve (from changes.getStartPageToken or previous response)
|
|
1216
|
+
page_size: Maximum number of changes to return (1-1000)
|
|
1217
|
+
drive_id: The shared drive from which changes are returned
|
|
1218
|
+
include_items_from_all_drives: Whether to include changes from all drives
|
|
1219
|
+
supports_all_drives: Whether the requesting application supports both My Drives and shared drives
|
|
1220
|
+
spaces: Comma-separated list of spaces to query
|
|
1221
|
+
include_removed: Whether to include changes indicating that items have been removed
|
|
1222
|
+
restrict_to_my_drive: Whether to restrict the results to changes inside the My Drive hierarchy
|
|
1223
|
+
**kwargs: Additional parameters
|
|
1224
|
+
|
|
1225
|
+
Returns:
|
|
1226
|
+
ChangesListResult
|
|
1227
|
+
"""
|
|
1228
|
+
params = {k: v for k, v in {
|
|
1229
|
+
"pageToken": page_token,
|
|
1230
|
+
"pageSize": page_size,
|
|
1231
|
+
"driveId": drive_id,
|
|
1232
|
+
"includeItemsFromAllDrives": include_items_from_all_drives,
|
|
1233
|
+
"supportsAllDrives": supports_all_drives,
|
|
1234
|
+
"spaces": spaces,
|
|
1235
|
+
"includeRemoved": include_removed,
|
|
1236
|
+
"restrictToMyDrive": restrict_to_my_drive,
|
|
1237
|
+
**kwargs
|
|
1238
|
+
}.items() if v is not None}
|
|
1239
|
+
|
|
1240
|
+
result = await self._connector.execute("changes", "list", params)
|
|
1241
|
+
# Cast generic envelope to concrete typed result
|
|
1242
|
+
return ChangesListResult(
|
|
1243
|
+
data=result.data,
|
|
1244
|
+
meta=result.meta
|
|
1245
|
+
)
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
class ChangesStartPageTokenQuery:
|
|
1250
|
+
"""
|
|
1251
|
+
Query class for ChangesStartPageToken entity operations.
|
|
1252
|
+
"""
|
|
1253
|
+
|
|
1254
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
1255
|
+
"""Initialize query with connector reference."""
|
|
1256
|
+
self._connector = connector
|
|
1257
|
+
|
|
1258
|
+
async def get(
|
|
1259
|
+
self,
|
|
1260
|
+
drive_id: str | None = None,
|
|
1261
|
+
supports_all_drives: bool | None = None,
|
|
1262
|
+
**kwargs
|
|
1263
|
+
) -> StartPageToken:
|
|
1264
|
+
"""
|
|
1265
|
+
Gets the starting pageToken for listing future changes
|
|
1266
|
+
|
|
1267
|
+
Args:
|
|
1268
|
+
drive_id: The ID of the shared drive for which the starting pageToken is returned
|
|
1269
|
+
supports_all_drives: Whether the requesting application supports both My Drives and shared drives
|
|
1270
|
+
**kwargs: Additional parameters
|
|
1271
|
+
|
|
1272
|
+
Returns:
|
|
1273
|
+
StartPageToken
|
|
1274
|
+
"""
|
|
1275
|
+
params = {k: v for k, v in {
|
|
1276
|
+
"driveId": drive_id,
|
|
1277
|
+
"supportsAllDrives": supports_all_drives,
|
|
1278
|
+
**kwargs
|
|
1279
|
+
}.items() if v is not None}
|
|
1280
|
+
|
|
1281
|
+
result = await self._connector.execute("changes_start_page_token", "get", params)
|
|
1282
|
+
return result
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
class AboutQuery:
|
|
1287
|
+
"""
|
|
1288
|
+
Query class for About entity operations.
|
|
1289
|
+
"""
|
|
1290
|
+
|
|
1291
|
+
def __init__(self, connector: GoogleDriveConnector):
|
|
1292
|
+
"""Initialize query with connector reference."""
|
|
1293
|
+
self._connector = connector
|
|
1294
|
+
|
|
1295
|
+
async def get(
|
|
1296
|
+
self,
|
|
1297
|
+
fields: str | None = None,
|
|
1298
|
+
**kwargs
|
|
1299
|
+
) -> About:
|
|
1300
|
+
"""
|
|
1301
|
+
Gets information about the user, the user's Drive, and system capabilities
|
|
1302
|
+
|
|
1303
|
+
Args:
|
|
1304
|
+
fields: Fields to include in the response (use * for all fields)
|
|
1305
|
+
**kwargs: Additional parameters
|
|
1306
|
+
|
|
1307
|
+
Returns:
|
|
1308
|
+
About
|
|
1309
|
+
"""
|
|
1310
|
+
params = {k: v for k, v in {
|
|
1311
|
+
"fields": fields,
|
|
1312
|
+
**kwargs
|
|
1313
|
+
}.items() if v is not None}
|
|
1314
|
+
|
|
1315
|
+
result = await self._connector.execute("about", "get", params)
|
|
1316
|
+
return result
|
|
1317
|
+
|
|
1318
|
+
|