A Python library for Google Sheets with high-level API, automatic type inference, and efficient caching.
Project description
SmartSpread
Python library for Google Sheets operations with automatic type inference, caching, and multiple data format support. Built on gspread.
Core Concepts
Two main classes:
SmartSpread: Represents a Google Sheets spreadsheet, manages authentication and tab accessSmartTab: Represents a single worksheet tab, handles data read/write operations
Three data formats:
DataFrame: pandas DataFrame (default) - best for data manipulationdict: List of dictionaries - each row is a dict with column names as keyslist: List of lists - first row is headers, remaining rows are data
Type inference:
- Empty cells →
None - Integers → nullable
Int64dtype (preservesNone) - Floats →
float64 - Strings →
objectdtype - Empty columns → inferred as needed when data is added
Caching behavior:
- Data is cached after first read to minimize API calls
- Hash comparison prevents unnecessary writes
- Use
refresh()to reload from Google Sheets after external changes
Installation & Setup
pip install smartspread
Authentication requirements:
- Google Cloud Project with Sheets API enabled
- Service account credentials JSON file
- Spreadsheet shared with service account email
Usage Patterns
Basic workflow
from smartspread import SmartSpread
spread = SmartSpread(
sheet_identifier="spreadsheet-id-or-name",
key_file="credentials.json"
)
tab = spread.tab("MyTab") # Get or create tab
tab.data["new_column"] = "value" # Modify DataFrame
tab.write_data(overwrite_tab=True) # Write to Sheets
Data format selection
tab_df = spread.tab("Sheet1", data_format="DataFrame") # pandas DataFrame
tab_dict = spread.tab("Sheet2", data_format="dict") # [{"col": "val"}, ...]
tab_list = spread.tab("Sheet3", data_format="list") # [["header"], ["val"], ...]
Update or insert rows
# Updates existing row where ID=123, or inserts new row if not found
tab.update_row_by_column_pattern(
column="ID",
value=123,
updates={"Status": "completed", "Date": "2024-01-01"}
)
tab.write_data(overwrite_tab=True)
Filter and refresh
filtered = tab.filter_rows_by_column("Name", "Alice") # Returns DataFrame
tab.refresh() # Reload from Sheets after external changes
API Reference
SmartSpread(sheet_identifier, key_file=None, service_account_data=None, user_email=None)
Constructor parameters:
sheet_identifier: Spreadsheet ID or namekey_file: Path to service account JSON credentialsservice_account_data: Dict of credentials (alternative to key_file)user_email: Email for user-based auth (alternative to service account)
Methods:
tab(tab_name, data_format="DataFrame", keep_number_formatting=False)→ SmartTabrefresh()→ None (clears cache, reloads metadata)grant_access(email, role="owner")→ None
Properties:
tab_names→ list[str]url→ strtab_exists(tab_name)→ bool
SmartTab
Attributes:
data: DataFrame | list[dict] | list[list] (mutable, modify directly)tab_name: strdata_format: "DataFrame" | "dict" | "list"
Methods:
read_data()→ DataFrame | list[dict] | list[list]write_data(overwrite_tab=False, as_table=False)→ Noneupdate_row_by_column_pattern(column, value, updates)→ None (modifiesdatain-place)filter_rows_by_column(column, pattern)→ DataFramerefresh()→ None (reloads from Sheets)
Important Implementation Details
Type handling:
- Empty cells →
None(not empty string) - Nullable integers use
Int64dtype (notint64) - Mixed-type columns automatically convert to
objectdtype when needed pd.NAvalues are sanitized toNonein dict/list formats- NaN values are converted to empty strings before writing to Sheets
Write behavior:
write_data()only writes if data hash has changedoverwrite_tab=Trueclears entire tab before writingoverwrite_tab=Falseupdates only the data rangeas_table=Trueadds header formatting and freeze
Rate limits:
- Google Sheets API: 60 requests/minute (free tier)
- Caching minimizes API calls automatically
Error handling:
- Empty tabs raise
ValueErroron read - Missing columns are auto-created with
Nonevalues - Type mismatches trigger automatic dtype conversion
Changelog
v1.1.4 (2024)
- Fixed: TypeError when writing strings to float64 columns in update_row_by_column_pattern
- Fixed: InvalidJSONError with NaN values in write_data by converting to object dtype before fillna
v1.1.3 (2024)
- Fixed: pd.NA values sanitized to None in list/dict formats
v1.1.2 (2024)
- Changed: Package renamed to smartspread (no underscore)
v1.1.1 (2024)
- Fixed: JSON serialization with Int64 columns containing pd.NA
Links
- GitHub: https://github.com/Redundando/smart_spread
- PyPI: https://pypi.org/project/smartspread/
- License: MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file smartspread-1.1.4.tar.gz.
File metadata
- Download URL: smartspread-1.1.4.tar.gz
- Upload date:
- Size: 13.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
456a38622d2ad4ace2e107ad81a5d6438cde8e9c6400ad9fc1fe5f296a863bf9
|
|
| MD5 |
e23518e49818c9570c5153dc14a5a3e5
|
|
| BLAKE2b-256 |
604a5f9cddd7c4fa05dd5b669d2b89e80fc1a2643c68cceb4755818503d2d701
|
File details
Details for the file smartspread-1.1.4-py3-none-any.whl.
File metadata
- Download URL: smartspread-1.1.4-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81451b06a4568e79bbb59bfb3cdc999215e0f325f4742f05b30a13c14ec8fcd0
|
|
| MD5 |
5d1315bc37c8b62f558836345c22fa62
|
|
| BLAKE2b-256 |
18a23b0334da217348190772dc173199870622fbebf36f98d41b89722156f351
|