Photos¶
Resumable upload facade and Google Photo Library port protocol.
q2google.photos
¶
High-level Google Photos Library helpers built on :mod:q2google.gphotos.
Keeps direct gphotos imports localized to this module; callers should use
:class:GooglePhotosClient, :class:GooglePhotoLibraryPort, and re-exported types.
GooglePhotoLibraryPort
¶
Bases: Protocol
Protocol for Library v1 resumable upload and mediaItems:batchCreate.
Implemented by :class:~q2google.gphotos.api.GooglePhotosAPI when used through
:class:GooglePhotosClient.
create_media_item(media_item: MediaItemBatchCreateRequest) -> MediaItemBatchCreateResponse
async
¶
Create library media items from finalized upload tokens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
media_item
|
MediaItemBatchCreateRequest
|
Batch request wrapping |
required |
Returns:
| Type | Description |
|---|---|
MediaItemBatchCreateResponse
|
API response with per-item status and identifiers. |
Source code in q2google/photos.py
init_upload_session(content_type: str, content_length: int) -> ResumableUploadSession
async
¶
Start a resumable upload and return the session (URL, token, chunk rules).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content_type
|
str
|
MIME type of the bytes that will be uploaded. |
required |
content_length
|
int
|
Total size in bytes of the object to upload. |
required |
Returns:
| Type | Description |
|---|---|
ResumableUploadSession
|
Session descriptor including |
Source code in q2google/photos.py
upload_chunk(url: str, command: str, offset: int, content: bytes) -> ResumableUploadSession
async
¶
POST one chunk to the resumable upload URL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
|
required |
command
|
str
|
Upload command header value (for example |
required |
offset
|
int
|
Byte offset of this chunk in the full object. |
required |
content
|
bytes
|
Raw chunk bytes. |
required |
Returns:
| Type | Description |
|---|---|
ResumableUploadSession
|
Updated session state; the last call should include the upload token |
ResumableUploadSession
|
needed for |
Source code in q2google/photos.py
GooglePhotosAPI(credentials: GooglePhotosOAuth, timeout: float = 600.0)
¶
Thin aiohttp wrapper around selected Google Photos Library v1 endpoints.
Instantiate and use async with GooglePhotosAPI(...) as api to obtain a live session.
HTTP error responses are surfaced via response.raise_for_status() (aiohttp client errors).
Create a client; the HTTP session starts on async context enter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials
|
GooglePhotosOAuth
|
OAuth credentials carrying a valid access token. |
required |
timeout
|
float
|
Per-request total timeout in seconds. Each resumable chunk is one request; large uploads often need a generous value. |
600.0
|
Source code in q2google/gphotos/api.py
base_url: str
property
¶
Root URL for Library API v1 resources for this client.
__aenter__() -> GooglePhotosAPI
async
¶
Open the underlying aiohttp client session.
__aexit__(exc_type: type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None) -> None
async
¶
Close the client session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc_type
|
type[BaseException] | None
|
Exception type if the context exited due to an error, else |
required |
exc
|
BaseException | None
|
Active exception instance when exiting with an error, else |
required |
tb
|
TracebackType | None
|
Traceback associated with |
required |
Source code in q2google/gphotos/api.py
create_media_item(media_item: MediaItemBatchCreateRequest) -> MediaItemBatchCreateResponse
async
¶
Call mediaItems:batchCreate with the given payload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
media_item
|
MediaItemBatchCreateRequest
|
Batch create request body. |
required |
Returns:
| Type | Description |
|---|---|
MediaItemBatchCreateResponse
|
API batch create response. |
Source code in q2google/gphotos/api.py
get_media_item(media_item_id: str) -> dict[str, Any]
async
¶
GET a single media item by id (mediaItems/{mediaItemId}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
media_item_id
|
str
|
Library media item id. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Parsed JSON object as returned by the API (shape matches the MediaItem resource). |
Source code in q2google/gphotos/api.py
init_upload_session(content_type: str, content_length: int) -> ResumableUploadSession
async
¶
Start a resumable upload; maps response headers to a session model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
content_type
|
str
|
MIME type of the file to upload. |
required |
content_length
|
int
|
Total byte size of the file. |
required |
Returns:
| Type | Description |
|---|---|
ResumableUploadSession
|
Parsed upload session metadata from response headers. |
Source code in q2google/gphotos/api.py
query_upload_status(url: str) -> ResumableUploadSession
async
¶
Send an upload query command and return parsed header state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
Resumable upload URL to query. |
required |
Returns:
| Type | Description |
|---|---|
ResumableUploadSession
|
Parsed session metadata from response headers. |
Source code in q2google/gphotos/api.py
upload_chunk(url: str, command: str, offset: int, content: bytes) -> ResumableUploadSession
async
¶
POST one chunk of a resumable upload.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
Resumable upload URL from a prior session. |
required |
command
|
str
|
Google resumable upload command (e.g. |
required |
offset
|
int
|
Byte offset for this chunk. |
required |
content
|
bytes
|
Raw chunk bytes. |
required |
Returns:
| Type | Description |
|---|---|
ResumableUploadSession
|
Parsed session state; when the upload completes, |
ResumableUploadSession
|
the response body. |
Source code in q2google/gphotos/api.py
GooglePhotosClient(api: GooglePhotoLibraryPort, chunk_granularity_multiplier: int = 4)
dataclass
¶
Stream local files via resumable upload and register them with batchCreate.
Attributes:
| Name | Type | Description |
|---|---|---|
api |
GooglePhotoLibraryPort
|
Async port implementing upload session and batch create (typically |
chunk_granularity_multiplier |
int
|
Factor applied to server |
create_media_items(media_items: list[NewMediaItem]) -> list[MediaItemBatchCreateResponse]
async
¶
Call mediaItems:batchCreate in slices of at most LIBRARY_BATCH_SIZE items.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
media_items
|
list[NewMediaItem]
|
Full list of |
required |
Returns:
| Type | Description |
|---|---|
list[MediaItemBatchCreateResponse]
|
One |
Source code in q2google/photos.py
create_media_items_from_upload_sessions(file_names: Sequence[str], sessions: Sequence[ResumableUploadSession]) -> list[MediaItemBatchCreateResponse]
async
¶
Pair each local filename with its finalized upload session and call batchCreate.
file_names and sessions must align (same length, same order as uploads).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_names
|
Sequence[str]
|
Display names for created media items. |
required |
sessions
|
Sequence[ResumableUploadSession]
|
Finalized upload sessions whose |
required |
Returns:
| Type | Description |
|---|---|
list[MediaItemBatchCreateResponse]
|
Batch create responses from |
Source code in q2google/photos.py
upload_file_path(file_name: str, path: Path) -> ResumableUploadSession
async
¶
Stream path to Google using resumable upload chunking.
Chunk size is chunk_granularity_multiplier * granularity from the
session when present; the final chunk may be smaller and uses the
"upload, finalize" command.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
file_name
|
str
|
Logical name used only for MIME guessing (not sent as path). |
required |
path
|
Path
|
Readable file on disk whose size defines |
required |
Returns:
| Type | Description |
|---|---|
ResumableUploadSession
|
Final |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the session response omits chunk granularity metadata. |
ValueError
|
If |
Source code in q2google/photos.py
GooglePhotosOAuth(client_secrets_file: str, scopes: list[PhotosScopes], token_file: str | None = None)
dataclass
¶
Load, refresh, or obtain Google OAuth credentials for Photos scopes.
Attributes:
| Name | Type | Description |
|---|---|---|
client_secrets_file |
str
|
Path to the Google OAuth client secrets JSON (installed app). |
scopes |
list[PhotosScopes]
|
API scopes to request; values are sent to the authorization server. |
token_file |
str | None
|
Optional path to persist the authorized user token; parent dirs are created on save. If omitted, tokens are only kept in memory. |
authorize_interactive() -> Credentials
¶
Run the local-server OAuth flow and optionally persist the token.
Returns:
| Type | Description |
|---|---|
Credentials
|
Newly authorized credentials. |
Source code in q2google/gphotos/auth.py
ensure_credentials() -> Credentials
¶
Return stored valid credentials, or complete an interactive authorization.
Returns:
| Type | Description |
|---|---|
Credentials
|
Credentials that are valid for API calls (refreshed from disk when possible). |
Raises:
| Type | Description |
|---|---|
Various ``google_auth`` exceptions
|
If the OAuth flow or refresh fails in a way not
handled by :meth: |
Source code in q2google/gphotos/auth.py
load_saved_credentials() -> Credentials | None
¶
Load credentials from disk and refresh if expired.
Returns:
| Type | Description |
|---|---|
Credentials | None
|
Valid or refreshed credentials, or |
Credentials | None
|
if |
Credentials | None
|
or if stored credentials cannot be used. |
Source code in q2google/gphotos/auth.py
MediaItemBatchCreateRequest
¶
MediaItemBatchCreateResponse
¶
Bases: BaseModel
Response body from mediaItems:batchCreate.
Examples:
newMediaItemResults: list[NewMediaItemResult]
instance-attribute
¶
Parallel list of results aligned with the request newMediaItems order.
NewMediaItem
¶
Bases: BaseModel
One new media item entry inside a batch create request.
Examples:
PhotosScopes
¶
Bases: str, Enum
OAuth 2.0 scope URLs accepted by the Google Photos Library API.
Examples:
LIBRARY_APPENDONLY = 'https://www.googleapis.com/auth/photoslibrary.appendonly'
class-attribute
instance-attribute
¶
Create albums and upload media; cannot read or delete unrelated library content.
LIBRARY_EDIT_APP_CREATED = 'https://www.googleapis.com/auth/photoslibrary.edit.appcreateddata'
class-attribute
instance-attribute
¶
Edit and delete media and albums created by this app.
LIBRARY_READONLY_APP_CREATED = 'https://www.googleapis.com/auth/photoslibrary.readonly.appcreateddata'
class-attribute
instance-attribute
¶
Read media and albums created by this app only.
ResumableUploadSession
¶
Bases: BaseModel
State parsed from Google resumable upload response headers (and optional body token).
Examples:
>>> ResumableUploadSession.model_validate(
... {
... "X-Goog-Upload-Status": "active",
... "X-GUploader-UploadID": "upload-id",
... "Date": "Mon, 01 Jan 2024 00:00:00 GMT",
... }
... )
date: datetime = Field(alias='Date')
class-attribute
instance-attribute
¶
Response Date header value, parsed to UTC-aware naive or as returned.
granularity: int | None = Field(alias='X-Goog-Upload-Chunk-Granularity', default=None)
class-attribute
instance-attribute
¶
Preferred chunk size in bytes, if the server advertises one.
status: str = Field(alias='X-Goog-Upload-Status')
class-attribute
instance-attribute
¶
Upload lifecycle status string from X-Goog-Upload-Status.
upload_id: str = Field(alias='X-GUploader-UploadID')
class-attribute
instance-attribute
¶
Server upload identifier from X-GUploader-UploadID.
upload_token: str | None = None
class-attribute
instance-attribute
¶
Raw upload token from the response body when the upload is complete.
upload_url: str | None = Field(alias='X-Goog-Upload-URL', default=None)
class-attribute
instance-attribute
¶
URL to POST the next chunk or query, when provided by the server.
parse_date(v: str) -> datetime
¶
Parse RFC 2822-style date strings from upload responses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v
|
str
|
Date header value as returned by Google. |
required |
Returns:
| Type | Description |
|---|---|
datetime
|
Parsed datetime. |
Source code in q2google/gphotos/models.py
SimpleMediaItem
¶
Bases: BaseModel
Minimal media reference for batch create (upload token plus optional filename).
Examples: