Add create_bullet_list operation to batch_update_doc

Exposes native Google Docs createParagraphBullets and
deleteParagraphBullets APIs via the batch operation manager.
Supports UNORDERED (bullets), ORDERED (numbered), and NONE
(remove formatting) list types with optional nesting levels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Rein Lemmens
2026-03-12 21:06:34 +01:00
parent 38ad39bea6
commit a9db471345
3 changed files with 65 additions and 0 deletions

View File

@@ -647,6 +647,33 @@ def create_bullet_list_request(
return requests
def create_delete_bullet_list_request(
start_index: int,
end_index: int,
doc_tab_id: Optional[str] = None,
) -> Dict[str, Any]:
"""
Create a deleteParagraphBullets request to remove bullet/list formatting.
Args:
start_index: Start of the paragraph range
end_index: End of the paragraph range
doc_tab_id: Optional ID of the tab to target
Returns:
Dictionary representing the deleteParagraphBullets request
"""
range_obj = {"startIndex": start_index, "endIndex": end_index}
if doc_tab_id:
range_obj["tabId"] = doc_tab_id
return {
"deleteParagraphBullets": {
"range": range_obj,
}
}
def validate_operation(operation: Dict[str, Any]) -> tuple[bool, str]:
"""
Validate a batch operation dictionary.
@@ -671,6 +698,7 @@ def validate_operation(operation: Dict[str, Any]) -> tuple[bool, str]:
"insert_table": ["index", "rows", "columns"],
"insert_page_break": ["index"],
"find_replace": ["find_text", "replace_text"],
"create_bullet_list": ["start_index", "end_index"],
"insert_doc_tab": ["title", "index"],
"delete_doc_tab": ["tab_id"],
"update_doc_tab": ["tab_id", "title"],

View File

@@ -872,6 +872,10 @@ async def batch_update_doc(
insert_page_break- required: index (int)
find_replace - required: find_text (str), replace_text (str)
optional: match_case (bool, default false)
create_bullet_list - required: start_index (int), end_index (int)
optional: list_type ('UNORDERED'|'ORDERED'|'NONE', default UNORDERED),
nesting_level (0-8), paragraph_start_indices (list[int])
Use list_type='NONE' to remove existing bullet/list formatting
insert_doc_tab - required: title (str), index (int)
optional: parent_tab_id (str)
delete_doc_tab - required: tab_id (str)

View File

@@ -17,6 +17,8 @@ from gdocs.docs_helpers import (
create_find_replace_request,
create_insert_table_request,
create_insert_page_break_request,
create_bullet_list_request,
create_delete_bullet_list_request,
create_insert_doc_tab_request,
create_delete_doc_tab_request,
create_update_doc_tab_request,
@@ -302,6 +304,31 @@ class BatchOperationManager:
)
description = f"find/replace '{op['find_text']}''{op['replace_text']}'"
elif op_type == "create_bullet_list":
list_type = op.get("list_type", "UNORDERED")
if list_type not in ("UNORDERED", "ORDERED", "NONE"):
raise ValueError(
f"Invalid list_type '{list_type}'. Must be 'UNORDERED', 'ORDERED', or 'NONE'"
)
if list_type == "NONE":
request = create_delete_bullet_list_request(
op["start_index"], op["end_index"], tab_id
)
description = f"remove bullets {op['start_index']}-{op['end_index']}"
else:
request = create_bullet_list_request(
op["start_index"],
op["end_index"],
list_type,
op.get("nesting_level"),
op.get("paragraph_start_indices"),
tab_id,
)
style = "bulleted" if list_type == "UNORDERED" else "numbered"
description = f"create {style} list {op['start_index']}-{op['end_index']}"
if op.get("nesting_level"):
description += f" (nesting level {op['nesting_level']})"
elif op_type == "insert_doc_tab":
request = create_insert_doc_tab_request(
op["title"], op["index"], op.get("parent_tab_id")
@@ -328,6 +355,7 @@ class BatchOperationManager:
"insert_table",
"insert_page_break",
"find_replace",
"create_bullet_list",
"insert_doc_tab",
"delete_doc_tab",
"update_doc_tab",
@@ -461,6 +489,11 @@ class BatchOperationManager:
"optional": ["match_case"],
"description": "Find and replace text throughout document",
},
"create_bullet_list": {
"required": ["start_index", "end_index"],
"optional": ["list_type", "nesting_level", "paragraph_start_indices"],
"description": "Apply or remove native bullet/numbered list formatting (list_type: UNORDERED, ORDERED, or NONE to remove; nesting_level: 0-8)",
},
"insert_doc_tab": {
"required": ["title", "index"],
"description": "Insert a new document tab with given title at specified index",