google-api-client-wrapper 2.1.1__tar.gz → 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/PKG-INFO +32 -6
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/README.md +31 -4
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_api_client_wrapper.egg-info/PKG-INFO +32 -6
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_api_client_wrapper.egg-info/SOURCES.txt +16 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_api_client_wrapper.egg-info/requires.txt +0 -1
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/api_service.py +33 -2
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/auth.py +8 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/__init__.py +3 -1
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/api_service.py +86 -12
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/async_api_service.py +88 -11
- google_api_client_wrapper-3.0.0/google_client/services/docs/__init__.py +7 -0
- google_api_client_wrapper-3.0.0/google_client/services/docs/api_service.py +277 -0
- google_api_client_wrapper-3.0.0/google_client/services/docs/async_api_service.py +307 -0
- google_api_client_wrapper-3.0.0/google_client/services/docs/async_batch_updater.py +31 -0
- google_api_client_wrapper-3.0.0/google_client/services/docs/base_batch_updater.py +201 -0
- google_api_client_wrapper-3.0.0/google_client/services/docs/batch_updater.py +27 -0
- google_api_client_wrapper-3.0.0/google_client/services/docs/types.py +10 -0
- google_api_client_wrapper-3.0.0/google_client/services/docs/utils.py +53 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/api_service.py +233 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/async_api_service.py +255 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/constants.py +1 -1
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/api_service.py +210 -22
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/async_api_service.py +197 -18
- google_api_client_wrapper-3.0.0/google_client/services/sheets/__init__.py +14 -0
- google_api_client_wrapper-3.0.0/google_client/services/sheets/api_service.py +433 -0
- google_api_client_wrapper-3.0.0/google_client/services/sheets/async_api_service.py +301 -0
- google_api_client_wrapper-3.0.0/google_client/services/sheets/async_batch_updater.py +58 -0
- google_api_client_wrapper-3.0.0/google_client/services/sheets/base_batch_updater.py +447 -0
- google_api_client_wrapper-3.0.0/google_client/services/sheets/batch_updater.py +47 -0
- google_api_client_wrapper-3.0.0/google_client/services/sheets/types.py +154 -0
- google_api_client_wrapper-3.0.0/google_client/services/sheets/utils.py +43 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/api_service.py +147 -2
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/async_api_service.py +132 -10
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/pyproject.toml +1 -2
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/LICENSE +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_api_client_wrapper.egg-info/dependency_links.txt +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_api_client_wrapper.egg-info/top_level.txt +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/__init__.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/__init__.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/async_query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/constants.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/types.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/calendar/utils.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/__init__.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/async_query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/exceptions.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/types.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/drive/utils.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/__init__.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/async_query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/constants.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/types.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/gmail/utils.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/__init__.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/async_query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/constants.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/query_builder.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/types.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/services/tasks/utils.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/utils/__init__.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/utils/datetime.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/utils/validation.py +0 -0
- {google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: google-api-client-wrapper
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: A comprehensive Python wrapper for Google APIs with async support, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, and Google Tasks services.
|
|
5
5
|
Author-email: Dagmawi Molla <dagmawishewadeg@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -46,12 +46,11 @@ Requires-Dist: html2text>=2025.4.15
|
|
|
46
46
|
Requires-Dist: pydantic>=2.11.7
|
|
47
47
|
Requires-Dist: aiohttp>=3.9.0
|
|
48
48
|
Requires-Dist: aiofiles>=23.0.0
|
|
49
|
-
Requires-Dist: aiogoogle>=5.15.0
|
|
50
49
|
Dynamic: license-file
|
|
51
50
|
|
|
52
51
|
# Google API Client Wrapper
|
|
53
52
|
|
|
54
|
-
A comprehensive Python wrapper for Google APIs, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, and Google
|
|
53
|
+
A comprehensive Python wrapper for Google APIs, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, Google Tasks, Google Docs, and Google Sheets services with both synchronous and asynchronous implementations.
|
|
55
54
|
|
|
56
55
|
## Installation
|
|
57
56
|
|
|
@@ -71,6 +70,8 @@ pip install git+https://github.com/dsmolla/google-api-client-wrapper.git
|
|
|
71
70
|
- **Google Drive Service**: Upload, download, and manage files and folders
|
|
72
71
|
- **Google Calendar Service**: Create, update, and manage calendar events
|
|
73
72
|
- **Google Tasks Service**: Manage tasks and task lists
|
|
73
|
+
- **Google Sheets Service**: Read, write, format, and batch-mutate spreadsheets
|
|
74
|
+
- **Google Docs Service**: Create, read, and perform complex batch formatting and structural mutations on Google Documents
|
|
74
75
|
- **Async Support**: Full async/await support for all services with concurrent batch operations
|
|
75
76
|
- **OAuth2 Authentication**: Secure authentication flow with token management
|
|
76
77
|
- **Query Builders**: Intuitive query building for each service
|
|
@@ -97,13 +98,13 @@ oauth_manager = GoogleOAuthManager(
|
|
|
97
98
|
|
|
98
99
|
# Generate authorization URL
|
|
99
100
|
auth_url, state = oauth_manager.generate_auth_url(
|
|
100
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
101
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
101
102
|
)
|
|
102
103
|
|
|
103
104
|
# After user authorizes, exchange code for tokens
|
|
104
105
|
user_info = oauth_manager.complete_auth_flow(
|
|
105
106
|
code='authorization_code_from_callback',
|
|
106
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
107
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
107
108
|
)
|
|
108
109
|
|
|
109
110
|
# Save user_info for future use
|
|
@@ -130,7 +131,7 @@ oauth_manager = GoogleOAuthManager(
|
|
|
130
131
|
|
|
131
132
|
# Authenticate using local server - browser opens automatically!
|
|
132
133
|
user_info = oauth_manager.authenticate_via_local_server(
|
|
133
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
134
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
134
135
|
)
|
|
135
136
|
|
|
136
137
|
# Save credentials
|
|
@@ -185,6 +186,16 @@ event = calendar.create_event(
|
|
|
185
186
|
# Access Tasks service
|
|
186
187
|
tasks = api_service.tasks
|
|
187
188
|
task = tasks.create_task(title="Review documents")
|
|
189
|
+
|
|
190
|
+
# Access Sheets service
|
|
191
|
+
sheets = api_service.sheets
|
|
192
|
+
values = sheets.get_values(spreadsheet_id="your_spreadsheet_id", range_name="Sheet1!A1:B2")
|
|
193
|
+
sheets.append_values_from_dicts("your_spreadsheet_id", "Sheet1!A1", [{"Name": "Alice", "Role": "Admin"}])
|
|
194
|
+
|
|
195
|
+
# Access Docs service
|
|
196
|
+
docs = api_service.docs
|
|
197
|
+
new_doc = docs.create_document(title="Automated Report")
|
|
198
|
+
docs.insert_table_with_data(new_doc.document_id, index=1, data=[["Column 1", "Column 2"]])
|
|
188
199
|
```
|
|
189
200
|
|
|
190
201
|
### Using Services (Asynchronous)
|
|
@@ -227,6 +238,15 @@ async def main():
|
|
|
227
238
|
tasks = api_service.async_tasks
|
|
228
239
|
all_tasks = await tasks.list_tasks(show_completed=True)
|
|
229
240
|
|
|
241
|
+
# Access async Sheets service
|
|
242
|
+
sheets = api_service.async_sheets
|
|
243
|
+
values = await sheets.get_values(spreadsheet_id="your_spreadsheet_id", range_name="Sheet1!A1:B2")
|
|
244
|
+
|
|
245
|
+
# Access async Docs service
|
|
246
|
+
docs = api_service.async_docs
|
|
247
|
+
new_doc = await docs.create_document(title="Async Automated Report")
|
|
248
|
+
extracted_text = await docs.get_document_text(new_doc.document_id)
|
|
249
|
+
|
|
230
250
|
# Run async code
|
|
231
251
|
asyncio.run(main())
|
|
232
252
|
```
|
|
@@ -327,6 +347,8 @@ Each service has detailed documentation with examples and API reference:
|
|
|
327
347
|
- **[Google Drive Service](google_client/services/drive/README.md)** - File and folder management
|
|
328
348
|
- **[Google Calendar Service](google_client/services/calendar/README.md)** - Calendar and event management
|
|
329
349
|
- **[Google Tasks Service](google_client/services/tasks/README.md)** - Task and task list management
|
|
350
|
+
- **[Google Sheets Service](google_client/services/sheets/README.md)** - Advanced spreadsheet reading, writing, and batch mutation
|
|
351
|
+
- **[Google Docs Service](google_client/services/docs/README.md)** - Precise document creation, abstract-syntax-tree parsing, and nested structural formatting
|
|
330
352
|
|
|
331
353
|
## Available Scopes
|
|
332
354
|
|
|
@@ -337,6 +359,8 @@ Scopes.GMAIL # Full Gmail access
|
|
|
337
359
|
Scopes.DRIVE # Full Drive access
|
|
338
360
|
Scopes.CALENDAR # Full Calendar access
|
|
339
361
|
Scopes.TASKS # Full Tasks access
|
|
362
|
+
Scopes.SHEETS # Full Sheets access
|
|
363
|
+
Scopes.DOCS # Full Docs access
|
|
340
364
|
```
|
|
341
365
|
|
|
342
366
|
## Token Refresh
|
|
@@ -362,6 +386,8 @@ refreshed_token = api_service.refresh_token()
|
|
|
362
386
|
- **[Drive API Reference](https://developers.google.com/drive/api)**
|
|
363
387
|
- **[Calendar API Reference](https://developers.google.com/calendar/api)**
|
|
364
388
|
- **[Tasks API Reference](https://developers.google.com/tasks/reference/rest)**
|
|
389
|
+
- **[Sheets API Reference](https://developers.google.com/sheets/api/reference/rest)**
|
|
390
|
+
- **[Docs API Reference](https://developers.google.com/docs/api/reference/rest)**
|
|
365
391
|
|
|
366
392
|
---
|
|
367
393
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Google API Client Wrapper
|
|
2
2
|
|
|
3
|
-
A comprehensive Python wrapper for Google APIs, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, and Google
|
|
3
|
+
A comprehensive Python wrapper for Google APIs, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, Google Tasks, Google Docs, and Google Sheets services with both synchronous and asynchronous implementations.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -20,6 +20,8 @@ pip install git+https://github.com/dsmolla/google-api-client-wrapper.git
|
|
|
20
20
|
- **Google Drive Service**: Upload, download, and manage files and folders
|
|
21
21
|
- **Google Calendar Service**: Create, update, and manage calendar events
|
|
22
22
|
- **Google Tasks Service**: Manage tasks and task lists
|
|
23
|
+
- **Google Sheets Service**: Read, write, format, and batch-mutate spreadsheets
|
|
24
|
+
- **Google Docs Service**: Create, read, and perform complex batch formatting and structural mutations on Google Documents
|
|
23
25
|
- **Async Support**: Full async/await support for all services with concurrent batch operations
|
|
24
26
|
- **OAuth2 Authentication**: Secure authentication flow with token management
|
|
25
27
|
- **Query Builders**: Intuitive query building for each service
|
|
@@ -46,13 +48,13 @@ oauth_manager = GoogleOAuthManager(
|
|
|
46
48
|
|
|
47
49
|
# Generate authorization URL
|
|
48
50
|
auth_url, state = oauth_manager.generate_auth_url(
|
|
49
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
51
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
50
52
|
)
|
|
51
53
|
|
|
52
54
|
# After user authorizes, exchange code for tokens
|
|
53
55
|
user_info = oauth_manager.complete_auth_flow(
|
|
54
56
|
code='authorization_code_from_callback',
|
|
55
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
57
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
56
58
|
)
|
|
57
59
|
|
|
58
60
|
# Save user_info for future use
|
|
@@ -79,7 +81,7 @@ oauth_manager = GoogleOAuthManager(
|
|
|
79
81
|
|
|
80
82
|
# Authenticate using local server - browser opens automatically!
|
|
81
83
|
user_info = oauth_manager.authenticate_via_local_server(
|
|
82
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
84
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
83
85
|
)
|
|
84
86
|
|
|
85
87
|
# Save credentials
|
|
@@ -134,6 +136,16 @@ event = calendar.create_event(
|
|
|
134
136
|
# Access Tasks service
|
|
135
137
|
tasks = api_service.tasks
|
|
136
138
|
task = tasks.create_task(title="Review documents")
|
|
139
|
+
|
|
140
|
+
# Access Sheets service
|
|
141
|
+
sheets = api_service.sheets
|
|
142
|
+
values = sheets.get_values(spreadsheet_id="your_spreadsheet_id", range_name="Sheet1!A1:B2")
|
|
143
|
+
sheets.append_values_from_dicts("your_spreadsheet_id", "Sheet1!A1", [{"Name": "Alice", "Role": "Admin"}])
|
|
144
|
+
|
|
145
|
+
# Access Docs service
|
|
146
|
+
docs = api_service.docs
|
|
147
|
+
new_doc = docs.create_document(title="Automated Report")
|
|
148
|
+
docs.insert_table_with_data(new_doc.document_id, index=1, data=[["Column 1", "Column 2"]])
|
|
137
149
|
```
|
|
138
150
|
|
|
139
151
|
### Using Services (Asynchronous)
|
|
@@ -176,6 +188,15 @@ async def main():
|
|
|
176
188
|
tasks = api_service.async_tasks
|
|
177
189
|
all_tasks = await tasks.list_tasks(show_completed=True)
|
|
178
190
|
|
|
191
|
+
# Access async Sheets service
|
|
192
|
+
sheets = api_service.async_sheets
|
|
193
|
+
values = await sheets.get_values(spreadsheet_id="your_spreadsheet_id", range_name="Sheet1!A1:B2")
|
|
194
|
+
|
|
195
|
+
# Access async Docs service
|
|
196
|
+
docs = api_service.async_docs
|
|
197
|
+
new_doc = await docs.create_document(title="Async Automated Report")
|
|
198
|
+
extracted_text = await docs.get_document_text(new_doc.document_id)
|
|
199
|
+
|
|
179
200
|
# Run async code
|
|
180
201
|
asyncio.run(main())
|
|
181
202
|
```
|
|
@@ -276,6 +297,8 @@ Each service has detailed documentation with examples and API reference:
|
|
|
276
297
|
- **[Google Drive Service](google_client/services/drive/README.md)** - File and folder management
|
|
277
298
|
- **[Google Calendar Service](google_client/services/calendar/README.md)** - Calendar and event management
|
|
278
299
|
- **[Google Tasks Service](google_client/services/tasks/README.md)** - Task and task list management
|
|
300
|
+
- **[Google Sheets Service](google_client/services/sheets/README.md)** - Advanced spreadsheet reading, writing, and batch mutation
|
|
301
|
+
- **[Google Docs Service](google_client/services/docs/README.md)** - Precise document creation, abstract-syntax-tree parsing, and nested structural formatting
|
|
279
302
|
|
|
280
303
|
## Available Scopes
|
|
281
304
|
|
|
@@ -286,6 +309,8 @@ Scopes.GMAIL # Full Gmail access
|
|
|
286
309
|
Scopes.DRIVE # Full Drive access
|
|
287
310
|
Scopes.CALENDAR # Full Calendar access
|
|
288
311
|
Scopes.TASKS # Full Tasks access
|
|
312
|
+
Scopes.SHEETS # Full Sheets access
|
|
313
|
+
Scopes.DOCS # Full Docs access
|
|
289
314
|
```
|
|
290
315
|
|
|
291
316
|
## Token Refresh
|
|
@@ -311,6 +336,8 @@ refreshed_token = api_service.refresh_token()
|
|
|
311
336
|
- **[Drive API Reference](https://developers.google.com/drive/api)**
|
|
312
337
|
- **[Calendar API Reference](https://developers.google.com/calendar/api)**
|
|
313
338
|
- **[Tasks API Reference](https://developers.google.com/tasks/reference/rest)**
|
|
339
|
+
- **[Sheets API Reference](https://developers.google.com/sheets/api/reference/rest)**
|
|
340
|
+
- **[Docs API Reference](https://developers.google.com/docs/api/reference/rest)**
|
|
314
341
|
|
|
315
342
|
---
|
|
316
343
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: google-api-client-wrapper
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: A comprehensive Python wrapper for Google APIs with async support, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, and Google Tasks services.
|
|
5
5
|
Author-email: Dagmawi Molla <dagmawishewadeg@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -46,12 +46,11 @@ Requires-Dist: html2text>=2025.4.15
|
|
|
46
46
|
Requires-Dist: pydantic>=2.11.7
|
|
47
47
|
Requires-Dist: aiohttp>=3.9.0
|
|
48
48
|
Requires-Dist: aiofiles>=23.0.0
|
|
49
|
-
Requires-Dist: aiogoogle>=5.15.0
|
|
50
49
|
Dynamic: license-file
|
|
51
50
|
|
|
52
51
|
# Google API Client Wrapper
|
|
53
52
|
|
|
54
|
-
A comprehensive Python wrapper for Google APIs, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, and Google
|
|
53
|
+
A comprehensive Python wrapper for Google APIs, providing clean and intuitive access to Gmail, Google Drive, Google Calendar, Google Tasks, Google Docs, and Google Sheets services with both synchronous and asynchronous implementations.
|
|
55
54
|
|
|
56
55
|
## Installation
|
|
57
56
|
|
|
@@ -71,6 +70,8 @@ pip install git+https://github.com/dsmolla/google-api-client-wrapper.git
|
|
|
71
70
|
- **Google Drive Service**: Upload, download, and manage files and folders
|
|
72
71
|
- **Google Calendar Service**: Create, update, and manage calendar events
|
|
73
72
|
- **Google Tasks Service**: Manage tasks and task lists
|
|
73
|
+
- **Google Sheets Service**: Read, write, format, and batch-mutate spreadsheets
|
|
74
|
+
- **Google Docs Service**: Create, read, and perform complex batch formatting and structural mutations on Google Documents
|
|
74
75
|
- **Async Support**: Full async/await support for all services with concurrent batch operations
|
|
75
76
|
- **OAuth2 Authentication**: Secure authentication flow with token management
|
|
76
77
|
- **Query Builders**: Intuitive query building for each service
|
|
@@ -97,13 +98,13 @@ oauth_manager = GoogleOAuthManager(
|
|
|
97
98
|
|
|
98
99
|
# Generate authorization URL
|
|
99
100
|
auth_url, state = oauth_manager.generate_auth_url(
|
|
100
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
101
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
101
102
|
)
|
|
102
103
|
|
|
103
104
|
# After user authorizes, exchange code for tokens
|
|
104
105
|
user_info = oauth_manager.complete_auth_flow(
|
|
105
106
|
code='authorization_code_from_callback',
|
|
106
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
107
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
107
108
|
)
|
|
108
109
|
|
|
109
110
|
# Save user_info for future use
|
|
@@ -130,7 +131,7 @@ oauth_manager = GoogleOAuthManager(
|
|
|
130
131
|
|
|
131
132
|
# Authenticate using local server - browser opens automatically!
|
|
132
133
|
user_info = oauth_manager.authenticate_via_local_server(
|
|
133
|
-
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS]
|
|
134
|
+
scopes=[Scopes.GMAIL, Scopes.DRIVE, Scopes.CALENDAR, Scopes.TASKS, Scopes.SHEETS]
|
|
134
135
|
)
|
|
135
136
|
|
|
136
137
|
# Save credentials
|
|
@@ -185,6 +186,16 @@ event = calendar.create_event(
|
|
|
185
186
|
# Access Tasks service
|
|
186
187
|
tasks = api_service.tasks
|
|
187
188
|
task = tasks.create_task(title="Review documents")
|
|
189
|
+
|
|
190
|
+
# Access Sheets service
|
|
191
|
+
sheets = api_service.sheets
|
|
192
|
+
values = sheets.get_values(spreadsheet_id="your_spreadsheet_id", range_name="Sheet1!A1:B2")
|
|
193
|
+
sheets.append_values_from_dicts("your_spreadsheet_id", "Sheet1!A1", [{"Name": "Alice", "Role": "Admin"}])
|
|
194
|
+
|
|
195
|
+
# Access Docs service
|
|
196
|
+
docs = api_service.docs
|
|
197
|
+
new_doc = docs.create_document(title="Automated Report")
|
|
198
|
+
docs.insert_table_with_data(new_doc.document_id, index=1, data=[["Column 1", "Column 2"]])
|
|
188
199
|
```
|
|
189
200
|
|
|
190
201
|
### Using Services (Asynchronous)
|
|
@@ -227,6 +238,15 @@ async def main():
|
|
|
227
238
|
tasks = api_service.async_tasks
|
|
228
239
|
all_tasks = await tasks.list_tasks(show_completed=True)
|
|
229
240
|
|
|
241
|
+
# Access async Sheets service
|
|
242
|
+
sheets = api_service.async_sheets
|
|
243
|
+
values = await sheets.get_values(spreadsheet_id="your_spreadsheet_id", range_name="Sheet1!A1:B2")
|
|
244
|
+
|
|
245
|
+
# Access async Docs service
|
|
246
|
+
docs = api_service.async_docs
|
|
247
|
+
new_doc = await docs.create_document(title="Async Automated Report")
|
|
248
|
+
extracted_text = await docs.get_document_text(new_doc.document_id)
|
|
249
|
+
|
|
230
250
|
# Run async code
|
|
231
251
|
asyncio.run(main())
|
|
232
252
|
```
|
|
@@ -327,6 +347,8 @@ Each service has detailed documentation with examples and API reference:
|
|
|
327
347
|
- **[Google Drive Service](google_client/services/drive/README.md)** - File and folder management
|
|
328
348
|
- **[Google Calendar Service](google_client/services/calendar/README.md)** - Calendar and event management
|
|
329
349
|
- **[Google Tasks Service](google_client/services/tasks/README.md)** - Task and task list management
|
|
350
|
+
- **[Google Sheets Service](google_client/services/sheets/README.md)** - Advanced spreadsheet reading, writing, and batch mutation
|
|
351
|
+
- **[Google Docs Service](google_client/services/docs/README.md)** - Precise document creation, abstract-syntax-tree parsing, and nested structural formatting
|
|
330
352
|
|
|
331
353
|
## Available Scopes
|
|
332
354
|
|
|
@@ -337,6 +359,8 @@ Scopes.GMAIL # Full Gmail access
|
|
|
337
359
|
Scopes.DRIVE # Full Drive access
|
|
338
360
|
Scopes.CALENDAR # Full Calendar access
|
|
339
361
|
Scopes.TASKS # Full Tasks access
|
|
362
|
+
Scopes.SHEETS # Full Sheets access
|
|
363
|
+
Scopes.DOCS # Full Docs access
|
|
340
364
|
```
|
|
341
365
|
|
|
342
366
|
## Token Refresh
|
|
@@ -362,6 +386,8 @@ refreshed_token = api_service.refresh_token()
|
|
|
362
386
|
- **[Drive API Reference](https://developers.google.com/drive/api)**
|
|
363
387
|
- **[Calendar API Reference](https://developers.google.com/calendar/api)**
|
|
364
388
|
- **[Tasks API Reference](https://developers.google.com/tasks/reference/rest)**
|
|
389
|
+
- **[Sheets API Reference](https://developers.google.com/sheets/api/reference/rest)**
|
|
390
|
+
- **[Docs API Reference](https://developers.google.com/docs/api/reference/rest)**
|
|
365
391
|
|
|
366
392
|
---
|
|
367
393
|
|
|
@@ -18,6 +18,14 @@ google_client/services/calendar/constants.py
|
|
|
18
18
|
google_client/services/calendar/query_builder.py
|
|
19
19
|
google_client/services/calendar/types.py
|
|
20
20
|
google_client/services/calendar/utils.py
|
|
21
|
+
google_client/services/docs/__init__.py
|
|
22
|
+
google_client/services/docs/api_service.py
|
|
23
|
+
google_client/services/docs/async_api_service.py
|
|
24
|
+
google_client/services/docs/async_batch_updater.py
|
|
25
|
+
google_client/services/docs/base_batch_updater.py
|
|
26
|
+
google_client/services/docs/batch_updater.py
|
|
27
|
+
google_client/services/docs/types.py
|
|
28
|
+
google_client/services/docs/utils.py
|
|
21
29
|
google_client/services/drive/__init__.py
|
|
22
30
|
google_client/services/drive/api_service.py
|
|
23
31
|
google_client/services/drive/async_api_service.py
|
|
@@ -35,6 +43,14 @@ google_client/services/gmail/constants.py
|
|
|
35
43
|
google_client/services/gmail/query_builder.py
|
|
36
44
|
google_client/services/gmail/types.py
|
|
37
45
|
google_client/services/gmail/utils.py
|
|
46
|
+
google_client/services/sheets/__init__.py
|
|
47
|
+
google_client/services/sheets/api_service.py
|
|
48
|
+
google_client/services/sheets/async_api_service.py
|
|
49
|
+
google_client/services/sheets/async_batch_updater.py
|
|
50
|
+
google_client/services/sheets/base_batch_updater.py
|
|
51
|
+
google_client/services/sheets/batch_updater.py
|
|
52
|
+
google_client/services/sheets/types.py
|
|
53
|
+
google_client/services/sheets/utils.py
|
|
38
54
|
google_client/services/tasks/__init__.py
|
|
39
55
|
google_client/services/tasks/api_service.py
|
|
40
56
|
google_client/services/tasks/async_api_service.py
|
{google_api_client_wrapper-2.1.1 → google_api_client_wrapper-3.0.0}/google_client/api_service.py
RENAMED
|
@@ -8,11 +8,15 @@ from .services.gmail import GmailApiService
|
|
|
8
8
|
from .services.calendar import CalendarApiService
|
|
9
9
|
from .services.tasks import TasksApiService
|
|
10
10
|
from .services.drive import DriveApiService
|
|
11
|
+
from .services.sheets import SheetsApiService
|
|
12
|
+
from .services.docs import DocsApiService
|
|
11
13
|
|
|
12
14
|
from .services.gmail import AsyncGmailApiService
|
|
13
15
|
from .services.calendar import AsyncCalendarApiService
|
|
14
16
|
from .services.drive import AsyncDriveApiService
|
|
15
17
|
from .services.tasks import AsyncTasksApiService
|
|
18
|
+
from .services.sheets import AsyncSheetsApiService
|
|
19
|
+
from .services.docs import AsyncDocsApiService
|
|
16
20
|
|
|
17
21
|
|
|
18
22
|
class APIServiceLayer:
|
|
@@ -27,11 +31,15 @@ class APIServiceLayer:
|
|
|
27
31
|
self._calendar = None
|
|
28
32
|
self._tasks = None
|
|
29
33
|
self._drive = None
|
|
34
|
+
self._docs = None
|
|
35
|
+
self._sheets = None
|
|
30
36
|
|
|
31
37
|
self._async_gmail = None
|
|
32
38
|
self._async_calendar = None
|
|
33
39
|
self._async_tasks = None
|
|
34
40
|
self._async_drive = None
|
|
41
|
+
self._async_sheets = None
|
|
42
|
+
self._async_docs = None
|
|
35
43
|
|
|
36
44
|
self.timezone = timezone
|
|
37
45
|
|
|
@@ -50,8 +58,8 @@ class APIServiceLayer:
|
|
|
50
58
|
def refresh_token(self) -> dict:
|
|
51
59
|
self._credentials.refresh(Request())
|
|
52
60
|
|
|
53
|
-
self._gmail, self._calendar, self._tasks, self._drive = None, None, None, None
|
|
54
|
-
self._async_gmail, self._async_calendar, self._async_tasks, self._async_drive = None, None, None, None
|
|
61
|
+
self._gmail, self._calendar, self._tasks, self._drive, self._docs, self._sheets = None, None, None, None, None, None
|
|
62
|
+
self._async_gmail, self._async_calendar, self._async_tasks, self._async_drive, self._async_sheets, self._async_docs = None, None, None, None, None, None
|
|
55
63
|
|
|
56
64
|
return json.loads(self._credentials.to_json())
|
|
57
65
|
|
|
@@ -83,6 +91,17 @@ class APIServiceLayer:
|
|
|
83
91
|
if self._drive is None:
|
|
84
92
|
self._drive = DriveApiService(self._credentials, timezone=self.timezone)
|
|
85
93
|
return self._drive
|
|
94
|
+
@property
|
|
95
|
+
def sheets(self):
|
|
96
|
+
if self._sheets is None:
|
|
97
|
+
self._sheets = SheetsApiService(self._credentials, timezone=self.timezone)
|
|
98
|
+
return self._sheets
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def docs(self):
|
|
102
|
+
if self._docs is None:
|
|
103
|
+
self._docs = DocsApiService(self._credentials, timezone=self.timezone)
|
|
104
|
+
return self._docs
|
|
86
105
|
|
|
87
106
|
|
|
88
107
|
@property
|
|
@@ -109,3 +128,15 @@ class APIServiceLayer:
|
|
|
109
128
|
self._async_drive = AsyncDriveApiService(self._credentials, timezone=self.timezone)
|
|
110
129
|
return self._async_drive
|
|
111
130
|
|
|
131
|
+
@property
|
|
132
|
+
def async_sheets(self):
|
|
133
|
+
if self._async_sheets is None:
|
|
134
|
+
self._async_sheets = AsyncSheetsApiService(self._credentials, timezone=self.timezone)
|
|
135
|
+
return self._async_sheets
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def async_docs(self):
|
|
139
|
+
if self._async_docs is None:
|
|
140
|
+
self._async_docs = AsyncDocsApiService(self._credentials, timezone=self.timezone)
|
|
141
|
+
return self._async_docs
|
|
142
|
+
|
|
@@ -177,6 +177,14 @@ class Scopes:
|
|
|
177
177
|
DRIVE_PHOTOS_READONLY = 'https://www.googleapis.com/auth/drive.photos.readonly'
|
|
178
178
|
DRIVE_SCRIPTS = 'https://www.googleapis.com/auth/drive.scripts'
|
|
179
179
|
|
|
180
|
+
# Docs scopes
|
|
181
|
+
DOCS = 'https://www.googleapis.com/auth/documents'
|
|
182
|
+
DOCS_READONLY = 'https://www.googleapis.com/auth/documents.readonly'
|
|
183
|
+
|
|
184
|
+
# Sheets scopes
|
|
185
|
+
SHEETS = 'https://www.googleapis.com/auth/spreadsheets'
|
|
186
|
+
SHEETS_READONLY = 'https://www.googleapis.com/auth/spreadsheets.readonly'
|
|
187
|
+
|
|
180
188
|
# User info scopes
|
|
181
189
|
USERINFO_EMAIL = 'https://www.googleapis.com/auth/userinfo.email'
|
|
182
190
|
USERINFO_PROFILE = 'https://www.googleapis.com/auth/userinfo.profile'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import uuid
|
|
2
3
|
from datetime import datetime, timedelta
|
|
3
4
|
from typing import Optional, List, Any, Dict, Union
|
|
@@ -370,11 +371,18 @@ class CalendarApiService:
|
|
|
370
371
|
"""
|
|
371
372
|
|
|
372
373
|
calendar_events = []
|
|
373
|
-
for
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
374
|
+
for i in range(0, len(event_ids), 10):
|
|
375
|
+
batch = self._service.new_batch_http_request()
|
|
376
|
+
for event_id in event_ids[i: i + 10]:
|
|
377
|
+
batch.add(self._service.events().get(calendarId=calendar_id, eventId=event_id))
|
|
378
|
+
batch.execute()
|
|
379
|
+
|
|
380
|
+
for response in batch._responses.values():
|
|
381
|
+
event_json = json.loads(response[1].decode())
|
|
382
|
+
if "error" in event_json:
|
|
383
|
+
calendar_events.append(("ERROR", event_json["error"]))
|
|
384
|
+
continue
|
|
385
|
+
calendar_events.append(utils.from_google_event(event_json, calendar_id, self._timezone))
|
|
378
386
|
|
|
379
387
|
return calendar_events
|
|
380
388
|
|
|
@@ -382,7 +390,7 @@ class CalendarApiService:
|
|
|
382
390
|
self,
|
|
383
391
|
events_data: List[Dict[str, Any]],
|
|
384
392
|
calendar_id: str = DEFAULT_CALENDAR_ID
|
|
385
|
-
) -> List[CalendarEvent |
|
|
393
|
+
) -> List[CalendarEvent | tuple]:
|
|
386
394
|
"""
|
|
387
395
|
Creates multiple events.
|
|
388
396
|
|
|
@@ -391,18 +399,84 @@ class CalendarApiService:
|
|
|
391
399
|
calendar_id: Calendar ID to create events in (default: 'primary').
|
|
392
400
|
|
|
393
401
|
Returns:
|
|
394
|
-
List of created CalendarEvent objects.
|
|
402
|
+
List of created CalendarEvent objects or ("ERROR", error_dict) tuples on failure.
|
|
395
403
|
"""
|
|
396
404
|
|
|
397
405
|
created_events = []
|
|
398
|
-
for
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
406
|
+
for i in range(0, len(events_data), 10):
|
|
407
|
+
batch = self._service.new_batch_http_request()
|
|
408
|
+
for event_data in events_data[i: i + 10]:
|
|
409
|
+
event_body = {
|
|
410
|
+
'summary': event_data.get('summary') or "New Event",
|
|
411
|
+
'start': {'dateTime': datetime_to_iso(event_data['start'], self._timezone), 'timeZone': self._timezone},
|
|
412
|
+
'end': {'dateTime': datetime_to_iso(event_data['end'], self._timezone), 'timeZone': self._timezone},
|
|
413
|
+
}
|
|
414
|
+
if event_data.get('description'):
|
|
415
|
+
event_body['description'] = event_data['description']
|
|
416
|
+
if event_data.get('location'):
|
|
417
|
+
event_body['location'] = event_data['location']
|
|
418
|
+
if event_data.get('attendees'):
|
|
419
|
+
event_body['attendees'] = [a.to_dict() for a in event_data['attendees']]
|
|
420
|
+
if event_data.get('recurrence'):
|
|
421
|
+
event_body['recurrence'] = event_data['recurrence']
|
|
422
|
+
if event_data.get('create_google_meet'):
|
|
423
|
+
event_body['conferenceData'] = {
|
|
424
|
+
"createRequest": {
|
|
425
|
+
"requestId": uuid.uuid4().hex,
|
|
426
|
+
"conferenceSolutionKey": {"type": "hangoutsMeet"}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
batch.add(self._service.events().insert(
|
|
430
|
+
calendarId=calendar_id, body=event_body, conferenceDataVersion=1
|
|
431
|
+
))
|
|
432
|
+
batch.execute()
|
|
433
|
+
|
|
434
|
+
for response in batch._responses.values():
|
|
435
|
+
event_json = json.loads(response[1].decode())
|
|
436
|
+
if "error" in event_json:
|
|
437
|
+
created_events.append(("ERROR", event_json["error"]))
|
|
438
|
+
continue
|
|
439
|
+
created_events.append(utils.from_google_event(event_json, calendar_id, self._timezone))
|
|
403
440
|
|
|
404
441
|
return created_events
|
|
405
442
|
|
|
443
|
+
def batch_delete_events(
|
|
444
|
+
self,
|
|
445
|
+
events: List[Union[CalendarEvent, str]],
|
|
446
|
+
calendar_id: str = DEFAULT_CALENDAR_ID
|
|
447
|
+
) -> List[bool | tuple]:
|
|
448
|
+
"""
|
|
449
|
+
Deletes multiple calendar events.
|
|
450
|
+
|
|
451
|
+
Args:
|
|
452
|
+
events: List of CalendarEvent objects or event IDs to delete.
|
|
453
|
+
calendar_id: Calendar ID containing the events (default: 'primary').
|
|
454
|
+
|
|
455
|
+
Returns:
|
|
456
|
+
List of True for each success or ("ERROR", error_dict) for each failure.
|
|
457
|
+
"""
|
|
458
|
+
results = []
|
|
459
|
+
event_ids = [e if isinstance(e, str) else e.event_id for e in events]
|
|
460
|
+
|
|
461
|
+
for i in range(0, len(event_ids), 10):
|
|
462
|
+
batch = self._service.new_batch_http_request()
|
|
463
|
+
for event_id in event_ids[i: i + 10]:
|
|
464
|
+
batch.add(self._service.events().delete(calendarId=calendar_id, eventId=event_id))
|
|
465
|
+
batch.execute()
|
|
466
|
+
|
|
467
|
+
for response in batch._responses.values():
|
|
468
|
+
body = response[1]
|
|
469
|
+
if not body:
|
|
470
|
+
results.append(True)
|
|
471
|
+
continue
|
|
472
|
+
response_json = json.loads(body.decode())
|
|
473
|
+
if "error" in response_json:
|
|
474
|
+
results.append(("ERROR", response_json["error"]))
|
|
475
|
+
continue
|
|
476
|
+
results.append(True)
|
|
477
|
+
|
|
478
|
+
return results
|
|
479
|
+
|
|
406
480
|
def get_freebusy(
|
|
407
481
|
self,
|
|
408
482
|
start: datetime,
|