Source code for langchain_google_community.sheets.base

"""Base class for Google Sheets tools."""

from __future__ import annotations

from typing import TYPE_CHECKING, Optional

from langchain_core.tools import BaseTool
from pydantic import Field

if TYPE_CHECKING:
    # This is for linting and IDE typehints
    from googleapiclient.discovery import Resource  # type: ignore[import]
else:
    try:
        # We do this so pydantic can resolve the types when instantiating
        from googleapiclient.discovery import Resource
    except ImportError:
        pass


[docs] class SheetsBaseTool(BaseTool): # type: ignore[override] """Base class for Google Sheets tools. Authentication: - api_resource: OAuth2 credentials for full access (read/write private sheets) - api_key: API key for read-only access (public sheets only) Note: Write operations require OAuth2 credentials. """ api_resource: Optional[Resource] = Field( default=None, description="Google Sheets API resource, OAuth2 credentials for full access", ) api_key: Optional[str] = Field( default=None, description="Google API key for read-only access to public spreadsheets", ) def _get_service(self) -> Resource: """Get the appropriate Google Sheets service based on available credentials. Returns: Resource: Google Sheets API service Raises: ValueError: If neither api_resource nor api_key is provided """ if self.api_resource: return self.api_resource # OAuth2 - full access elif self.api_key: from langchain_google_community.sheets.utils import ( build_sheets_service_with_api_key, ) return build_sheets_service_with_api_key( self.api_key ) # API key - read-only else: # Try to create OAuth2 service as fallback from langchain_google_community.sheets.utils import build_sheets_service return build_sheets_service() def _check_write_permissions(self) -> None: """Check if the current authentication method supports write operations. Raises: ValueError: If using API key for write operations """ if self.api_key and not self.api_resource: raise ValueError( "Write operations require OAuth2 credentials, not API key. " "Please provide api_resource for write access to private spreadsheets." )
[docs] @classmethod def from_api_resource(cls, api_resource: Resource) -> "SheetsBaseTool": """Create a tool from an API resource. Args: api_resource: The API resource to use. Returns: A tool with OAuth2 credentials for full access. """ return cls(api_resource=api_resource) # type: ignore[call-arg]
[docs] @classmethod def from_api_key(cls, api_key: str) -> "SheetsBaseTool": """Create a tool from an API key. Args: api_key: The API key to use. Returns: A tool with API key for read-only access. """ return cls(api_key=api_key) # type: ignore[call-arg]
def _safe_get_cell_value(self, cell_data: dict) -> str: """Safely extract cell value with proper fallback hierarchy. Args: cell_data: Cell data dictionary from Google Sheets API Returns: str: The cell value as a string """ if cell_data.get("formattedValue"): return cell_data["formattedValue"] elif cell_data.get("effectiveValue", {}).get("stringValue"): return str(cell_data["effectiveValue"]["stringValue"]) elif cell_data.get("effectiveValue", {}).get("numberValue") is not None: return str(cell_data["effectiveValue"]["numberValue"]) elif cell_data.get("userEnteredValue", {}).get("stringValue"): return str(cell_data["userEnteredValue"]["stringValue"]) elif cell_data.get("userEnteredValue", {}).get("numberValue") is not None: return str(cell_data["userEnteredValue"]["numberValue"]) else: return ""