tha-google-runner 0.1.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.
- tha_google_runner-0.1.0/.github/workflows/ci.yml +36 -0
- tha_google_runner-0.1.0/.github/workflows/publish.yml +53 -0
- tha_google_runner-0.1.0/.gitignore +38 -0
- tha_google_runner-0.1.0/LICENSE +21 -0
- tha_google_runner-0.1.0/PKG-INFO +325 -0
- tha_google_runner-0.1.0/README.md +296 -0
- tha_google_runner-0.1.0/pyproject.toml +56 -0
- tha_google_runner-0.1.0/src/tha_google_runner/__init__.py +10 -0
- tha_google_runner-0.1.0/src/tha_google_runner/auth.py +48 -0
- tha_google_runner-0.1.0/src/tha_google_runner/errors.py +2 -0
- tha_google_runner-0.1.0/src/tha_google_runner/py.typed +0 -0
- tha_google_runner-0.1.0/src/tha_google_runner/sheets.py +337 -0
- tha_google_runner-0.1.0/tests/test_sheets.py +668 -0
- tha_google_runner-0.1.0/uv.lock +777 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["main"]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v4
|
|
20
|
+
with:
|
|
21
|
+
version: "latest"
|
|
22
|
+
|
|
23
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
24
|
+
run: uv python install ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: uv sync --extra dev --python ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Lint
|
|
30
|
+
run: uv run ruff check src/ tests/
|
|
31
|
+
|
|
32
|
+
- name: Test
|
|
33
|
+
run: uv run pytest
|
|
34
|
+
|
|
35
|
+
- name: Type check
|
|
36
|
+
run: uv run mypy src/
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- name: Install uv
|
|
14
|
+
uses: astral-sh/setup-uv@v4
|
|
15
|
+
- name: Build
|
|
16
|
+
run: uv build
|
|
17
|
+
- name: Upload dist
|
|
18
|
+
uses: actions/upload-artifact@v4
|
|
19
|
+
with:
|
|
20
|
+
name: dist
|
|
21
|
+
path: dist/
|
|
22
|
+
|
|
23
|
+
publish-testpypi:
|
|
24
|
+
needs: build
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
environment: testpypi
|
|
27
|
+
permissions:
|
|
28
|
+
id-token: write
|
|
29
|
+
steps:
|
|
30
|
+
- name: Download dist
|
|
31
|
+
uses: actions/download-artifact@v4
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
- name: Publish to TestPyPI
|
|
36
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
37
|
+
with:
|
|
38
|
+
repository-url: https://test.pypi.org/legacy/
|
|
39
|
+
|
|
40
|
+
publish-pypi:
|
|
41
|
+
needs: publish-testpypi
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
environment: pypi
|
|
44
|
+
permissions:
|
|
45
|
+
id-token: write
|
|
46
|
+
steps:
|
|
47
|
+
- name: Download dist
|
|
48
|
+
uses: actions/download-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/
|
|
52
|
+
- name: Publish to PyPI
|
|
53
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.egg-info/
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg
|
|
10
|
+
.eggs/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# uv
|
|
18
|
+
.uv/
|
|
19
|
+
|
|
20
|
+
# mypy
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
|
|
23
|
+
# pytest
|
|
24
|
+
.pytest_cache/
|
|
25
|
+
.coverage
|
|
26
|
+
htmlcov/
|
|
27
|
+
|
|
28
|
+
# ruff
|
|
29
|
+
.ruff_cache/
|
|
30
|
+
|
|
31
|
+
# OS
|
|
32
|
+
.DS_Store
|
|
33
|
+
Thumbs.db
|
|
34
|
+
|
|
35
|
+
# Google auth tokens -- never commit these
|
|
36
|
+
token.json
|
|
37
|
+
client_secrets.json
|
|
38
|
+
*_secrets.json
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nathan Wright
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tha-google-runner
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Tabular Helper API library that wraps Google Sheets with a typed, consistent interface built on gspread.
|
|
5
|
+
Project-URL: Homepage, https://github.com/tha-guy-nate/tha-google-runner
|
|
6
|
+
Project-URL: Issues, https://github.com/tha-guy-nate/tha-google-runner/issues
|
|
7
|
+
Author: Nate Wright
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: google,gspread,helper,sheets,tabular
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: google-auth-oauthlib>=1.0
|
|
22
|
+
Requires-Dist: google-auth>=2.0
|
|
23
|
+
Requires-Dist: gspread>=6.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# tha-google-runner
|
|
31
|
+
|
|
32
|
+
[](https://github.com/tha-guy-nate/tha-google-runner/actions/workflows/ci.yml)
|
|
33
|
+
|
|
34
|
+
A Tabular Helper API library that wraps Google Sheets with a typed, consistent interface built on gspread.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install tha-google-runner
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Authentication setup
|
|
43
|
+
|
|
44
|
+
`tha-google-runner` uses your **personal Google account** — not a service account. There are two ways to authenticate. Option 1 is recommended if you have the Google Cloud SDK installed.
|
|
45
|
+
|
|
46
|
+
> **Cost note:** This package is free and open source. The Google APIs it uses (Google Sheets API, Google Drive API) are also free for normal scripting workloads — Google provides a generous free tier (300 reads/min, 60 writes/min) that the vast majority of users will never exceed. Google Cloud Console may ask for a credit card when you first create a project to verify your identity, but **Google does not charge you** for the APIs used here. Any billing questions are between you and Google — not this package.
|
|
47
|
+
|
|
48
|
+
### Option 1 — Application Default Credentials (ADC)
|
|
49
|
+
|
|
50
|
+
This is the zero-config path. Run once in your terminal:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
gcloud auth application-default login
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
A browser window opens, you sign in with your Google account, and credentials are saved to your machine. After that, `ThaSheets()` works with no arguments.
|
|
57
|
+
|
|
58
|
+
> Don't have `gcloud`? Install the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install) — it's a standalone CLI tool, roughly similar in spirit to the AWS CLI or the Azure CLI. It is not heavy and not venv-specific; install it once at the system level and every Python project on your machine can use ADC. Or skip it entirely and use Option 2.
|
|
59
|
+
|
|
60
|
+
### Option 2 — OAuth2 client secrets
|
|
61
|
+
|
|
62
|
+
Use this if you don't have `gcloud` or prefer not to install it.
|
|
63
|
+
|
|
64
|
+
**Step 1 — Create a Google Cloud project**
|
|
65
|
+
|
|
66
|
+
1. Go to [console.cloud.google.com](https://console.cloud.google.com/)
|
|
67
|
+
2. Click the project dropdown → **New Project** → give it any name → **Create**
|
|
68
|
+
|
|
69
|
+
**Step 2 — Enable the required APIs**
|
|
70
|
+
|
|
71
|
+
In your new project, go to **APIs & Services** → **Enable APIs and Services** and enable both:
|
|
72
|
+
- **Google Sheets API**
|
|
73
|
+
- **Google Drive API**
|
|
74
|
+
|
|
75
|
+
**Step 3 — Create OAuth2 credentials**
|
|
76
|
+
|
|
77
|
+
1. Go to **APIs & Services** → **Credentials** → **Create Credentials** → **OAuth 2.0 Client ID**
|
|
78
|
+
2. If prompted, configure the **OAuth consent screen** first:
|
|
79
|
+
- User type: **External** → fill in app name and your email → save
|
|
80
|
+
3. Application type: **Desktop app** → give it a name → **Create**
|
|
81
|
+
4. Click **Download JSON** and save the file (e.g., `client_secrets.json`)
|
|
82
|
+
|
|
83
|
+
**Step 4 — Use the credentials file**
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
sheets = ThaSheets(credentials_file="client_secrets.json")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
On the **first run**, a browser window opens for you to grant access. After that, the token is cached at `~/.config/tha-google-runner/token.json` and no browser is needed.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Quick start
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from tha_google_runner import ThaSheets
|
|
97
|
+
|
|
98
|
+
sheets = ThaSheets() # uses ADC; or pass credentials_file="client_secrets.json"
|
|
99
|
+
|
|
100
|
+
# Read all rows (first row is headers)
|
|
101
|
+
rows = sheets.read(spreadsheet_id="your-spreadsheet-id")
|
|
102
|
+
|
|
103
|
+
# Append new rows (writes headers automatically if the sheet is empty)
|
|
104
|
+
sheets.append_rows(
|
|
105
|
+
[{"name": "Alice", "score": 95}, {"name": "Bob", "score": 82}],
|
|
106
|
+
spreadsheet_id="your-spreadsheet-id",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Append using raw lists — header row auto-detected and dropped if it matches the sheet
|
|
110
|
+
sheets.append_rows(
|
|
111
|
+
[["name", "score"], ["Alice", 95]],
|
|
112
|
+
spreadsheet_id="your-spreadsheet-id",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Overwrite the entire sheet
|
|
116
|
+
sheets.update_rows(
|
|
117
|
+
[{"name": "Alice", "score": 95}],
|
|
118
|
+
spreadsheet_id="your-spreadsheet-id",
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Upsert by key — inserts new rows, updates existing ones
|
|
122
|
+
sheets.upsert_rows(
|
|
123
|
+
[{"id": "1", "name": "Alice", "score": 99}],
|
|
124
|
+
key="id",
|
|
125
|
+
spreadsheet_id="your-spreadsheet-id",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Create a new spreadsheet and get its ID
|
|
129
|
+
spreadsheet_id = sheets.create("My Report", rows=[{"col": "val"}])
|
|
130
|
+
|
|
131
|
+
# Clear a sheet
|
|
132
|
+
sheets.clear(spreadsheet_id="your-spreadsheet-id")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
> **Finding your spreadsheet ID:** It's the long string in the URL between `/d/` and `/edit`.
|
|
136
|
+
> `https://docs.google.com/spreadsheets/d/<spreadsheet-id>/edit`
|
|
137
|
+
>
|
|
138
|
+
> You can also pass `url=` instead of `spreadsheet_id=` to any method and the ID will be extracted automatically.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Row input formats
|
|
143
|
+
|
|
144
|
+
All write methods (`append_rows`, `update_rows`, `upsert_rows`, `create`, `add_sheet`) accept either format:
|
|
145
|
+
|
|
146
|
+
**`list[dict]`** — keys are column headers:
|
|
147
|
+
```python
|
|
148
|
+
[{"name": "Alice", "score": 95}, {"name": "Bob", "score": 82}]
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**`list[list]`** — raw rows with automatic header detection:
|
|
152
|
+
```python
|
|
153
|
+
[["name", "score"], ["Alice", 95], ["Bob", 82]]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Header detection for `list[list]` input:
|
|
157
|
+
|
|
158
|
+
| Sheet state | First row matches existing headers? | Result |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| Has data | Yes | Header row dropped, rest appended as data |
|
|
161
|
+
| Has data | No | All rows treated as data |
|
|
162
|
+
| Empty / being replaced | — | First row always becomes headers |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## API
|
|
167
|
+
|
|
168
|
+
### `ThaSheets(*, credentials_file=None, token_file=None)`
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
ThaSheets(
|
|
172
|
+
credentials_file: str | None = None, # path to client_secrets.json; None uses ADC
|
|
173
|
+
token_file: str | None = None, # override token cache path (OAuth2 only)
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The Google client is built lazily on first use and cached for the lifetime of the instance.
|
|
178
|
+
After any write, `sheets.rows` is set to the data rows that were written (as `list[dict]`).
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `read(*, spreadsheet_id=None, url=None, sheet_name=None) -> list[dict]`
|
|
183
|
+
|
|
184
|
+
Read all rows. The first row is treated as headers; each subsequent row becomes a `dict`.
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
rows = sheets.read(spreadsheet_id="spreadsheet-id")
|
|
188
|
+
rows = sheets.read(url="https://docs.google.com/spreadsheets/d/.../edit")
|
|
189
|
+
rows = sheets.read(spreadsheet_id="spreadsheet-id", sheet_name="Q1 Data")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### `append_rows(rows, *, spreadsheet_id=None, url=None, sheet_name=None) -> int`
|
|
195
|
+
|
|
196
|
+
Append rows to an existing sheet. Returns the number of rows appended.
|
|
197
|
+
|
|
198
|
+
- If the sheet is empty, the headers are written first.
|
|
199
|
+
- Missing keys in a row are filled with `""`.
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
count = sheets.append_rows(
|
|
203
|
+
[{"name": "Alice", "score": 95}],
|
|
204
|
+
spreadsheet_id="spreadsheet-id",
|
|
205
|
+
)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### `update_rows(rows, *, spreadsheet_id=None, url=None, sheet_name=None) -> int`
|
|
211
|
+
|
|
212
|
+
Overwrite all data in a sheet. Clears the sheet first, then writes headers + rows. Returns the number of rows written. Passing an empty list clears the sheet and returns `0`.
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
count = sheets.update_rows(
|
|
216
|
+
[{"name": "Alice", "score": 95}],
|
|
217
|
+
spreadsheet_id="spreadsheet-id",
|
|
218
|
+
)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### `upsert_rows(rows, *, key, spreadsheet_id=None, url=None, sheet_name=None, on_conflict="update_all") -> int`
|
|
224
|
+
|
|
225
|
+
Insert new rows and update existing ones matched by key. Returns the number of rows upserted.
|
|
226
|
+
|
|
227
|
+
- `key` — column name (str) or list of column names for composite keys
|
|
228
|
+
- New columns in incoming rows are appended to the sheet automatically
|
|
229
|
+
- `on_conflict` controls what happens when multiple existing rows match the same key:
|
|
230
|
+
- `"update_all"` (default) — update every matching row
|
|
231
|
+
- `"update_first"` — update only the first match
|
|
232
|
+
- `"update_last"` — update only the last match
|
|
233
|
+
- `"skip"` — leave duplicates untouched
|
|
234
|
+
- `"raise"` — raise `GoogleError`
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
count = sheets.upsert_rows(
|
|
238
|
+
[{"id": "1", "name": "Alice", "score": 99}],
|
|
239
|
+
key="id",
|
|
240
|
+
spreadsheet_id="spreadsheet-id",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Composite key
|
|
244
|
+
count = sheets.upsert_rows(rows, key=["year", "month"], spreadsheet_id="spreadsheet-id")
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### `create(title, *, rows=None, sheet_name="Sheet1") -> str`
|
|
250
|
+
|
|
251
|
+
Create a new spreadsheet. Returns the new spreadsheet's ID.
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
sid = sheets.create("My Report")
|
|
255
|
+
sid = sheets.create("My Report", rows=[{"col": "val"}], sheet_name="Data")
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### `delete(*, spreadsheet_id=None, url=None) -> None`
|
|
261
|
+
|
|
262
|
+
Permanently delete a spreadsheet.
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
sheets.delete(spreadsheet_id="spreadsheet-id")
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### `list_sheets(*, spreadsheet_id=None, url=None) -> list[str]`
|
|
271
|
+
|
|
272
|
+
Return the names of all worksheets in a spreadsheet.
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
names = sheets.list_sheets(spreadsheet_id="spreadsheet-id")
|
|
276
|
+
# ["Sheet1", "Q1 Data", "Archive"]
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### `add_sheet(sheet_name, *, spreadsheet_id=None, url=None, rows=None) -> None`
|
|
282
|
+
|
|
283
|
+
Add a new worksheet to an existing spreadsheet. Optionally write initial rows.
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
sheets.add_sheet("Q2 Data", spreadsheet_id="spreadsheet-id")
|
|
287
|
+
sheets.add_sheet("Q2 Data", spreadsheet_id="spreadsheet-id", rows=[{"col": "val"}])
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### `delete_sheet(sheet_name, *, spreadsheet_id=None, url=None) -> None`
|
|
293
|
+
|
|
294
|
+
Delete a worksheet from a spreadsheet.
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
sheets.delete_sheet("Archive", spreadsheet_id="spreadsheet-id")
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
### `share(email, *, spreadsheet_id=None, url=None, role="reader") -> None`
|
|
303
|
+
|
|
304
|
+
Share a spreadsheet with a user. `role` can be `"reader"`, `"writer"`, or `"owner"`.
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
sheets.share("colleague@example.com", spreadsheet_id="spreadsheet-id", role="writer")
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### `clear(*, spreadsheet_id=None, url=None, sheet_name=None) -> None`
|
|
313
|
+
|
|
314
|
+
Clear all data in a sheet. Resets `sheets.rows` to `[]`.
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
sheets.clear(spreadsheet_id="spreadsheet-id")
|
|
318
|
+
sheets.clear(spreadsheet_id="spreadsheet-id", sheet_name="Archive")
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## License
|
|
324
|
+
|
|
325
|
+
MIT
|