Skip to content

Batch

sppyte.batch

OData $batch support: send several REST requests in one round trip.

SharePoint 2016+ and Subscription Edition support /_api/$batch; SharePoint 2013 does not. Each sub-request gets its own BatchResponse; a failing sub-request does not fail the batch, so check BatchResponse.ok. Consecutive writes are grouped into one changeset (atomic on the server); reads are sent as individual parts. Order is preserved.

Example
batch = site.batch()
batch.get(f"{pets.path}/items", params={"$top": 5})
batch.post(
    f"{pets.path}/items", {"__metadata": {"type": pets.item_type}, "Title": "A"}
)
batch.merge(
    f"{pets.path}/items(7)",
    {"__metadata": {"type": pets.item_type}, "Title": "B"},
)
for res in batch.send():
    if not res.ok:
        print(res.status, res.error)

WRITE_METHODS module-attribute

WRITE_METHODS = frozenset({'POST', 'PATCH', 'MERGE', 'DELETE'})

Methods that are grouped into changesets.

BatchRequest dataclass

BatchRequest(method: str, url: str, headers: dict[str, str] = dict(), body: str | None = None)

One sub-request of a $batch call, with its URL already resolved.

Attributes:

Name Type Description
method str

Upper-cased HTTP method.

url str

Absolute URL of the sub-request.

headers dict[str, str]

Extra headers; defaults are added when the part is encoded.

body str | None

Serialised body, or None.

BatchResponse dataclass

BatchResponse(status: int, headers: dict[str, str], body: str, json: Any = None)

Response to one BatchRequest, in request order.

Attributes:

Name Type Description
status int

HTTP status of the part.

headers dict[str, str]

Response headers with lower-cased names.

body str

Raw body text.

json Any

Parsed body when the part is JSON and parses; otherwise None.

ok property

ok: bool

Whether the part has a 2xx status.

error property

error: SharePointErrorDetails | None

SharePoint's error object for a failed part, if the body carried one.

Batch

Batch(site: Site)

Collects sub-requests and sends them as one /_api/$batch call.

Obtain one from Site.batch(). Paths are site-relative (_api/...) or absolute URLs on the site's host; query options go in params. Builder methods return the batch so calls can be chained.

Parameters:

Name Type Description Default
site Site

The site to send the batch to.

required

add

add(method: str, path: str, *, params: Params = None, json: Any = None, body: str | None = None, headers: Mapping[str, str] | None = None) -> Batch

Queue a sub-request.

Default headers are Accept: application/json;odata=nometadata, Content-Type: application/json;odata=verbose when there is a body, and If-Match: * for PATCH / MERGE / DELETE; headers override them.

Parameters:

Name Type Description Default
method str

HTTP method (GET, POST, MERGE, PATCH or DELETE).

required
path str

Site-relative REST path (_api/...) or an absolute URL on the site's host.

required
params Params

OData query options appended to the URL.

None
json Any

JSON body, serialised for you.

None
body str | None

Pre-serialised body, sent as-is. Pass either json or body.

None
headers Mapping[str, str] | None

Extra headers for this sub-request.

None

Returns:

Type Description
Batch

This batch, so calls can be chained.

Raises:

Type Description
ValueError

if both json and body are given.

ConfigurationError

if an absolute path is not on the site's host.

get

get(path: str, *, params: Params = None, headers: Mapping[str, str] | None = None) -> Batch

Queue a GET; see add for the arguments.

post

post(path: str, json: Any = None, *, params: Params = None, body: str | None = None, headers: Mapping[str, str] | None = None) -> Batch

Queue a POST (create, or any action endpoint); see add for the arguments.

merge

merge(path: str, json: Any = None, *, params: Params = None, body: str | None = None, headers: Mapping[str, str] | None = None) -> Batch

Queue a MERGE (partial update; omitted fields are untouched); see add.

patch

patch(path: str, json: Any = None, *, params: Params = None, body: str | None = None, headers: Mapping[str, str] | None = None) -> Batch

Queue a PATCH (equivalent to MERGE on SharePoint); see add.

delete

delete(path: str, *, params: Params = None, headers: Mapping[str, str] | None = None) -> Batch

Queue a DELETE; see add for the arguments.

send

send(*, digest: str | None = None, **kwargs: Any) -> list[BatchResponse]

Send the queued requests in one POST /_api/$batch.

The batch itself raising (AuthError, SharePointError) means the whole call failed; a failed sub-request is reported through its own BatchResponse.ok. An empty batch returns [] without a request.

Parameters:

Name Type Description Default
digest str | None

Form digest to send instead of the managed one.

None
**kwargs Any

Passed to Site.request (e.g. timeout).

{}

Returns:

Type Description
list[BatchResponse]

One BatchResponse per request, in order.

Raises:

Type Description
ResponseFormatError

if the response is not multipart or the part count differs.

new_boundary

new_boundary(prefix: str) -> str

Return a unique multipart boundary, e.g. batch_<uuid>.

build_batch_body

build_batch_body(requests: list[BatchRequest], boundary: str) -> str

Build the multipart body for /_api/$batch.

Reads are individual parts; each run of consecutive writes is wrapped in one changeset, as OData requires. Order is preserved so responses can be matched to requests.

multipart_boundary

multipart_boundary(content_type: str | None) -> str | None

Extract boundary=... from a multipart Content-Type header, or None.

parse_batch_response

parse_batch_response(body: str, content_type: str | None) -> list[BatchResponse]

Parse a $batch response body into one BatchResponse per sub-request.

Changeset responses are flattened; order is preserved.

Raises:

Type Description
ResponseFormatError

if the response is not multipart/mixed.