Operazioni asincrone
Come visto precedentemente, la classe Client
già supporta l’esecuzione asincrona di gran parte dei suoi metodi,
tramite l’uso delle callback success, error e progress. Esiste però anche un approccio più moderno all’esecuzione asincrona
che supporta direttamente il modulo asyncio
di Python, in modo da poter usare costrutti come async
e await
; per fare
questo è stata introdotta la classe AsyncClient
.
Nota
La classe AsyncClient
è disponibile solo se si usa Python versione 3.6 o successive.
E” possibile convertire oggetti di classe Client
a oggetti di classe AsyncClient
e viceversa
tramite i metodi kongalib.Client.as_async()
e kongalib.AsyncClient.as_sync()
; eventuali connessioni a server e
database verranno preservate.
Classe AsyncClient
- class kongalib.AsyncClient(impl=None)
La classe AsyncClient, analogamente alla classe
Client
, permette di connettersi ad un server Konga e di eseguire comandi sullo stesso; la differenza è nel fatto che questa classe è costruita esplicitamente per lavorare con asyncio di Python, ed è disponibile solo se si usa Python >= 3.6.Tutti i metodi che esistono nella classe Client e che possono essere invocati sia in maniera asincrona (specificando le callback di success, error e progress) che sincrona (generalmente omettendo di specificare la callback di success), nella classe AsyncClient accettano eventualmente la sola callback di progress, in quanto vengono sempre eseguiti in maniera asincrona tramite l’event loop di asyncio, che si assume sia in esecuzione. La progress viene eseguita in un thread separato, ed ha la forma
progress(type, completeness, state, userdata)
; i parametri interessanti di questa callback sono completeness (percentuale di completamento, ossia un numero che varia da 0.0 a 100.0; se -1.0 indica una percentuale di completamento indefinita), state (stringa che specifica l’eventuale stato corrente dell’operazione) e userdata, che è un parametro aggiuntivo che viene normalmente passato alla chiamata asincrona dall’utente per tenere traccia di un eventuale stato.Come per la classe Client, oggetti di classe AsyncClient possono essere usati come contesti per il costrutto
with
: all’ingresso del blocco verrà iniziata una transazione, mentre in uscita verrà eseguita una commit o una rollback della stessa a seconda che ci sia stata o meno un’eccezione all’interno del blocco di istruzioni. Da notare che dal momento che siamo in ambito asincrono, andrà usato il costruttoasync with
al posto del semplicewith
.- as_sync()
Ritorna un oggetto
Client
equivalente a questo client, preservando le connessioni già presenti.
- authenticate(username, password, progress=None, userdata=None, timeout=180000, new_password=None)
Effettua un accesso al database attivo sulla connessione corrente, identificando l’utente tramite i parametri username e password. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà undict
con informazioni dettagliate sull’utente autenticato, oppure viene lanciata l’eccezioneError
in caso di errore.
- backup_database(password, backup_name, driver, name, auto=True, overwrite=False, position=0, store_index=False, progress=None, userdata=None, timeout=180000)
Esegue un backup del database specificato sul server attualmente connesso. Se auto è
False
, è necessario specificare un nome per il backup tramite backup_name, altrimenti il backup viene considerato automatico ed un nome univoco è assegnato dal server. Se overwrite èFalse
ed un backup con lo stesso nome esiste già sul server, non sarà possibile eseguire il backup. position permette di specificare dove eseguire il backup, ed è una combinazione delle costantikongalib.BACKUP_ON_COMPUTER
ekongalib.BACKUP_ON_CLOUD
, mentre store_index specifica se includere l’indice di ricerca full-text nel backup. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- begin_transaction(pause_indexing=False, deferred=False)
Inizia una transazione sul database attivo nella connessione corrente. Se pause_indexing è
True
, l’indicizzazione del database è disabilitata sul server. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.
- close_database(backup=False, progress=None, userdata=None, timeout=180000)
Chiude il database attivo sulla connessione corrente, restituendo un oggetto
asyncio.Future
per l’esecuzione asincrona; in caso di errore verrà lanciata l’eccezioneError
.Nota
Se backup è
True
, il server esegue un backup automatico del database prima di chiuderlo.
- code_exists(tablename, code, code_azienda, num_esercizio, extra_where=None)
Controlla l’esistenza del codice code nella tabella tablename per l’azienda e l’esercizio specificati in code_azienda e num_esercizio. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà un valore booleano; in caso di errore verrà lanciata un’eccezione di classeError
.
- commit_transaction(resume_indexing=False)
Esegue una COMMIT della transazione sul database attivo nella connessione corrente. Se resume_indexing è
True
, l’indicizzazione del database è abilitata sul server. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.
- connect(server=None, host=None, port=0, options=None, timeout=30000, progress=None, userdata=None)
Tenta una connessione ad un server Konga. Il server a cui ci si vuole connettere può essere specificato in due modi: tramite i parametri host e port, oppure tramite un
dict
server che deve contenere almeno le chiavi host e port. Alternativamente, se server è una stringa e host non è specificato, viene assunta come host. Se host include una specifica di porta e port è0
, port viene ottenuta dalla specifica contenuta nella stringa di host. Il parametro options può essere undict
contenente opzioni aggiuntive per la connessione; al momento le opzioni supportate sono:tenant_key
(str): chiave del tenant per stabilire la connessione con un server multitenant.
La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà undict
contenente le informazioni sulla connessione stabilita.
- create_database(password, driver, name, desc='', progress=None, userdata=None, timeout=180000)
Crea un nuovo database sul server attualmente connesso; il database avrà nome name e descrizione desc. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà l’UUID del nuovo database; se si verifica un errore viene lanciata l’eccezioneError
.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- delete_backup(password, backup_name, position, progress=None, userdata=None, timeout=180000)
Cancella il backup identificato da backup_name dal server connesso. La funzione restituisce un oggetto
asyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- delete_database(password, driver, name, delete_cloud_data=None, progress=None, userdata=None, timeout=180000)
Cancella il database specificato. Se delete_cloud_data è
None
(valore predefinito) la cancellazione sarà negata nel caso ci siano dati binari legati al database al momento presenti nel cloud; in caso contrario i dati binari saranno o meno cancellati dal cloud in base al valore del parametro. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- delete_record(tablename, code=None, id=None, code_azienda=None, num_esercizio=None, log=None, progress=None)
Cancella un record dalla tabella tablename. Il record può essere identificato in due modi: o tramite il solo id, oppure tramite la specifica dei parametri code, code_azienda e num_esercizio. La funzione restituisce un oggetto
asyncio.Future
per l’esecuzione asincrona; in caso di errore verrà lanciata un’eccezione di classeError
oErrorList
. Al termine dell’operazione, se log è un oggetto di classeOperationLog
, esso riceverà ogni eventuale messaggio di log prodotto dal server durante la cancellazione.
- disconnect()
Disconnette il server attualmente connesso, oppure non fa nulla se non si è al momento connessi.
- fetch_binary(field_or_tablename, id, type, filename=None, check_only=False, progress=None)
Carica un contenuto binario dal server. field_or_tablename può essere un nome tabella o un campo da cui risolvere il nome tabella; questa tabella unita a id identificano la scheda del database da cui caricare la risorsa; type è uno dei valori della Choice
Resources
, mentre filename ha senso solo per identificare le risorse di tipo documento. La funzione restituisce un oggettoasyncio.Future
il cui risultato una volta completato sarà una tupla di quattro elementi: ( dati, filename, original_filename, checksum ). dati sono i dati binari che sono stati caricati dal server; filename è il nome file interno con cui è identificata la risorsa, original_filename è il nome del file originale che è stato specificato all’atto del salvataggio della risorsa sul server, mentre checksum è un checksum dei dati. Se check_only èTrue
, i dati binari della risorsa non verranno effettivamente caricati dal dispositivo di archiviazione in cui sono depositati, e dati saràNone
; questa modalità è utile per verificare l’esistenza di una risorsa e il suo checksum senza effettivamente caricarla da remoto (nel caso di archiviazione su cloud il caricamento potrebbe essere lento).
- fetch_image(fieldname, id, type, progress=None)
Piccolo wrapper alla funzione
fetch_binary()
, dedicato alle immagini, con l’unica differenza che l’oggettoasyncio.Future
restituito una volta completato avrà come valore di ritorno direttamente il contenuto binario dell’immagine.
- full_text_search(text, limit, progress=None, userdata=None, timeout=180000)
Esegue una ricerca full-text sul database attivo sulla connessione corrente, limitando la ricerca di text a limit risultati. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà una lista di risultati, dove ogni risultato èdict
con almeno le chiavi score, tablename, id e display; in caso di errore viene lanciata l’eccezioneError
.
- get_connection_info()
Restituisce un
dict
con informazioni sulla connessione corrente, oNone
se non si è connessi.
- get_data_dictionary(progress=None, userdata=None, timeout=180000)
Restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà il dizionario dei dati disponibile sul server attualmente connesso, sotto forma di oggetto di classekongalib.DataDictionary
.
- get_id()
Restituisce un ID numerico univoco assegnato dal server alla connessione con questo client, o 0 se non si è connessi.
- get_record(tablename, code=None, id=None, field_names=None, row_extra_field_names=None, code_azienda=None, num_esercizio=None, mode=None, mask_binary=None, flags=287, progress=None)
Ottiene il record completo della tabella tablename, sotto forma di
dict
. Il record può essere identificato in due modi: o tramite il solo id, oppure tramite la specifica dei parametri code, code_azienda e num_esercizio. La funzione restituisce un oggettoasyncio.Future
il cui risultato una volta completato sarà undict
con il record ottenuto; verrà lanciata un’eccezioneError
in caso di errore.
- index_database(password, driver, name, reset=False, run=True, progress=None, userdata=None, timeout=180000)
Esegue una indicizzazione del database specificato sul server attualmente connesso. Se reset è
False
, l’indicizzazione è incrementale, ovvero l’indice viene modificato per tenere conto solo dei record inseriti, modificati o cancellati dall’ultima indicizzazione; se invece reset èTrue
l’indice viene prima cancellato e poi, se run è anch’essoTrue
, viene ricreato completamente. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- insert_record(tablename, data, code_azienda=None, num_esercizio=None, log=None, progress=None)
Inserisce un nuovo record nella tabella tablename. Il nuovo record, i cui dati sono passati nel
dict
data, sarà un record condiviso con tutte le aziende del database se code_azienda e num_esercizio sonoNone
, altrimenti apparterrà solo all’azienda e all’esercizio specificati. La funzione restituisce un oggettoasyncio.Future
il cui risultato una volta completato sarà una tupla nella forma(id, code)
, dove id è l’ID univoco assegnato al record dal server, mentre code è il codice del record (che può essere diverso da quello passato in data se sono attivi i codici automatici per tablename); in caso di errore verrà lanciata un’eccezione di classeError
oErrorList
. Al termine dell’operazione, se log è un oggetto di classeOperationLog
, esso riceverà ogni eventuale messaggio di log prodotto dal server durante l’inserimento.
- interrupt()
Interrompe tutte le operazioni al momento in esecuzione da parte di questo client.
- list_backups(position=0, progress=None, userdata=None, timeout=180000)
Ottiene la lista dei backup disponibili sul server connesso. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà una lista di backup; ogni backup è undict
che contiene almeno le chiavi backup_name, uuid, date e size; se si verifica un errore viene lanciata l’eccezioneError
.
- list_binaries(field_or_tablename, id, type=None, progress=None)
Ottiene la lista dei dati binari associati ad una scheda del database, identificata da field_or_tablename (che può essere un nome tabella o un campo da cui risolvere il nome tabella) e id. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà una lista di tuple, in cui la n-esima tupla ha la forma( Tipo, NomeAllegato, NomeOriginale )
; Tipo è un intero ed è uno dei valori della ChoiceResources
, NomeAllegato è il nome assegnato internamente a Konga per identificare univocamente il contenuto binario, mentre NomeOriginale è il nome del file originale da cui è stato caricato il contenuto. Se type è specificato, la funzione filtrerà i risultati in baso ad esso, ritornando solo le tuple con il Tipo corretto.
- list_databases(driver=None, quick=False, progress=None, userdata=None, timeout=180000)
Restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà la lista dei database disponibili sul server corrente, appartenenti a tutti o ad uno specifico driver. La lista viene tornata sotto forma didict
, le cui chiavi sono i nomi dei driver e i valori le liste dei database appartenenti allo specifico driver. Ogni database nelle liste è undict
che contiene almeno le chiavi name, desc, uuid, created_ts e modified_ts. L’eccezioneError
viene lanciata se si verifica un errore. Se quick èTrue
, la funzione ritorna il più velocemente possibile ma la scansione dei database disponibili potrebbe risultare ancora incompleta.
- list_drivers(configured=True, progress=None, userdata=None, timeout=180000)
Restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà la lista dei driver di database presenti sul server attualmente connesso, oppure lancia un’eccezioneError
su errore. Ogni elemento della lista restituita è undict
che comprende la chiavi name, version e description. Se configured è False, tutti i driver installati sul server sono restituiti, altrimenti verranno restituite solo le informazioni sui driver configurati correttamente ed in esecuzione sul server.
- list_servers(timeout=5000, port=0, progress=None, userdata=None)
Esegue una scansione della rete locale alla ricerca dei server Konga disponibili, attendendo al massimo timeout millisecondi per una risposta. port specifica la porta da cui far partire la scansione (default = 51967); sono controllate le successive 10 porte UDP con intervallo di 20 porte (quindi di default vengono scansionate le porte 51967, 51987, 52007, … 52147). La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà una lista didict
, le cui chiavi principali sono host, port, name e description.
- lock_resource(command, row_id=None)
Tenta di eseguire il blocco della risorsa identificata da command. Se row_id è diverso da
None
, è possibile eseguire il blocco di una singola riga di una tabella del database. La funzione restituisce un oggettoasyncio.Future
il cui risultato una volta completato sarà una tupla(result, owner_data)
, dove owner_data è undict
contenente informazioni sull’utente che detiene già il blocco della risorsa in caso fosse già bloccata, oppure lancia un’eccezioneError
in caso di errore.
- open_database(driver, name, progress=None, userdata=None, timeout=180000)
Apre un database rendendolo il database attivo per la connessione corrente. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà undict
con le informazioni sul database connesso, oppure viene lanciata l’eccezioneError
in caso di errore.
- optimize_database(password, driver, name, progress=None, userdata=None, timeout=180000)
Esegue una ottimizzazione del database specificato sul server attualmente connesso. La funzione restituisce un oggetto
asyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- query(query, native=False, full_column_names=False, collapse_blobs=False, progress=None, userdata=None, timeout=180000)
Esegue una query SQL sul database attivo nella connessione corrente. Se native è
True
, la query viene passata al driver del database senza essere interpretata, permettendo l’esecuzione di query native per l’RDBMS sottostante. La funzione restituisce un oggettoasyncio.Future
il cui risultato una volta completato sarà una tupla nella forma(affected_rows, column_names, result_set)
; affected_rows è il numero di righe coinvolte nella query di UPDATE/DELETE, column_names è una lista di nomi di colonne per il result set, mentre result_set è una lista di righe risultati della query, dove ogni riga è una lista di valori corrispondenti alle colonne restituite in column_names. In caso di errore viene lanciata l’eccezioneError
.Nota
Se full_column_names è
False
, column_names includerà i nomi delle colonne senza nome tabella, altrimenti saranno inclusi i nomi completi delle colonne. Se collapse_blobs èTrue
, i dati di tipo BLOB binari verranno restituiti come[...]
.
- repair_database(password, driver, name, output, progress=None, userdata=None, timeout=180000)
Prova a riparare il database danneggiato specificato, salvando il database recuperato in output. La funzione restituisce un oggetto
asyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.Nota
Non tutti i driver di database supportano questa operazione, e il recupero del database potrebbe fallire in ogni caso.
Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- restore_database(password, backup_name, driver, name, change_uuid=True, overwrite=False, position=0, restore_index=True, progress=None, userdata=None, timeout=180000)
Ripristina un database a partire da un backup effettuato in precedenza sul server connesso. Se overwrite è False ed esiste un database gestito da driver con lo stesso nome, la funzione riporterà errore. change_uuid specifica se cambiare l’UUID associato al database oppure se ripristinare quello originale; se si hanno database con lo stesso nome gestiti da driver diversi è opportuno che almeno l’UUID per essi sia diverso, altrimenti si può incorrere in problemi di aliasing. position specifica da dove prendere il backup da rispristinare, e deve essere una delle costanti
kongalib.BACKUP_ON_COMPUTER
okongalib.BACKUP_ON_CLOUD
; restore_index invece permette di specificare se ripristinare o meno l’indice di ricerca qualora fosse contenuto all’interno del backup. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
- rollback_transaction(resume_indexing=False)
Esegue un ROLLBACK della transazione sul database attivo nella connessione corrente. Se resume_indexing è
True
, l’indicizzazione del database è abilitata sul server. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.
- select_data(tablename, fieldnamelist=None, where_expr=None, order_by=None, order_desc=False, offset=0, count=None, get_total=False, exist=None, progress=None)
Genera ed esegue una SELECT sul server per ottenere una lista di risultati, a partire dalla tabella tablename. fieldnamelist è una lista di nomi dei campi da ottenere; se un campo fk_X di tablename è una foreign key, si può accedere ai campi della tabella collegata Y specificando «fk_X.Campo_di_Y»; la JOIN corrispondente verrà generata e gestita automaticamente dal server. Analogamente, si possono creare catene di JOIN implicite facendo riferimenti multipli di campi foreign key, per esempio «fk_X.fk_Y.fk_Z.Campo_di_Z».
Se where_expr non è
None
, può essere il corpo di una espressione WHERE SQL, e può contenere riferimenti nella stessa forma di fieldnamelist, per esempio «(Campo_di_X = 1) AND (fk_X.Campo_di_Y > 5)».order_by può essere un nome di campo per cui ordinare i risultati, dove order_desc specifica se ordinare in modo ascendente o discendente. offset e count permettono di restituire risultati solo a partire dal numero offset, e limitandosi a count risultati.
La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato dipende dal valore del parametro get_total. Se get_total èTrue
, il risultato sarà una tupla nella forma(result_set, total_rows, exist_results)
; total_rows sarà il numero totale di righe come se offset e limit non fossero stati specificati, mentre exist_results sarà undict
le cui chiavi saranno gli ID specificati nel parametro exist, e i valori sarannoTrue
oFalse
a seconda che il corrispettivo ID sia presente nel database per la tabella tablename oppure no. Se get_total èFalse
, il risultato sarà il solo result_set, ossia una lista di righe risultato della query, dove ogni riga è una lista di valori.
- select_data_as_dict(tablename, fieldnamelist=None, where_expr=None, order_by=None, order_desc=False, offset=0, count=None, get_total=False, progress=None)
Esattamente come
select_data()
, ma l’oggettoasyncio.Future
restituito una volta completato ritornerà un result_set sotto forma di lista didict
, anzichè una lista di liste.
- store_binary(field_or_tablename, id, type, filename=None, original_filename=None, data=None, desc=None, force_delete=False, code_azienda=None, progress=None)
Salva un contenuto binario sul server. field_or_tablename può essere un nome tabella o un campo da cui risolvere il nome tabella; questa tabella unita a id identificano la scheda a cui abbinare la risorsa; type è uno dei valori della Choice*``Resources``; *filename permette di specificare un nome file interno con cui identificare la risorsa (se
None
il server genererà un nome univoco automaticamente); original_filename è il nome file originale i cui dati si stanno salvando sul server; data sono i dati binari effettivi; desc è la descrizione da abbinare alla risorsa; code_azienda infine identifica l’azienda su cui si sta operando. La funzione restituisce un oggettoasyncio.Future
il cui risultato una volta completato sarà il nome del file interno usato dal server per identificare la risorsa, che come detto sopra è uguale a filename se quest’ultimo è diverso daNone
, altrimenti sarà il nome file generato dal server. Se data èNone
, la funzione cancella i dati binari associati alla scheda; force_delete in questo caso può essereTrue
se si desidera cancellare il riferimento ai dati anche se i dati non sono raggiungibili dal server.
- unlock_resource(command, row_id=None)
Rilascia il blocco della risorsa identificata da tablename e row_id. La funzione restituisce un oggetto
asyncio.Future
per l’esecuzione asincrona, e verrà lanciata l’eccezioneError
in caso di errore.
- update_record(tablename, data, code=None, id=None, code_azienda=None, num_esercizio=None, log=None, progress=None)
Aggiorna un record esistente nella tabella tablename. Il record, i cui dati da aggiornare sono passati nel
dict
data, può essere identificato in due modi: o tramite il solo id, oppure tramite la specifica dei parametri code, code_azienda e num_esercizio. La funzione restituisce un oggettoasyncio.Future
per l’esecuzione asincrona; in caso di errore verrà lanciata un’eccezione di classeError
oErrorList
. Al termine dell’operazione, se log è un oggetto di classeOperationLog
, esso riceverà ogni eventuale messaggio di log prodotto dal server durante l’aggiornamento.
- upgrade_database(password, driver, name, progress=None, userdata=None, timeout=180000)
Aggiorna il database specificato all’ultima versione disponibile. La funzione restituisce un oggetto
asyncio.Future
il cui risultato una volta completato sarà una tupla (log, old_version, new_version), dove il log dell’operazione è sotto forma di una lista di stringhe, oppure viene lanciata l’eccezioneError
in caso di errore.Avvertimento
E” necessaria la password del server per poter eseguire questa operazione.
Esempi
Di seguito vengono riportati alcuni esempi di utilizzo della classe AsyncClient
; si assume che ci sia un server
Konga disponibile su localhost e che esista su di esso un database SQLite «demo» inizializzato con i dati di esempio.
Esempio di connessione e lista dell’archivio clienti presenti sul database:
import asyncio
import kongalib
async def main():
c = kongalib.AsyncClient()
await c.connect(host='localhost')
await c.open_database('sqlite', 'demo')
await c.authenticate('admin', '')
results = await c.select_data('EB_ClientiFornitori', ['Codice', 'RagioneSociale'], 'Tipo = 1')
for row in results:
print(row)
asyncio.run(main())
Esempio di come ottenere tutto il record di un documento fiscale (testata e righe):
import asyncio
import kongalib
def print_data(data, indent=1):
# Stampa i dati, tralasciando le chiavi speciali (che cominciano con '@')
lines = [ '%s: %s' % (key, value) for key, value in data.items() if not key.startswith('@') ]
print("\n".join((indent * "\t") + line for line in lines))
async def main():
c = kongalib.Client()
await c.connect(host='localhost')
await c.open_database('sqlite', 'demo')
await c.authenticate('admin', '')
record = await c.get_record('EB_DocumentiFiscali', 11, code_azienda='00000001')
print("Testata:")
print_data(record)
rows = record.get('@rows', [])
for i, row in enumerate(rows):
print("\tRiga %d:" % (i + 1))
print_data(row, 2)
asyncio.run(main())