kongalib 2.0.0__cp310-cp310-win_amd64.whl → 2.0.0.post1__cp310-cp310-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kongalib might be problematic. Click here for more details.
- _kongalib.cp310-win_amd64.pdb +0 -0
- _kongalib.cp310-win_amd64.pyd +0 -0
- kongalib/__init__.py +6 -4
- kongalib/async_client.py +57 -26
- kongalib/client.py +47 -15
- kongalib/constants.py +110 -1853
- kongalib/data_dictionary.py +2 -10
- kongalib/db.py +5 -5
- kongalib/expression.py +7 -2
- kongalib/scripting.py +35 -16
- {kongalib-2.0.0.dist-info → kongalib-2.0.0.post1.dist-info}/METADATA +26 -23
- kongalib-2.0.0.post1.dist-info/RECORD +21 -0
- {kongalib-2.0.0.dist-info → kongalib-2.0.0.post1.dist-info}/WHEEL +1 -1
- {kongalib-2.0.0.dist-info → kongalib-2.0.0.post1.dist-info}/top_level.txt +1 -0
- kongautil.py +14 -2
- kongalib/_kongalib.cp310-win_amd64.pdb +0 -0
- kongalib/_kongalib.cp310-win_amd64.pyd +0 -0
- kongalib-2.0.0.dist-info/RECORD +0 -21
- {kongalib-2.0.0.dist-info → kongalib-2.0.0.post1.dist-info/licenses}/LICENSE +0 -0
- {kongalib-2.0.0.dist-info → kongalib-2.0.0.post1.dist-info}/zip-safe +0 -0
|
Binary file
|
|
Binary file
|
kongalib/__init__.py
CHANGED
|
@@ -126,6 +126,10 @@ class Log(object):
|
|
|
126
126
|
return self.messages
|
|
127
127
|
return [ msg for msg in self.messages if msg[0] == type ]
|
|
128
128
|
|
|
129
|
+
def add_messages(self, messages):
|
|
130
|
+
for msg in messages:
|
|
131
|
+
self.add_message(*msg)
|
|
132
|
+
|
|
129
133
|
def get_exception(self, klass=RuntimeError):
|
|
130
134
|
error = self.get_messages(Log.ERROR)[0][1]
|
|
131
135
|
return klass(error)
|
|
@@ -321,14 +325,12 @@ def ensure_text(text, error='replace'):
|
|
|
321
325
|
|
|
322
326
|
|
|
323
327
|
|
|
324
|
-
from
|
|
328
|
+
from _kongalib import Decimal, Deferred, JSONEncoder, JSONDecoder, NamedSemaphore, start_timer, hash_password, host_lookup, get_network_interfaces, get_machine_uuid, get_system_info, _cleanup, lock, unlock, set_default_idle_callback, set_power_callbacks, checksum, _apply_stylesheet, regexp_find_all, _check_all
|
|
325
329
|
from .constants import *
|
|
326
330
|
from .client import *
|
|
327
331
|
from .expression import *
|
|
328
332
|
from .data_dictionary import *
|
|
329
|
-
|
|
330
|
-
if sys.version_info >= (3, 6):
|
|
331
|
-
from .async_client import AsyncClient
|
|
333
|
+
from .async_client import AsyncClient
|
|
332
334
|
|
|
333
335
|
|
|
334
336
|
class ErrorMessage(object):
|
kongalib/async_client.py
CHANGED
|
@@ -16,11 +16,15 @@
|
|
|
16
16
|
from __future__ import absolute_import
|
|
17
17
|
|
|
18
18
|
import asyncio
|
|
19
|
+
import nest_asyncio
|
|
19
20
|
import inspect
|
|
20
21
|
|
|
21
22
|
from kongalib import *
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
nest_asyncio.apply()
|
|
26
|
+
|
|
27
|
+
|
|
24
28
|
class AsyncClient(Client):
|
|
25
29
|
"""La classe AsyncClient, analogamente alla classe :class:`~kongalib.Client`, permette di connettersi ad un server Konga e di eseguire
|
|
26
30
|
comandi sullo stesso; la differenza è nel fatto che questa classe è costruita esplicitamente per lavorare con *asyncio* di Python, ed
|
|
@@ -50,7 +54,7 @@ class AsyncClient(Client):
|
|
|
50
54
|
future.set_exception(e)
|
|
51
55
|
|
|
52
56
|
def _make_progress(self, future, progress, userdata):
|
|
53
|
-
def callback(ptype, completeness, state,
|
|
57
|
+
def callback(ptype, completeness, state, dummy):
|
|
54
58
|
loop = future.get_loop()
|
|
55
59
|
try:
|
|
56
60
|
if future.cancelled() or (progress is None):
|
|
@@ -107,7 +111,7 @@ class AsyncClient(Client):
|
|
|
107
111
|
answer = output[OUT_LOG] or []
|
|
108
112
|
error_list = ErrorList(answer)
|
|
109
113
|
if output[OUT_ERRNO] == OK:
|
|
110
|
-
if
|
|
114
|
+
if error_list.errno != OK:
|
|
111
115
|
if log is None:
|
|
112
116
|
loop.call_soon_threadsafe(self._safe_set_exception, future, error_list)
|
|
113
117
|
else:
|
|
@@ -115,13 +119,21 @@ class AsyncClient(Client):
|
|
|
115
119
|
if log.has_errors():
|
|
116
120
|
loop.call_soon_threadsafe(self._safe_set_exception, future, error_list)
|
|
117
121
|
else:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
try:
|
|
123
|
+
if finalize_output is not None:
|
|
124
|
+
output = finalize_output(output)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
loop.call_soon_threadsafe(self._safe_set_exception, future, e)
|
|
127
|
+
else:
|
|
128
|
+
loop.call_soon_threadsafe(self._safe_set_result, future, output)
|
|
121
129
|
else:
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
130
|
+
try:
|
|
131
|
+
if finalize_output is not None:
|
|
132
|
+
output = finalize_output(output)
|
|
133
|
+
except Exception as e:
|
|
134
|
+
loop.call_soon_threadsafe(self._safe_set_exception, future, e)
|
|
135
|
+
else:
|
|
136
|
+
loop.call_soon_threadsafe(self._safe_set_result, future, output)
|
|
125
137
|
else:
|
|
126
138
|
loop.call_soon_threadsafe(self._safe_set_exception, future, ErrorList.from_error(output[OUT_ERRNO], output[OUT_ERROR]))
|
|
127
139
|
return success
|
|
@@ -457,7 +469,7 @@ class AsyncClient(Client):
|
|
|
457
469
|
def get_permissions(self, user_id):
|
|
458
470
|
return self._execute(CMD_GET_PERMISSIONS, {
|
|
459
471
|
IN_USER_ID: user_id
|
|
460
|
-
})
|
|
472
|
+
}, OUT_PERMISSIONS)
|
|
461
473
|
|
|
462
474
|
def set_permissions(self, user_id, permissions):
|
|
463
475
|
return self._execute(CMD_SET_PERMISSIONS, {
|
|
@@ -674,12 +686,13 @@ class AsyncClient(Client):
|
|
|
674
686
|
IN_EXTRA_WHERE: where(extra_where),
|
|
675
687
|
}, OUT_EXISTS)
|
|
676
688
|
|
|
677
|
-
def get_next_available_code(self, tablename, code_azienda, num_esercizio, dry_run=False):
|
|
689
|
+
def get_next_available_code(self, tablename, code_azienda, num_esercizio, dry_run=False, force=False):
|
|
678
690
|
return self._execute(CMD_GET_NEXT_CODE, {
|
|
679
691
|
IN_TABLE_NAME: tablename,
|
|
680
692
|
IN_CODE_AZIENDA: code_azienda,
|
|
681
693
|
IN_NUM_ESERCIZIO: num_esercizio,
|
|
682
694
|
IN_DRY_RUN: dry_run,
|
|
695
|
+
IN_FORCE: force,
|
|
683
696
|
}, OUT_CODE)
|
|
684
697
|
|
|
685
698
|
def get_last_npfe(self, code_azienda, num_esercizio):
|
|
@@ -695,24 +708,26 @@ class AsyncClient(Client):
|
|
|
695
708
|
IN_CODE_AZIENDA: code_azienda,
|
|
696
709
|
IN_NUM_ESERCIZIO: num_esercizio,
|
|
697
710
|
IN_TX: tx,
|
|
698
|
-
}, OUT_DATA, progress=progress)
|
|
711
|
+
}, OUT_DATA, progress=progress, log=log)
|
|
699
712
|
|
|
700
|
-
def list_binaries(self, field_or_tablename, id, type=None, progress=None):
|
|
713
|
+
def list_binaries(self, field_or_tablename, id, type=None, progress=None, full=False):
|
|
701
714
|
"""Ottiene la lista dei dati binari associati ad una scheda del database, identificata da *field_or_tablename* (che può essere un nome
|
|
702
715
|
tabella o un campo da cui risolvere il nome tabella) e *id*. La funzione restituisce un oggetto ``asyncio.Future`` il cui risultato
|
|
703
716
|
una volta completato sarà una lista di tuple, in cui la n-esima tupla ha la forma ``( Tipo, NomeAllegato, NomeOriginale )``; *Tipo*
|
|
704
717
|
è un intero ed è uno dei valori della *Choice* ``Resources``, *NomeAllegato* è il nome assegnato internamente a Konga per identificare
|
|
705
718
|
univocamente il contenuto binario, mentre *NomeOriginale* è il nome del file originale da cui è stato caricato il contenuto. Se *type*
|
|
706
|
-
è specificato, la funzione filtrerà i risultati in baso ad esso, ritornando solo le tuple con il *Tipo* corretto.
|
|
719
|
+
è specificato, la funzione filtrerà i risultati in baso ad esso, ritornando solo le tuple con il *Tipo* corretto. Se *full* è ``True``
|
|
720
|
+
la n-esima tupla ritornata avrà un valore in più corrispondente all'etichetta dell'immagine aggiuntiva se specificata.
|
|
707
721
|
"""
|
|
708
722
|
def get_result(output):
|
|
709
723
|
return [ tuple(row) for row in output[OUT_LIST] if ((type is None) or (row[0] == type)) ]
|
|
710
724
|
return self._execute(CMD_LIST_BINARIES, {
|
|
711
725
|
IN_FIELD_NAME: field_or_tablename,
|
|
712
726
|
IN_ROW_ID: id,
|
|
727
|
+
IN_FULL: full,
|
|
713
728
|
}, get_result, progress=progress)
|
|
714
729
|
|
|
715
|
-
def fetch_image(self, fieldname, id, type, progress=None):
|
|
730
|
+
def fetch_image(self, fieldname, id, type, progress=None, label=None):
|
|
716
731
|
"""Piccolo wrapper alla funzione :meth:`.fetch_binary`, dedicato alle immagini, con l'unica differenza che l'oggetto ``asyncio.Future``
|
|
717
732
|
restituito una volta completato avrà come valore di ritorno direttamente il contenuto binario dell'immagine.
|
|
718
733
|
"""
|
|
@@ -720,35 +735,47 @@ class AsyncClient(Client):
|
|
|
720
735
|
IN_FIELD_NAME: fieldname,
|
|
721
736
|
IN_ROW_ID: id,
|
|
722
737
|
IN_TYPE: type,
|
|
738
|
+
IN_LABEL: label,
|
|
723
739
|
}, OUT_DATA, progress=progress)
|
|
724
740
|
|
|
725
|
-
def fetch_binary(self, field_or_tablename, id, type, filename=None, check_only=False, progress=None):
|
|
741
|
+
def fetch_binary(self, field_or_tablename, id, type, filename=None, check_only=False, progress=None, label=None, with_extra=False):
|
|
726
742
|
"""Carica un contenuto binario dal server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
727
743
|
questa tabella unita a *id* identificano la scheda del database da cui caricare la risorsa; *type* è uno dei valori della *Choice*
|
|
728
|
-
``Resources``, mentre *filename*
|
|
744
|
+
``Resources``, mentre *filename* e *label* hanno senso solo per identificare rispettivamente le risorse di tipo documento ed immagine
|
|
745
|
+
aggiuntiva.
|
|
729
746
|
La funzione restituisce un oggetto ``asyncio.Future`` il cui risultato una volta completato sarà una tupla di quattro elementi:
|
|
730
747
|
( *dati*, *filename*, *original_filename*, *checksum* ). *dati* sono i dati binari che sono stati caricati dal server; *filename* è
|
|
731
748
|
il nome file interno con cui è identificata la risorsa, *original_filename* è il nome del file originale che è stato specificato
|
|
732
|
-
all'atto del salvataggio della risorsa sul server, mentre *checksum* è un checksum dei dati. Se *
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
749
|
+
all'atto del salvataggio della risorsa sul server, mentre *checksum* è un checksum dei dati. Se *with_extra* è ``True``, la funzione
|
|
750
|
+
ritorna sei elementi, e gli elementi aggiuntivi sono un ``dict`` con i metadata associati alla risorsa, o ``None`` se non ci sono
|
|
751
|
+
metadati associati, e il codice della tipologia allegato se presente. Se *check_only* è ``True``, i dati binari della risorsa non
|
|
752
|
+
verranno effettivamente caricati dal dispositivo di archiviazione in cui sono depositati, e *dati* sarà ``None``; questa modalità è
|
|
753
|
+
utile per verificare l'esistenza di una risorsa e il suo checksum senza effettivamente caricarla da remoto (nel caso di archiviazione
|
|
754
|
+
su cloud il caricamento potrebbe essere lento)."""
|
|
736
755
|
if (type == 0) and (not filename):
|
|
737
756
|
raise ValueError('filename must be specified for document type resources')
|
|
757
|
+
if with_extra:
|
|
758
|
+
out_params = ( OUT_DATA, OUT_FILENAME, OUT_ORIGINAL_FILENAME, OUT_DATA_CHECKSUM, OUT_METADATA, OUT_CODE_TIPOLOGIA )
|
|
759
|
+
else:
|
|
760
|
+
out_params = ( OUT_DATA, OUT_FILENAME, OUT_ORIGINAL_FILENAME, OUT_DATA_CHECKSUM )
|
|
738
761
|
return self._execute(CMD_FETCH_BINARY, {
|
|
739
762
|
IN_FIELD_NAME: field_or_tablename,
|
|
740
763
|
IN_ROW_ID: id,
|
|
741
764
|
IN_TYPE: type,
|
|
742
765
|
IN_FILENAME: filename,
|
|
766
|
+
IN_LABEL: label,
|
|
743
767
|
IN_CHECK: check_only,
|
|
744
|
-
},
|
|
768
|
+
}, out_params, progress=progress)
|
|
745
769
|
|
|
746
|
-
def store_binary(self, field_or_tablename, id, type, filename=None, original_filename=None, data=None, desc=None, force_delete=False, code_azienda=None, progress=None):
|
|
770
|
+
def store_binary(self, field_or_tablename, id, type, filename=None, original_filename=None, data=None, desc=None, force_delete=False, code_azienda=None, progress=None, label=None, metadata=None, code_tipologia=None, log=None):
|
|
747
771
|
"""Salva un contenuto binario sul server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
748
772
|
questa tabella unita a *id* identificano la scheda a cui abbinare la risorsa; *type* è uno dei valori della *Choice*``Resources``;
|
|
749
773
|
*filename* permette di specificare un nome file interno con cui identificare la risorsa (se ``None`` il server genererà un nome univoco
|
|
750
774
|
automaticamente); *original_filename* è il nome file originale i cui dati si stanno salvando sul server; *data* sono i dati binari
|
|
751
|
-
effettivi; *desc* è la descrizione da abbinare alla risorsa; *code_azienda* infine identifica l'azienda su cui si sta operando
|
|
775
|
+
effettivi; *desc* è la descrizione da abbinare alla risorsa; *code_azienda* infine identifica l'azienda su cui si sta operando, mentre
|
|
776
|
+
*code_tipologia* permette di specificare una tipologia da abbinare al dati. Per le risorse di tipo immagine aggiuntiva è necessario
|
|
777
|
+
specificare una *label* da abbinare all'immagine per identificarla univocamente. *metadata* può essere un ``dict`` in cui sia chiavi che
|
|
778
|
+
valori siano delle semplici stringhe, e permette di specificare dei metadati aggiuntivi associati alla risorsa binaria che si sta inserendo.
|
|
752
779
|
La funzione restituisce un oggetto ``asyncio.Future`` il cui risultato una volta completato sarà il nome del file interno usato dal
|
|
753
780
|
server per identificare la risorsa, che come detto sopra è uguale a *filename* se quest'ultimo è diverso da ``None``, altrimenti sarà
|
|
754
781
|
il nome file generato dal server.
|
|
@@ -764,13 +791,17 @@ class AsyncClient(Client):
|
|
|
764
791
|
IN_DATA: data,
|
|
765
792
|
IN_DESC: desc,
|
|
766
793
|
IN_FORCE_DELETE: force_delete,
|
|
767
|
-
|
|
794
|
+
IN_LABEL: label,
|
|
795
|
+
IN_METADATA: metadata,
|
|
796
|
+
IN_CODE_TIPOLOGIA: code_tipologia,
|
|
797
|
+
}, OUT_FILENAME, progress=progress, log=log)
|
|
768
798
|
|
|
769
|
-
def translate(self, field, value, language):
|
|
799
|
+
def translate(self, field, value, language, code_azienda=None):
|
|
770
800
|
return self._execute(CMD_TRANSLATE, {
|
|
771
801
|
IN_FIELD: field,
|
|
772
802
|
IN_VALUE: value,
|
|
773
|
-
IN_LANGUAGE: language
|
|
803
|
+
IN_LANGUAGE: language,
|
|
804
|
+
IN_CODE_AZIENDA: code_azienda,
|
|
774
805
|
}, OUT_TEXT)
|
|
775
806
|
|
|
776
807
|
def set_database_language(self, language, progress=None):
|
kongalib/client.py
CHANGED
|
@@ -23,8 +23,8 @@ from .constants import *
|
|
|
23
23
|
from .expression import *
|
|
24
24
|
from .data_dictionary import *
|
|
25
25
|
|
|
26
|
-
from
|
|
27
|
-
from
|
|
26
|
+
from _kongalib import Client as ClientImpl
|
|
27
|
+
from _kongalib import start_timer
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
DEFAULT_DISCOVER_TIMEOUT = 5000
|
|
@@ -55,6 +55,7 @@ GET_FLAG_DEFAULT = GET_FLAG_GET_IMAGES | GET_FLAG_GET_ATTACHMENTS | GET_FLAG_
|
|
|
55
55
|
IMAGE_NORMAL = 1
|
|
56
56
|
IMAGE_WEB = 2
|
|
57
57
|
IMAGE_THUMBNAIL = 3
|
|
58
|
+
IMAGE_EXTRA = 4
|
|
58
59
|
|
|
59
60
|
|
|
60
61
|
def make_callbacks(success, error, log=None):
|
|
@@ -768,12 +769,13 @@ class Client(object):
|
|
|
768
769
|
})
|
|
769
770
|
return output['EXISTS']
|
|
770
771
|
|
|
771
|
-
def get_next_available_code(self, tablename, code_azienda, num_esercizio, dry_run=False):
|
|
772
|
+
def get_next_available_code(self, tablename, code_azienda, num_esercizio, dry_run=False, force=False):
|
|
772
773
|
return self.execute(CMD_GET_NEXT_CODE, {
|
|
773
774
|
IN_TABLE_NAME: tablename,
|
|
774
775
|
IN_CODE_AZIENDA: code_azienda,
|
|
775
776
|
IN_NUM_ESERCIZIO: num_esercizio,
|
|
776
777
|
IN_DRY_RUN: dry_run,
|
|
778
|
+
IN_FORCE: force,
|
|
777
779
|
})[OUT_CODE]
|
|
778
780
|
|
|
779
781
|
def get_last_npfe(self, code_azienda, num_esercizio):
|
|
@@ -828,13 +830,14 @@ class Client(object):
|
|
|
828
830
|
return output[OUT_DATA]
|
|
829
831
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
830
832
|
|
|
831
|
-
def list_binaries(self, field_or_tablename, id, type=None, success=None, error=None, progress=None):
|
|
833
|
+
def list_binaries(self, field_or_tablename, id, type=None, success=None, error=None, progress=None, full=False):
|
|
832
834
|
"""Ottiene la lista dei dati binari associati ad una scheda del database, identificata da *field_or_tablename* (che può essere un nome
|
|
833
835
|
tabella o un campo da cui risolvere il nome tabella) e *id*. La funzione ritorna una lista di tuple, in cui la n-esima tupla ha la
|
|
834
836
|
forma ``( Tipo, NomeAllegato, NomeOriginale )``; *Tipo* è un intero ed è uno dei valori della *Choice* ``Resources``, *NomeAllegato* è
|
|
835
837
|
il nome assegnato internamente a Konga per identificare univocamente il contenuto binario, mentre *NomeOriginale* è il nome del file
|
|
836
838
|
originale da cui è stato caricato il contenuto. Se *type* è specificato, la funzione filtrerà i risultati in baso ad esso, ritornando
|
|
837
|
-
solo le tuple con il *Tipo* corretto.
|
|
839
|
+
solo le tuple con il *Tipo* corretto. Se *full* è ``True`` la n-esima tupla ritornata avrà un valore in più corrispondente all'etichetta
|
|
840
|
+
dell'immagine aggiuntiva se specificata.
|
|
838
841
|
Se *success* è diverso da ``None``, la callback verrà invocata in caso di successo con la lista di tuple di cui sopra.
|
|
839
842
|
"""
|
|
840
843
|
if success is not None:
|
|
@@ -850,17 +853,19 @@ class Client(object):
|
|
|
850
853
|
return self.execute(CMD_LIST_BINARIES, {
|
|
851
854
|
IN_FIELD_NAME: field_or_tablename,
|
|
852
855
|
IN_ROW_ID: id,
|
|
856
|
+
IN_FULL: full,
|
|
853
857
|
}, success=callback, error=errback, progress=progress)
|
|
854
858
|
else:
|
|
855
859
|
output = self.execute(CMD_LIST_BINARIES, {
|
|
856
860
|
IN_FIELD_NAME: field_or_tablename,
|
|
857
861
|
IN_ROW_ID: id,
|
|
862
|
+
IN_FULL: full,
|
|
858
863
|
})
|
|
859
864
|
if output[OUT_ERRNO] == OK:
|
|
860
865
|
return [ tuple(row) for row in output[OUT_LIST] if ((type is None) or (row[0] == type)) ]
|
|
861
866
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
862
867
|
|
|
863
|
-
def fetch_image(self, fieldname, id, type, success=None, error=None, progress=None):
|
|
868
|
+
def fetch_image(self, fieldname, id, type, success=None, error=None, progress=None, label=None):
|
|
864
869
|
"""Piccolo wrapper alla funzione :meth:`.fetch_binary`, dedicato alle immagini, con l'unica differenza che il valore di ritorno sarà
|
|
865
870
|
direttamente il contenuto binario dell'immagine in caso di successo (e questo sarà anche l'unico parametro passato alla callback
|
|
866
871
|
*success*)"""
|
|
@@ -878,25 +883,30 @@ class Client(object):
|
|
|
878
883
|
IN_FIELD_NAME: fieldname,
|
|
879
884
|
IN_ROW_ID: id,
|
|
880
885
|
IN_TYPE: type,
|
|
886
|
+
IN_LABEL: label,
|
|
881
887
|
}, success=callback, error=errback, progress=progress)
|
|
882
888
|
else:
|
|
883
889
|
output = self.execute(CMD_FETCH_BINARY, {
|
|
884
890
|
IN_FIELD_NAME: fieldname,
|
|
885
891
|
IN_ROW_ID: id,
|
|
886
892
|
IN_TYPE: type,
|
|
893
|
+
IN_LABEL: label,
|
|
887
894
|
})
|
|
888
895
|
if output[OUT_ERRNO] == OK:
|
|
889
896
|
return output[OUT_DATA]
|
|
890
897
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
891
898
|
|
|
892
|
-
def fetch_binary(self, field_or_tablename, id, type, filename=None, check_only=False, success=None, error=None, progress=None):
|
|
899
|
+
def fetch_binary(self, field_or_tablename, id, type, filename=None, check_only=False, success=None, error=None, progress=None, label=None, with_extra=False):
|
|
893
900
|
"""Carica un contenuto binario dal server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
894
901
|
questa tabella unita a *id* identificano la scheda del database da cui caricare la risorsa; *type* è uno dei valori della *Choice*
|
|
895
|
-
``Resources``, mentre *filename*
|
|
902
|
+
``Resources``, mentre *filename* e *label* hanno senso solo per identificare rispettivamente le risorse di tipo documento ed immagine
|
|
903
|
+
aggiuntiva.
|
|
896
904
|
La funzione ritorna una tupla di quattro elementi: ( *dati*, *filename*, *original_filename*, *checksum* ). Questi quattro elementi
|
|
897
905
|
sono anche i parametri passati alla callback *success* in caso di successo. *dati* sono i dati binari che sono stati caricati dal
|
|
898
906
|
server; *filename* è il nome file interno con cui è identificata la risorsa, *original_filename* è il nome del file originale che è
|
|
899
|
-
stato specificato all'atto del salvataggio della risorsa sul server, mentre *checksum* è un checksum dei dati.
|
|
907
|
+
stato specificato all'atto del salvataggio della risorsa sul server, mentre *checksum* è un checksum dei dati. Se *with_extra* è
|
|
908
|
+
``True``, la funzione ritorna sei elementi, e gli elementi aggiuntivi sono un ``dict`` con i metadata associati alla risorsa, o ``None``
|
|
909
|
+
se non ci sono metadati associati, e il codice della tipologia allegato se presente.
|
|
900
910
|
Se *check_only* è ``True``, i dati binari della risorsa non verranno effettivamente caricati dal dispositivo di archiviazione in cui
|
|
901
911
|
sono depositati, e *dati* sarà ``None``; questa modalità è utile per verificare l'esistenza di una risorsa e il suo checksum senza
|
|
902
912
|
effettivamente caricarla da remoto (nel caso di archiviazione su cloud il caricamento potrebbe essere lento)."""
|
|
@@ -905,7 +915,10 @@ class Client(object):
|
|
|
905
915
|
if success is not None:
|
|
906
916
|
def callback(output, dummy):
|
|
907
917
|
if output[OUT_ERRNO] == OK:
|
|
908
|
-
|
|
918
|
+
if with_extra:
|
|
919
|
+
success(output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM], output[OUT_METADATA], output[OUT_CODE_TIPOLOGIA])
|
|
920
|
+
else:
|
|
921
|
+
success(output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM])
|
|
909
922
|
elif error is not None:
|
|
910
923
|
error(Error(output[OUT_ERRNO], output[OUT_ERROR]))
|
|
911
924
|
def errback(errno, errstr, dummy):
|
|
@@ -917,6 +930,7 @@ class Client(object):
|
|
|
917
930
|
IN_ROW_ID: id,
|
|
918
931
|
IN_TYPE: type,
|
|
919
932
|
IN_FILENAME: filename,
|
|
933
|
+
IN_LABEL: label,
|
|
920
934
|
IN_CHECK: check_only,
|
|
921
935
|
}, success=callback, error=errback, progress=progress)
|
|
922
936
|
else:
|
|
@@ -925,18 +939,25 @@ class Client(object):
|
|
|
925
939
|
IN_ROW_ID: id,
|
|
926
940
|
IN_TYPE: type,
|
|
927
941
|
IN_FILENAME: filename,
|
|
942
|
+
IN_LABEL: label,
|
|
928
943
|
IN_CHECK: check_only,
|
|
929
944
|
})
|
|
930
945
|
if output[OUT_ERRNO] == OK:
|
|
931
|
-
|
|
946
|
+
if with_extra:
|
|
947
|
+
return output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM], output[OUT_METADATA], output[OUT_CODE_TIPOLOGIA]
|
|
948
|
+
else:
|
|
949
|
+
return output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM]
|
|
932
950
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
933
951
|
|
|
934
|
-
def store_binary(self, field_or_tablename, id, type, filename=None, original_filename=None, data=None, desc=None, force_delete=False, code_azienda=None, success=None, error=None, progress=None):
|
|
952
|
+
def store_binary(self, field_or_tablename, id, type, filename=None, original_filename=None, data=None, desc=None, force_delete=False, code_azienda=None, success=None, error=None, progress=None, label=None, metadata=None, code_tipologia=None, log=None):
|
|
935
953
|
"""Salva un contenuto binario sul server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
936
954
|
questa tabella unita a *id* identificano la scheda a cui abbinare la risorsa; *type* è uno dei valori della *Choice*``Resources``;
|
|
937
955
|
*filename* permette di specificare un nome file interno con cui identificare la risorsa (se ``None`` il server genererà un nome univoco
|
|
938
956
|
automaticamente); *original_filename* è il nome file originale i cui dati si stanno salvando sul server; *data* sono i dati binari
|
|
939
|
-
effettivi; *desc* è la descrizione da abbinare alla risorsa; *code_azienda* infine identifica l'azienda su cui si sta operando
|
|
957
|
+
effettivi; *desc* è la descrizione da abbinare alla risorsa; *code_azienda* infine identifica l'azienda su cui si sta operando, mentre
|
|
958
|
+
*code_tipologia* permette di specificare una tipologia da abbinare al dati. Per le risorse di tipo immagine aggiuntiva è necessario
|
|
959
|
+
specificare una *label* da abbinare all'immagine per identificarla univocamente. *metadata* può essere un ``dict`` in cui sia chiavi che
|
|
960
|
+
valori siano delle semplici stringhe, e permette di specificare dei metadati aggiuntivi associati alla risorsa binaria che si sta inserendo.
|
|
940
961
|
La funzione ritorna il nome del file interno usato dal server per identificare la risorsa, che come detto sopra è uguale a *filename* se
|
|
941
962
|
quest'ultimo è diverso da ``None``, altrimenti verrà ritornato il nome file generato dal server. La callback *success* se specificata
|
|
942
963
|
riceverà *filename* come unico parametro.
|
|
@@ -945,6 +966,8 @@ class Client(object):
|
|
|
945
966
|
if success is not None:
|
|
946
967
|
def callback(output, dummy):
|
|
947
968
|
if output[OUT_ERRNO] == OK:
|
|
969
|
+
if log is not None:
|
|
970
|
+
ErrorList(output[OUT_LOG] or []).prepare_log(log)
|
|
948
971
|
success(output[OUT_FILENAME])
|
|
949
972
|
elif error is not None:
|
|
950
973
|
error(Error(output[OUT_ERRNO], output[OUT_ERROR]))
|
|
@@ -962,6 +985,9 @@ class Client(object):
|
|
|
962
985
|
IN_DATA: data,
|
|
963
986
|
IN_DESC: desc,
|
|
964
987
|
IN_FORCE_DELETE: force_delete,
|
|
988
|
+
IN_LABEL: label,
|
|
989
|
+
IN_METADATA: metadata,
|
|
990
|
+
IN_CODE_TIPOLOGIA: code_tipologia,
|
|
965
991
|
}, success=callback, error=errback, progress=progress)
|
|
966
992
|
else:
|
|
967
993
|
output = self.execute(CMD_STORE_BINARY, {
|
|
@@ -974,16 +1000,22 @@ class Client(object):
|
|
|
974
1000
|
IN_DATA: data,
|
|
975
1001
|
IN_DESC: desc,
|
|
976
1002
|
IN_FORCE_DELETE: force_delete,
|
|
1003
|
+
IN_LABEL: label,
|
|
1004
|
+
IN_METADATA: metadata,
|
|
1005
|
+
IN_CODE_TIPOLOGIA: code_tipologia,
|
|
977
1006
|
})
|
|
978
1007
|
if output[OUT_ERRNO] == OK:
|
|
1008
|
+
if log is not None:
|
|
1009
|
+
ErrorList(output[OUT_LOG] or []).prepare_log(log)
|
|
979
1010
|
return output[OUT_FILENAME]
|
|
980
1011
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
981
1012
|
|
|
982
|
-
def translate(self, field, value, language):
|
|
1013
|
+
def translate(self, field, value, language, code_azienda=None):
|
|
983
1014
|
output = self.execute(CMD_TRANSLATE, {
|
|
984
1015
|
IN_FIELD: field,
|
|
985
1016
|
IN_VALUE: value,
|
|
986
|
-
IN_LANGUAGE: language
|
|
1017
|
+
IN_LANGUAGE: language,
|
|
1018
|
+
IN_CODE_AZIENDA: code_azienda,
|
|
987
1019
|
})
|
|
988
1020
|
if output[OUT_ERRNO] != OK:
|
|
989
1021
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|