DataRpc

Di norma lo scopo di una pagina è sempre quello di dare modo all’utente di interagire con il server per inserire dati, elaborarli o richiedere dati.

Per gestire questo dialogo con il server esistono diversi modi ma il principale è il dataRpc.

Come il dataFormula e il dataController, possiamo immaginare un dataRpc come un elemento attivo che riceve un input da uno o più dei suoi ingressi (i parametri che passiamo) ed esegue un’azione. In questo caso l’azione avviene sul server.

I parametri di definizione di un dataRpc sono:

pane.dataRpc(destination_path, callable, **rpcParameters)

Quindi, nel momento in cui un dataRpc viene attivato da uno dei suoi parametri con “^”, viene effettuata una chiamata ad un metodo python definito nella pagina stessa.

Il metodo in questione dovrà però, per motivi di sicurezza, essere dichiarato pubblico tramite il decoratore @public_method

Vediamo ora direttamente alcuni esempi d’uso.

Esaminiamo il codice

def main(self,root,**kwargs):
    root.h1('Server Datetime',text_align='center',color='888')
    box=root.div(margin='10px',width='320px',datapath='test_1')
    box.button('Get Server Datetime',fire='.get_datetime',margin_bottom='10px')

    box.div('^.now',text_align='center',font_size='14px',color='#666',
            lbl='Server datetime',width='300px',height='30px',border='1px solid silver',
            lbl_background='darkblue',lbl_text_align='center')

    box.dataRpc('.now', self.getNow, _fired='^.get_datetime')


@public_method
def getNow(self):
    return datetime.datetime.now()

In questo primo esempio il bottone genera un fire sul path “get_datetime” che è sottoscritto dal parametro fittizio _fired del dataRpc.

N.B. : Nei dataRpc i parametri che iniziano con “_” sono considerati unicamente dal punto di vista del client e non vengono quindi inviati al server.

Il dataRpc chiama quindi il metodo di pagina getNow che deve essere decorato con il decoratore @public_method.

Il server rende il datetime corrispondente che il dataRpc provvede a mettere nel path “.now” che è visualizzato in un div.

Da notare l’utilizzo del parametro lbl= al di fuori di un formbuilder. In tale caso l’etichetta è posta al di sopra dell’elemento e, come al solito, può ricevere dei parametri di stile usando il prefisso lbl_

QuickGrid

Nei prossimi esempi useremo per la prima volta il widget QuickGrid senza peraltro entrare in dettaglio sul suo funzionamento. Questo widget consente di visualizzare come tabella una zona dello store creata da una Bag.

Nel suo utilizzo minimale la quickGrid è in grado di desumere la formattazione e le intestazioni dal contenuto della Bag.

Esaminiamo il codice:

def main(self,root,**kwargs):
   root.h1('Cpu Times',text_align='center',color='888')
   pane=root.div(margin='15px',datapath='cpuTimes')
   pane.quickGrid(value='^.data', border='1px solid silver',
                         height='auto',width='auto')
   pane.dataRpc('.data', self.getCpuTimes, _timing=1,_onStart=True)

Dopo aver messo un titolo e definito un div con datapath='cpuTimes', definiamo un quickGrid con altezza e larghezza automatiche e con value='^.data'.

Questa grid provvederà a visualizzare la bag al path relativo “.data” in una griglia. La struttura della griglia potrebbe essere impostata aggiungendo la definizione delle colonne ma in questo caso lasciamo che sia la quickGrid a ricavare in modo automatico la sua struttura dai dati in arrivo.

Vediamo poi la definizione della dataRpc. Notiamo che il primo parametro passato '.data' è il path di destinazione del risultato. Notiamo anche che la dataRpc riceve il parametro _timing=1 ,usato per attivare la chiamata una volta al secondo, e il parametro _onStart=True che provvede a fare comunque scattare la chiamata all’avvio della pagina.

Suggerimento

Alla fine del caricamento di una pagina viene eseguito un fire al path gnr.onStart. Aggiungere il parametro _onStart=True è solo un modo veloce per sottoscrivere questo evento di fire. Se per qualche ragione fosse necessario aggiungere un ritardo è possibile scrivere ad esempio “_onStart=500” per avere un ritardo di 500 millisecondi nell’esecuzione di questo evento.

Veniamo ora ad esaminare il codice lato server:

@public_method
def getCpuTimes(self):
    result=Bag()
    columns=['user','nice','system','idle']
    for j, core in enumerate(psutil.cpu_times(True)):
        row = Bag()
        row['core']=j+1
        for k in columns:
            row.setItem(k, getattr(core,k))
        result.setItem('r_%i'%j, row)
    return result

Per ricavare le informazioni sull’utilizzo della CPU viene usato il modulo psutil (autore Giampaolo Rodolà https://github.com/giampaolo/psutil) che fornisce tutte le informazioni che vogliamo presentare.

In particolare chiamiamo psutil.cpu_times(True) che ci fornisce per ogni core i dati da trasferire al client per la visualizzazione.

Per ogni core viene creata una Bag con i valori della riga e tale riga viene quindi inserita nel risultato ad un path come r_0, r_1 ecc.. La Bag con le righe viene quindi restituita al client dove la QuickGrid, al variare del valore sottoscritto, provvede a ridisegnarsi.

Si noti che cliccando sugli headers è possibile riordinare i valori.

L’ultimo esempio è decisamente più ambizioso e complesso. Ci proponiamo infatti di mostrare in una griglia i processi attivi sul server con le relative informazioni disponibili.

Saremo in grado di mostrare solo le colonne volute e di mettere dei filtri sui nomi dei processi e sugli username e di limitare solo ai processi con una percentuale di uso della CPU e/o della memoria superiore ad un valore impostato.

Per prima cosa viene preparata una lista con i nomi delle possibili colonne. Poi in un formbuider vengono richiesti alcuni parametri e al variare di questi viene chiamato il metodo della pagina getProcessList. Questo riceve nei parametri le colonne che l’utente desidera vedere e filtra i processi in base al nome, allo user e, se richiesto alla percenrtuale di Cpu e di memoria. La Bag che risulta viene quindi visualizzata nella quickGrid.

Da notare l’uso del widget checkBoxText per decidere le colonne da visualizzare.

Per i dettagli sui parametri e sulla sintassi del widget dataRpc si rimanda all’apposita sezione sulla Widgetpedia