Skip to main content
Questa pagina documenta squarecloud-api 5.0, una riscrittura dell’SDK. Arrivi dalla v4? Leggi la guida alla migrazione v4 → v5.

Requisiti

Il pacchetto non ha dipendenze a runtime (solo la libreria standard: http.client, json, ssl) ed è completamente tipizzato (py.typed): le risposte sono TypedDict che il tuo editor e il tuo type checker comprendono.

Installazione

Il pacchetto si installa come squarecloud-api e si importa come squarecloud. La versione installata è squarecloud.__version__.

Chiave API e scope

Crea una chiave su squarecloud.app/account/security. L’SDK la invia così com’è nell’header Authorization (senza prefisso Bearer). Una chiave può essere limitata a determinati scope (apps:read, apps:deploy, apps:control, ai:chat, …) e ad app o database specifici:
  • Una chiamata al di fuori di questi limiti solleva un SquareCloudAPIError con 403 MISSING_SCOPE o RESOURCE_NOT_ALLOWED.
  • I metodi di elenco (account.me(), apps.status_all(), …) restituiscono solo le risorse che la chiave può vedere.
  • Una chiave sconosciuta, revocata o scaduta produce 401 ACCESS_DENIED.
Tieni la chiave fuori dal codice sorgente: leggila dall’ambiente (os.environ["SQUARECLOUD_API_KEY"]) o da un secret manager.
Gli esempi leggono la chiave dalla variabile d’ambiente SQUARECLOUD_API_KEY. Impostala nel terminale in cui li esegui:

Creare il client

L’SDK ha due client con gli stessi gruppi e metodi:
  • SquareCloud è sincrono e thread-safe: condividi una sola istanza tra i thread. Ogni thread riutilizza la propria connessione keep-alive.
  • AsyncSquareCloud è la stessa API con await. Ogni chiamata esegue il client sincrono in asyncio.to_thread, quindi l’event loop non viene mai bloccato.
Entrambi stampano il nome del tuo account e il numero di app che la chiave può vedere:
Uscire dal blocco with / async with chiude le connessioni del pool. Senza un blocco, chiama client.close() quando hai finito. close() è un normale metodo (sincrono) su entrambi i client. Una chiave vuota o composta solo da spazi solleva un ValueError nel costruttore, prima di qualsiasi richiesta.

Il client asincrono

AsyncSquareCloud differisce da SquareCloud solo in tre punti:
  • Ogni metodo restituisce una coroutine: await client.apps.status(app_id).
  • close() è sincrono: chiamalo senza await.
  • apps.realtime(app_id) non va atteso: restituisce un AsyncRealtime che consumi con async for (vedi Realtime).
Poiché ogni chiamata gira in un worker thread, puoi eseguire più chiamate in parallelo con asyncio.gather:
Annullare un task in attesa non ferma la richiesta già in esecuzione nel suo worker thread: la chiamata si completa comunque (o va in timeout) in background.

Opzioni

Le opzioni sono solo keyword, e AsyncSquareCloud accetta le stesse.
Il client conserva la chiave solo nei suoi header di richiesta privati: non esiste un attributo client.api_key, e il logger dell’SDK non la scrive mai.

Moduli

Il pacchetto esporta SquareCloud, AsyncSquareCloud, SquareCloudAPIError, BASE_URL, HTTPTransport, i protocolli Transport e Response, Realtime, AsyncRealtime e __version__. I tipi delle risposte (App, RuntimeStats, Snapshot, …) si trovano in squarecloud.types:

Convenzioni

Prima gli id, in risposta dati semplici

Ogni metodo accetta l’id della risorsa come primo argomento e restituisce dati semplici: ogni risposta è un TypedDict, che a runtime è un normale dict (niente classi, niente cache), quindi i campi che l’API aggiungerà in futuro vengono mantenuti. I nomi dei campi sono quelli dell’API (created_at, version_id, lastModified, joinedAt, netIO, …), quindi il riferimento API si applica così com’è.
  • Le mutazioni restituiscono None, a meno che l’API non restituisca dati (envs.*, deploys.set_webhook, deploys.link_github_app, databases.reset_credentials e i metodi create).
  • Un risultato stringa non è mai None: è '' quando l’API non ne invia.
  • Gli elenchi arrivano completi in una sola chiamata: non c’è paginazione.
  • I modificatori facoltativi sono solo keyword (status(app_id, raw=True), commit(app_id, file, path="/src")). L’unica eccezione è il path facoltativo di files.list, che può essere passato anche per posizione.
I metodi sono normali metodi associati (bound method), quindi puoi conservarne un riferimento:

App dei workspace

Ogni app_id accetta anche la forma composta <appId>-<workspaceId> per agire su un’app condivisa con te tramite un workspace. workspaces.get() e workspaces.list() restituiscono gli id grezzi; l’id composto lo costruisci tu:

Gli id vengono codificati

Gli id nel percorso dell’URL sono codificati in percent-encoding. Un id vuoto, . o .. raggiungerebbe una route diversa, quindi fallisce localmente con INVALID_ID (status 0) prima che venga inviato qualsiasi cosa. Le route dei workspace invece inviano i loro id nel body: lì, INVALID_ID (400) proviene dal server.

Date

Gli argomenti start ed end (vedi Rete) accettano una stringa ISO 8601 (inviata così com’è) o un datetime (inviato in UTC). Un datetime naive viene trattato come ora locale e convertito in UTC, quindi preferisci quelli aware (datetime.now(UTC)). Le date nelle risposte restano come le invia l’API (stringhe ISO, o millisecondi Unix dove l’API li usa).

Timeout

timeout limita ogni operazione sul socket: la connessione e ogni lettura o scrittura. Una risposta che continua a inviare dati può durare complessivamente più di timeout. Un timeout pari a 0 o inferiore disattiva tutti i timeout, comprese le soglie minime di 120 s. Le chiamate non possono essere annullate una volta inviate: l’unico flusso che puoi interrompere a metà è apps.realtime(), con close() da qualsiasi thread. Per un upload lungo, mantieni il timeout predefinito così una connessione morta viene rilevata alla connessione, ed eseguilo in un thread o con AsyncSquareCloud se il resto del programma deve continuare a funzionare.

Account

client.account.me() restituisce l’utente autenticato insieme alle app e ai database che la chiave può vedere.
client.account.snapshots(scope=...) elenca tutti gli snapshot dell’account: vedi Snapshot.

Stato della piattaforma

client.service.status() restituisce lo stato pubblico della piattaforma. La route non richiede una chiave valida, ma il client ne richiede comunque una non vuota.
unknown significa che il controllo stesso non è stato possibile: non è la prova di un disservizio.

Avanzate

Transport personalizzato

transport= sostituisce il livello HTTP. Usalo per proxy, tracing o test. Un transport è qualsiasi callable con questa firma:
L’oggetto restituito deve avere status, read(), readline() e close(): un http.client.HTTPResponse va bene. I retry, la mappatura degli errori e l’estrazione di {status, response} restano nel client, quindi un transport si limita a spostare byte. HTTPTransport(timeout=30.0) è il transport predefinito: una connessione keep-alive per thread e host, risposte compresse con gzip (tranne i flussi) e timeout come limite di connessione per le chiamate senza un timeout proprio. Puoi incapsularlo:
client.close() chiude le connessioni del transport predefinito. Viene chiuso anche un transport personalizzato che ha un metodo close().

Logging

L’SDK registra ogni richiesta a livello DEBUG sul logger squarecloud: metodo, percorso e status, mai body o chiavi. Collega solo un NullHandler, quindi non viene stampato nulla finché non configuri il logging:

Prossimi passi

Gestire le applicazioni

Stato, ciclo di vita, log e metriche.

Errori

Classe di errore, retry e rate limit.

Introduzione all'API

URL base, autenticazione e una prima richiesta.

Quickstart della CLI

Fai il deploy e gestisci le app dal terminale.