googleapiutils2
Python wrapper for Google APIs: Drive, Sheets, Gmail, Admin, Groups, Geocoding.
Installation
via pip
pip install googleapiutils2
via uv
uv add googleapiutils2
Requires Python ^3.12
Overview
googleapiutils2 provides a unified, Pythonic interface for Google APIs with built-in:
- Automatic retry - 10 retries with exponential backoff
- TTL caching - 80s cache on frequently accessed data
- Request throttling - Rate limiting to prevent quota exhaustion
- Type hints - Full IDE support via google-api-stubs
- URL support - Accept file/sheet IDs or URLs interchangeably
Quick Start
Drive
from googleapiutils2 import Drive, GoogleMimeTypes
drive = Drive()
drive.upload("file.csv", to_mime_type=GoogleMimeTypes.sheets, parents=["folder_id"])
drive.upload("./folder", recursive=True, update=True)
for file in drive.list(query="name contains 'report'"):
print(f"{file['name']}: {file['id']}")
drive.download("file_id", "./output.pdf", mime_type=GoogleMimeTypes.pdf)
drive.download("folder_id", "./local_folder", recursive=True)
Sheets
from googleapiutils2 import Sheets, SheetsValueRange
sheets = Sheets()
Sheet1 = SheetsValueRange(sheets, sheet_url, "Sheet1")
Sheet1[1, "A"].update([["Value"]])
Sheet1[2:5, 1:3].update([[1,2,3], [4,5,6], [7,8,9]])
data = Sheet1[...].read()
sheets.batch_update(sheet_url, {
Sheet1[1, ...]: [["Header 1", "Header 2"]],
Sheet1[2:4, ...]: [[1, 2], [3, 4]]
})
import pandas as pd
df = Sheet1[...].to_frame()
Sheet1.update(sheets.from_frame(df, include_header=True))
sheets.format(sheet_url, Sheet1[1, ...], bold=True, background_color="#d48686")
Mail
from googleapiutils2 import Mail
mail = Mail()
mail.send(
sender="me@example.com",
to="user@example.com",
subject="Test",
body="Hello"
)
for msg in mail.list_messages(query="from:user@example.com after:2024/01/01"):
print(msg['id'], msg['snippet'])
Admin (Workspace)
from googleapiutils2 import Admin
admin = Admin()
user = admin.create_user(
primary_email="test@domain.com",
given_name="Test",
family_name="User",
password="temp123"
)
for user in admin.list_users(query="givenName:John"):
print(user['primaryEmail'])
Groups
from googleapiutils2 import Groups
groups = Groups()
group = groups.create(
email="team@domain.com",
name="Engineering",
description="All engineers"
)
groups.members_insert("team@domain.com", "user@domain.com")
for member in groups.members_list("team@domain.com"):
print(member['email'], member['role'])
Geocode
from googleapiutils2 import Geocode
geocoder = Geocode(api_key="YOUR_API_KEY")
results = geocoder.geocode("1600 Amphitheatre Parkway, Mountain View, CA")
print(results[0]['geometry']['location'])
results = geocoder.reverse_geocode(lat=37.422, long=-122.084)
Monitor (Change Detection)
from googleapiutils2 import SheetsMonitor
def on_change(data, monitor):
print(f"Sheet updated: {len(data)} rows")
monitor = SheetsMonitor(sheets, drive, sheet_url, on_change, interval=30)
monitor.start()
Authentication
Two authentication methods supported:
Service Account (Recommended for automation)
When to use:
- Automated scripts and server applications
- No user interaction needed
- Domain-wide delegation (Workspace only)
Setup:
Usage:
from googleapiutils2 import Drive, get_oauth2_creds
creds = get_oauth2_creds(client_config="auth/service-account.json")
drive = Drive(creds=creds)
creds = get_oauth2_creds(client_config="auth/service-account.json")
creds = creds.with_subject("user@domain.com")
drive = Drive(creds=creds)
OAuth2 Client (For user authorization)
When to use:
- Desktop applications
- User consent required
- Personal Google accounts
Setup:
Usage:
creds = get_oauth2_creds(
client_config="auth/oauth2_credentials.json",
token_path="auth/token.pickle"
)
drive = Drive(creds=creds)
Auto-discovery
drive = Drive()
sheets = Sheets()
Features
Drive
Upload:
- Files, folders (recursive)
- DataFrames to Google Sheets
- Markdown ↔ Google Docs conversion
- MD5 checksum for skip-if-unchanged
Download:
- Files, folders (recursive)
- Format conversion (Sheets → xlsx, Docs → docx, etc.)
- Chunked downloads for large files
Operations:
get, list, create, copy, update, delete
sync - Sync local ↔ remote directories
empty_trash - Empty trash
- Permissions management
Sheets
Slice Notation:
Sheet[1, "A"]
Sheet[2:5, 1:3]
Sheet[1, ...]
Sheet[..., "A"]
Sheet[-1, -1]
Sheet["A1:B2"]
Operations:
- CRUD: create, read, update, delete, append, clear
- Formatting: bold, colors, alignment, wrap, freeze
- Batch updates with auto-chunking
- Column alignment for dict data
- Auto-resize on overflow
DataFrame Integration:
df = Sheet1[...].to_frame()
Sheet1.update(sheets.from_frame(df, include_header=True))
Mail
Messages:
- Send (plain text, HTML)
- Create drafts
- List, get, modify, trash, delete
Labels:
- List, create, delete, modify
- Apply/remove labels from messages
Admin (Workspace)
User Management:
- Create, update, delete users
- Suspend/unsuspend accounts
- Password management
- Admin role management
- Search by name, email, org unit
Groups
Group Operations:
- Create, update, delete groups
- List groups by domain/customer/user
Member Operations:
- Add, remove, update members
- List members
- Check membership
- Role management (OWNER, MANAGER, MEMBER)
Geocode
Operations:
- Forward geocoding (address → coordinates)
- Reverse geocoding (coordinates → address)
- Address component parsing
- Location type (ROOFTOP, RANGE_INTERPOLATED, etc.)
Architecture
Base Class: DriveBase - All API classes inherit (except Geocode)
- TTL caching (80s, 128 entries)
- Retry decorator (10 retries, 30s delay, exponential backoff)
- Throttling (0.1s individual, 1s batch)
- Background request queueing
Exception Hierarchy:
GoogleAPIException
├── InvalidRequestError
├── OverQueryLimitError
├── RequestDeniedError
├── NotFoundError
└── UnknownError
Key Patterns:
- TYPE_CHECKING blocks for circular import prevention
- Generator pattern for pagination
- MIME type auto-detection and conversion
- MD5 checksum caching
- Slice notation for Sheets (NumPy-like)
File Structure
googleapiutils2/
├── utils/ # Core: DriveBase, auth, caching, retry, MIME types
├── drive/ # Google Drive API
├── sheets/ # Google Sheets API
├── mail/ # Gmail API
├── admin/ # Workspace Admin API
├── groups/ # Google Groups API
├── geocode/ # Maps Geocoding API
└── monitor.py # Change detection (DriveMonitor, SheetsMonitor)
Dependencies
- google-api-python-client ^2.168.0
- google-auth ^2.39.0
- google-auth-oauthlib ^1.2.1
- pandas ^2.2.3
- cachetools ^5.5.2
- loguru ^0.7.3
- requests ^2.32.3
Testing
pytest test/
Tests use real Google APIs with session-scoped fixtures and automatic cleanup.
Documentation
Examples
See examples/ for more usage patterns:
drive_upload.py - File/folder uploads
sheets_crud.py - Sheet operations and formatting
mail.py - Email sending
monitor.py - Change detection
- And more...
License
MIT
Repository
https://github.com/mkbabb/googleapiutils2