PloneClient#

PloneClient holds the connection to one Plone site.

Parameters#

Parameter

Type

Default

Meaning

url

str

required

URL of the site root, without ++api++.

username

str

""

Login name; empty for anonymous access.

password

str

""

Password of username.

token

str

""

A JWT issued beforehand, sent instead of a password.

auth_method

"basic" or "jwt"

"basic"

How username and password authenticate.

auth

httpx.Auth or None

None

A custom authentication flow; overrides the three above.

api_prefix

str

"++api++"

Traversal prefix of the REST API.

timeout

float

30.0

Seconds to wait for the site.

verify

bool, str, or ssl.SSLContext

True

Verify TLS certificates; a path of a CA bundle, a file or a directory, replaces the default certificates.

retries

int

3

Retries of idempotent requests.

backoff

float

0.5

Base of the exponential delay between retries, in seconds.

headers

mapping or None

None

Extra headers sent with every request.

read_only

bool

False

Refuse every request that could change the site.

dry_run

bool

False

Record changing requests in dry_run_log instead of sending them.

transport

httpx.BaseTransport or None

None

A custom transport, for tests.

Constructors#

Constructor

Reads

PloneClient(url, …)

The arguments.

from_env()

<prefix>URL, <prefix>USERNAME or <prefix>USER, <prefix>PASSWORD, <prefix>TOKEN, <prefix>AUTH_METHOD, <prefix>API_PREFIX, <prefix>TIMEOUT, <prefix>VERIFY, <prefix>RETRIES, <prefix>BACKOFF, <prefix>READ_ONLY; the prefix defaults to PLONE_CLIENT_.

from_profile()

A profile from the configuration file, and its secret.

Keyword arguments passed to either class method win over the settings it reads.

Retries#

Failure

Requests retried

Connection refused or reset before sending

All

429, 502, 503, 504

GET, HEAD, OPTIONS, PUT, DELETE

Any other status

None

The delay between retries is Retry-After when the site sends it, and backoff * 2 ** attempt otherwise.

Safety switches#

Switch

Changing requests

Reads

Always allowed

read_only=True

Raise PloneReadOnlyError before sending

Sent

POST to @querystring-search, @login, @login-renew

dry_run=True

Recorded in dry_run_log; the call returns the record

Sent

Same as above

Methods#

class plone_client.PloneClient(url, *, username='', password='', token='', auth_method='basic', auth=None, api_prefix='++api++', timeout=30.0, verify=True, retries=3, backoff=0.5, headers=None, read_only=False, dry_run=False, frontend_url='', transport=None)[source]#

Bases: object

Client for one Plone site, through plone.restapi.

Paths given to the client and its managers can be written as site paths (/news/item), as absolute URLs of the site (the @id values the API returns) or as API URLs (with ++api++). They are all mapped to the same API URL.

Parameters:
  • url (str) – URL of the site root, such as https://example.org or http://localhost:8080/Plone.

  • username (str) – Login name.

  • password (str) – Password.

  • token (str) – JWT issued beforehand; used instead of the username and password.

  • auth_method (Literal['basic', 'jwt']) – basic (default) sends the username and password on every request; jwt logs in with @login and sends the token.

  • auth (Auth | None) – Any httpx.Auth; overrides the credentials above.

  • api_prefix (str) – Traversal prefix of the REST API. ++api++ works with and without a Volto frontend in front of the backend; use an empty string to rely on the Accept header only.

  • timeout (float) – Seconds to wait for the site.

  • verify (bool | str | SSLContext) – Verify TLS certificates. A path (a file or a directory) verifies them against that CA bundle instead of the default one; an ssl.SSLContext is used as given.

  • retries (int) – Times a request is repeated after a network error, or after a 429/502/503/504 answer to an idempotent method.

  • backoff (float) – Base delay in seconds between retries; doubles each time.

  • headers (Mapping[str, str] | None) – Extra headers sent with every request.

  • read_only (bool) – Refuse every request that could change the site.

  • dry_run (bool) – Do not send requests that could change the site; log them and return a description of what would have been sent instead.

  • frontend_url (str) – URL of the Volto frontend, for services that Volto serves itself (@blocks-schema); the site URL by default, which is right when url is the frontend.

  • transport (BaseTransport | None) – Custom httpx transport, mostly for tests.

dry_run_log: list[dict[str, Any]]#

Requests skipped because of dry_run, oldest first.

classmethod from_env(prefix='PLONE_CLIENT_', **overrides)[source]#

Build a client from environment variables.

Reads <prefix>URL, <prefix>USERNAME, <prefix>PASSWORD, <prefix>TOKEN, <prefix>AUTH_METHOD, <prefix>TIMEOUT, <prefix>VERIFY, <prefix>RETRIES, <prefix>BACKOFF, <prefix>READ_ONLY and <prefix>FRONTEND_URL; see settings_from_env().

Parameters:
  • prefix (str) – Prefix of the variable names.

  • overrides (Any) – Keyword arguments that win over the environment.

Returns:

A configured client.

Raises:

PloneConfigurationError – If no URL is set.

Return type:

Self

classmethod from_profile(name='', *, config_file=None, **overrides)[source]#

Build a client from a named profile.

Profiles live in the configuration file (see plone_client.profiles) and their secrets in the operating system’s keyring.

Parameters:
  • name (str) – Profile name; empty selects the current profile.

  • config_file (Path | None) – Configuration file; defaults to the user’s.

  • overrides (Any) – Keyword arguments that win over the profile.

Returns:

A configured client.

Raises:

PloneConfigurationError – If the profile or its secret is missing.

Return type:

Self

property api_root: str#

Absolute URL of the API root.

path(ref)[source]#

Site path for a path or a URL of the site.

Parameters:

ref (str) – /news, news, https://example.org/news or https://example.org/++api++/news. A query string is dropped.

Returns:

Path starting with /, without a trailing slash (/ for the site root).

Raises:

ValueError – If ref is a URL of another site.

Return type:

str

api_url(ref)[source]#

Absolute API URL for a path or a URL of the site.

Parameters:

ref (str) – See path().

Returns:

The URL the request is sent to.

Return type:

str

site_url(ref)[source]#

Absolute URL of the site, as the API writes it in @id.

Parameters:

ref (str) – See path().

Returns:

The URL without ++api++.

Return type:

str

token()[source]#

A JWT for the client’s user, for services that only take tokens.

Volto’s own services, such as @blocks-schema, read a Bearer token and not basic authentication. A token given to the client is returned as is; otherwise the client logs in with @login once and keeps the token.

Returns:

The token, or an empty string for an anonymous client.

Raises:

PloneAuthenticationError – If the site refuses the credentials.

Return type:

str

recording()[source]#

Record the requests sent, or skipped, inside a with block.

Used by plone_client.operations to report every request an operation made. Recordings can be nested.

Returns:

A list that receives one entry per request: method, url, status and, for skipped requests, dry_run.

Return type:

Iterator[list[dict[str, Any]]]

request(method, ref='/', *, params=None, json=None, content=None, headers=None, raise_for_status=True, timeout=None)[source]#

Send a request to the site.

This is the escape hatch for services the managers do not cover, such as the ones added by add-ons.

Parameters:
  • method (str) – HTTP method.

  • ref (str) – Path or URL of the site, @ services included (/news/@workflow/publish).

  • params (Mapping[str, Any] | list[tuple[str, Any]] | None) – Query parameters (see encode_params()).

  • json (Any) – Body, serialized as JSON.

  • content (bytes | None) – Raw body, instead of json.

  • headers (Mapping[str, str] | None) – Extra headers for this request.

  • raise_for_status (bool) – Raise PloneAPIError for error answers.

  • timeout (float | None) – Seconds to wait, instead of the client’s timeout.

Returns:

The response.

Raises:
Return type:

Response

frontend_request(method, ref='/', *, headers=None, raise_for_status=True)[source]#

Send a read request to the Volto frontend, with a Bearer token.

For the services that Volto serves itself rather than plone.restapi, such as @blocks-schema. The request goes to frontend_url, without ++api++.

Parameters:
  • method (str) – GET or HEAD.

  • ref (str) – Site path with the service, or a URL of the frontend.

  • headers (Mapping[str, str] | None) – Extra headers for this request.

  • raise_for_status (bool) – Raise PloneAPIError for error answers.

Returns:

The response.

Raises:

ValueError – If the method could change the site.

Return type:

Response

get(ref='/', **params)[source]#

GET a path and return the JSON body.

Parameters:
  • ref (str) – Path or URL of the site.

  • params (Any) – Query parameters.

Returns:

The parsed body.

Return type:

Any

post(ref, data=None, **kwargs)[source]#

POST JSON to a path and return the JSON body.

Parameters:
  • ref (str) – Path or URL of the site.

  • data (Any) – Body.

  • kwargs (Any) – Extra arguments for request().

Returns:

The parsed body, or None.

Return type:

Any

patch(ref, data=None, **kwargs)[source]#

PATCH a path with JSON and return the JSON body.

Parameters:
  • ref (str) – Path or URL of the site.

  • data (Any) – Body.

  • kwargs (Any) – Extra arguments for request().

Returns:

The parsed body, or None (plone.restapi usually answers 204).

Return type:

Any

put(ref, data=None, **kwargs)[source]#

PUT JSON to a path and return the JSON body.

Parameters:
  • ref (str) – Path or URL of the site.

  • data (Any) – Body.

  • kwargs (Any) – Extra arguments for request().

Returns:

The parsed body, or None.

Return type:

Any

delete(ref, data=None, **kwargs)[source]#

DELETE a path, with an optional JSON body.

Parameters:
  • ref (str) – Path or URL of the site.

  • data (Any) – Body; some services (@aliases, @relations) read one.

  • kwargs (Any) – Extra arguments for request().

Returns:

The parsed body, or None.

Return type:

Any

iter_batches(ref, params=None, *, key='items')[source]#

Yield every page of a batched answer, following batching.next.

Parameters:
  • ref (str) – Path or URL of a batched service (/@search, a folder, @users…).

  • params (Mapping[str, Any] | list[tuple[str, Any]] | None) – Query parameters of the first page.

  • key (str) – Key of the list in each page.

Returns:

Each page, as returned by the site.

Return type:

Iterator[dict[str, Any]]

iter_items(ref, params=None, *, key='items', limit=None)[source]#

Yield the items of every page of a batched answer.

Parameters:
  • ref (str) – Path or URL of a batched service.

  • params (Mapping[str, Any] | list[tuple[str, Any]] | None) – Query parameters of the first page.

  • key (str) – Key of the list in each page.

  • limit (int | None) – Stop after this many items.

Returns:

Each item.

Return type:

Iterator[dict[str, Any]]

exists(ref)[source]#

Say whether there is an item at a path.

Parameters:

ref (str) – Path or URL of the site.

Returns:

True if the item exists, False on 404.

Raises:

PloneAPIError – For any other error, such as 401.

Return type:

bool

close()[source]#

Close the HTTP connections.

Return type:

None

plone_client.client.encode_params(params)[source]#

Encode query parameters the way plone.restapi reads them.

  • None values are dropped;

  • booleans become true / false;

  • lists and tuples become repeated keys (portal_type=Document&portal_type=News Item);

  • nested mappings are flattened with dots, which is how catalog query options are written ({"path": {"query": "/news", "depth": 1}} becomes path.query=/news&path.depth=1).

Parameters:

params (Mapping[str, Any] | list[tuple[str, Any]] | None) – Parameters as a mapping or as a list of pairs.

Returns:

Encoded key/value pairs.

Return type:

list[tuple[str, str | int | float | bool | None]]