gformlib.client

Main client for the Google Forms API.

This module exposes GoogleFormsClient, the primary public interface of the gformlib library. The client handles authentication, delegates request-body construction to FormBuilder, and wraps the raw Google API responses in typed FormInfo objects.

Supported authentication strategies

  1. Service Account (server-to-server) – GoogleFormsClient.from_service_account()

  2. OAuth 2.0 installed appGoogleFormsClient.from_oauth_credentials()

  3. Pre-built credentials – pass any google.oauth2 credentials object directly to the constructor.

Required Google API scopes

  • https://www.googleapis.com/auth/forms.body – create and modify forms

  • https://www.googleapis.com/auth/drive.file – required for file-upload questions

Example:

from gformlib import GoogleFormsClient

client = GoogleFormsClient.from_service_account("service_account.json")
info = client.create_form(
    {
        "title": "Quick Survey",
        "description": "Tell us what you think.",
        "questions": [
            {"title": "Your name", "type": "short_answer", "required": True},
            {
                "title": "Rating",
                "type": "scale",
                "low": 1,
                "high": 5,
                "low_label": "Poor",
                "high_label": "Excellent",
            },
        ],
    }
)
print(info.responder_uri)
gformlib.client.DEFAULT_SCOPES: List[str] = ['https://www.googleapis.com/auth/forms.body', 'https://www.googleapis.com/auth/drive.file']

Default OAuth scopes required by the Google Forms API.

class gformlib.client.GoogleFormsClient(credentials, scopes=None)[source]

Bases: object

High-level client for creating and managing Google Forms.

Do not instantiate this class directly with the constructor unless you already have a google.oauth2 credentials object. Use one of the class-method factories instead:

Parameters:
  • credentials (Any) – Any google.oauth2 credentials object that has been authorised for the required scopes.

  • scopes (Optional[List[str]]) – OAuth scopes to request. Defaults to DEFAULT_SCOPES.

Raises:

AuthenticationError – If the credentials object is None or invalid.

Example:

from google.oauth2.service_account import Credentials
from gformlib import GoogleFormsClient

creds = Credentials.from_service_account_file("sa.json", scopes=[...])
client = GoogleFormsClient(credentials=creds)
classmethod from_service_account(service_account_file, scopes=None, subject=None)[source]

Create a client authenticated as a Google Service Account.

This is the recommended approach for server-side applications that do not have a logged-in user context.

Parameters:
  • service_account_file (str | PathLike[str]) – Path to the service account JSON key file downloaded from the Google Cloud Console.

  • scopes (List[str] | None) – OAuth scopes to request. Defaults to DEFAULT_SCOPES.

  • subject (str | None) – The email address of the user account to impersonate (requires Domain-Wide Delegation to be configured).

Returns:

An authenticated GoogleFormsClient.

Raises:
Return type:

GoogleFormsClient

Example:

client = GoogleFormsClient.from_service_account(
    "path/to/service_account.json"
)
classmethod from_service_account_info(info, scopes=None, subject=None)[source]

Create a client from a service account info dict.

Useful when credentials are stored in environment variables or a secrets manager rather than on the file system.

Parameters:
  • info (Dict[str, Any]) – Service account info dict (the parsed contents of a service account JSON key file).

  • scopes (List[str] | None) – OAuth scopes to request. Defaults to DEFAULT_SCOPES.

  • subject (str | None) – Email address of the user to impersonate (requires Domain-Wide Delegation).

Returns:

An authenticated GoogleFormsClient.

Raises:

AuthenticationError – If info is invalid.

Return type:

GoogleFormsClient

Example:

import json, os
info = json.loads(os.environ["SERVICE_ACCOUNT_JSON"])
client = GoogleFormsClient.from_service_account_info(info)
classmethod from_oauth_credentials(client_secrets_file, token_file=None, scopes=None)[source]

Create a client using the OAuth 2.0 installed-app flow.

On the first run the user is prompted to grant access in their browser. The resulting token is saved to token_file so subsequent runs are non-interactive.

Parameters:
  • client_secrets_file (str | PathLike[str]) – Path to the client_secrets.json file downloaded from the Google Cloud Console (OAuth 2.0 client ID of type Desktop app).

  • token_file (str | PathLike[str] | None) – Path where the OAuth token will be cached. Defaults to "token.json" in the current directory.

  • scopes (List[str] | None) – OAuth scopes to request. Defaults to DEFAULT_SCOPES.

Returns:

An authenticated GoogleFormsClient.

Raises:
Return type:

GoogleFormsClient

Example:

client = GoogleFormsClient.from_oauth_credentials(
    "client_secrets.json",
    token_file="my_token.json",
)
create_form(config)[source]

Create a new Google Form from a configuration dict or FormConfig.

This method:

  1. Validates config (if it is a dict) with parse_form_config().

  2. Calls forms().create() to create the bare form skeleton.

  3. Calls forms().batchUpdate() to add questions and description.

Parameters:

config (Dict[str, Any] | FormConfig) – Either a raw configuration dict (see Quickstart) or a pre-built FormConfig object.

Returns:

A FormInfo with the form’s ID, responder URL, and other metadata.

Raises:
Return type:

FormInfo

Example:

info = client.create_form(
    {
        "title": "My Survey",
        "questions": [
            {"title": "Name", "type": "short_answer", "required": True},
        ],
    }
)
print(info.responder_uri)
update_form(form_id, config)[source]

Update an existing Google Form.

Modifies the title, description, and/or appends new questions to an existing form identified by form_id. Only the fields explicitly set in config are changed; everything else is left untouched.

This method:

  1. Validates config (if it is a dict) with parse_update_config().

  2. If new questions are being added, calls forms().get() first to determine the current item count so that questions are appended at the correct position.

  3. Calls forms().batchUpdate() with the generated request list.

  4. Returns a FormInfo reflecting the updated form state.

Parameters:
  • form_id (str) – The ID of the form to update.

  • config (Dict[str, Any] | UpdateFormConfig) –

    Either a raw update configuration dict or a pre-built UpdateFormConfig object.

    Recognised dict keys:

    • "title" (str) – new form title.

    • "description" (str) – new form description.

    • "add_questions" (list) – question dicts to append.

Returns:

A FormInfo with the updated metadata.

Raises:
Return type:

FormInfo

Example:

info = client.update_form(
    "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
    {
        "title": "Revised Survey",
        "add_questions": [
            {"title": "Any comments?", "type": "paragraph"},
        ],
    },
)
print(info.title)
get_form(form_id)[source]

Retrieve the full metadata of an existing form.

Parameters:

form_id (str) – The ID of the form to retrieve.

Returns:

The raw JSON response dict from the forms().get() call.

Raises:

APIError – If the form is not found or the API returns an error.

Return type:

Dict[str, Any]

Example:

data = client.get_form("1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms")
list_responses(form_id, page_size=100, filter_str=None)[source]

Retrieve all responses submitted to a form.

Automatically handles pagination via the nextPageToken returned by the API.

Parameters:
  • form_id (str) – The ID of the form to retrieve responses for.

  • page_size (int) – Maximum number of responses per API page. Defaults to 100 (the API maximum).

  • filter_str (str | None) – Optional filter string in the format accepted by the Forms API (e.g. "timestamp > 2024-01-01T00:00:00Z").

Returns:

A list of raw response dicts from the API.

Raises:

APIError – If the API call fails.

Return type:

List[Dict[str, Any]]

Example:

responses = client.list_responses(form_id)
for r in responses:
    print(r["responseId"])
delete_form(form_id)[source]

Delete a form by moving it to the Google Drive trash.

The Google Forms API does not expose a direct delete endpoint; this method calls the Drive API to trash the backing document.

Parameters:

form_id (str) – The ID of the form (same as the Drive file ID).

Raises:

APIError – If the Drive API call fails.

Return type:

None

Note

This requires the https://www.googleapis.com/auth/drive.file scope to be included in the credentials.

Example:

client.delete_form("1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms")