Source code for langchain_google_community.sheets.utils
"""Google Sheets tool utils."""
from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from langchain_google_community._utils import (
get_google_credentials,
import_googleapiclient_resource_builder,
)
if TYPE_CHECKING:
from google.oauth2.credentials import Credentials # type: ignore[import]
from googleapiclient.discovery import Resource # type: ignore[import]
[docs]
def build_sheets_service(
credentials: Optional[Credentials] = None,
service_name: str = "sheets",
service_version: str = "v4",
use_domain_wide: bool = False,
delegated_user: Optional[str] = None,
service_account_file: Optional[str] = None,
scopes: Optional[List[str]] = None,
) -> Resource:
"""Build a Google Sheets service with OAuth2 credentials (full access).
Args:
credentials: OAuth2 credentials. If None, will attempt to load from
default locations.
service_name: The Google API service name.
service_version: The Google API service version.
use_domain_wide: Whether to use domain-wide delegation.
delegated_user: User to impersonate for domain-wide delegation.
service_account_file: Path to service account file for domain-wide
delegation.
scopes: List of OAuth2 scopes. Defaults to full access scopes.
Returns:
Resource: Google Sheets API service with full access capabilities.
"""
# Default scopes for full access
default_scopes = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive.readonly",
]
if use_domain_wide:
# Scopes for domain-wide delegation (can be read-only or read-write)
default_scopes = [
"https://www.googleapis.com/auth/spreadsheets.readonly",
"https://www.googleapis.com/auth/drive.readonly",
]
scopes = scopes or default_scopes
credentials = credentials or get_google_credentials(
scopes=scopes,
use_domain_wide=use_domain_wide,
delegated_user=delegated_user,
service_account_file=service_account_file,
)
builder = import_googleapiclient_resource_builder()
return builder(service_name, service_version, credentials=credentials)
[docs]
def build_sheets_service_with_api_key(api_key: str) -> Resource:
"""Build a Google Sheets service with API key (read-only access).
Args:
api_key: Google API key for authentication.
Returns:
Resource: Google Sheets API service with read-only access to public
spreadsheets.
Note:
API key authentication only works with public spreadsheets.
For private spreadsheets, use OAuth2 credentials instead.
"""
builder = import_googleapiclient_resource_builder()
return builder("sheets", "v4", developerKey=api_key)
[docs]
def validate_spreadsheet_id(spreadsheet_id: str) -> str:
"""Validate and normalize a Google Spreadsheet ID.
Args:
spreadsheet_id: The spreadsheet ID to validate.
Returns:
str: The validated spreadsheet ID.
Raises:
ValueError: If the spreadsheet ID is invalid.
"""
if not spreadsheet_id:
raise ValueError("Spreadsheet ID cannot be empty")
# Remove any URL components if present
if "docs.google.com/spreadsheets/d/" in spreadsheet_id:
# Extract ID from URL
start = spreadsheet_id.find("/d/") + 3
end = spreadsheet_id.find("/", start)
if end == -1:
end = len(spreadsheet_id)
spreadsheet_id = spreadsheet_id[start:end]
# Basic validation - Google Spreadsheet IDs are typically 44 characters
if len(spreadsheet_id) < 20:
raise ValueError(f"Invalid spreadsheet ID format: {spreadsheet_id}")
return spreadsheet_id
[docs]
def validate_range_name(range_name: str) -> str:
"""Validate and normalize a range name.
Args:
range_name: The range name to validate (e.g., "A1:Z100", "Sheet1!A1:B2").
Returns:
str: The validated range name.
Raises:
ValueError: If the range name is invalid.
"""
if not range_name:
raise ValueError("Range name cannot be empty")
# Basic validation - should contain at least one colon for range
if ":" not in range_name and not range_name.isalpha():
raise ValueError(f"Invalid range format: {range_name}")
return range_name