kongalib 2.0.0__cp311-cp311-win_amd64.whl → 2.0.2__cp311-cp311-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.cp311-win_amd64.pdb +0 -0
- _kongalib.cp311-win_amd64.pyd +0 -0
- kongalib/__init__.py +6 -4
- kongalib/async_client.py +59 -26
- kongalib/client.py +49 -16
- kongalib/constants.py +110 -1853
- kongalib/data_dictionary.py +2 -10
- kongalib/db.py +5 -5
- kongalib/expression.py +7 -2
- kongalib/scripting.py +39 -18
- {kongalib-2.0.0.dist-info → kongalib-2.0.2.dist-info}/METADATA +26 -23
- kongalib-2.0.2.dist-info/RECORD +21 -0
- {kongalib-2.0.0.dist-info → kongalib-2.0.2.dist-info}/WHEEL +1 -1
- {kongalib-2.0.0.dist-info → kongalib-2.0.2.dist-info}/top_level.txt +1 -0
- kongautil.py +14 -2
- kongalib/_kongalib.cp311-win_amd64.pdb +0 -0
- kongalib/_kongalib.cp311-win_amd64.pyd +0 -0
- kongalib-2.0.0.dist-info/RECORD +0 -21
- {kongalib-2.0.0.dist-info → kongalib-2.0.2.dist-info/licenses}/LICENSE +0 -0
- {kongalib-2.0.0.dist-info → kongalib-2.0.2.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,28 @@ 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
|
|
719
|
+
è specificato, la funzione filtrerà i risultati in base ad esso, ritornando solo le tuple con il *Tipo* corretto. Se *full* è ``True``
|
|
720
|
+
la n-esima tupla ritornata avrà tre valori in più corrispondenti all'etichetta dell'immagine aggiuntiva (se specificata), al codice
|
|
721
|
+
della tipologia dell'allegato e ai metadati associati (se presenti), e la tupla avrà quindi la forma
|
|
722
|
+
``( Tipo, NomeAllegato, NomeOriginale, Etichetta, CodiceTipologia, Metadati )``.
|
|
707
723
|
"""
|
|
708
724
|
def get_result(output):
|
|
709
725
|
return [ tuple(row) for row in output[OUT_LIST] if ((type is None) or (row[0] == type)) ]
|
|
710
726
|
return self._execute(CMD_LIST_BINARIES, {
|
|
711
727
|
IN_FIELD_NAME: field_or_tablename,
|
|
712
728
|
IN_ROW_ID: id,
|
|
729
|
+
IN_FULL: full,
|
|
713
730
|
}, get_result, progress=progress)
|
|
714
731
|
|
|
715
|
-
def fetch_image(self, fieldname, id, type, progress=None):
|
|
732
|
+
def fetch_image(self, fieldname, id, type, progress=None, label=None):
|
|
716
733
|
"""Piccolo wrapper alla funzione :meth:`.fetch_binary`, dedicato alle immagini, con l'unica differenza che l'oggetto ``asyncio.Future``
|
|
717
734
|
restituito una volta completato avrà come valore di ritorno direttamente il contenuto binario dell'immagine.
|
|
718
735
|
"""
|
|
@@ -720,35 +737,47 @@ class AsyncClient(Client):
|
|
|
720
737
|
IN_FIELD_NAME: fieldname,
|
|
721
738
|
IN_ROW_ID: id,
|
|
722
739
|
IN_TYPE: type,
|
|
740
|
+
IN_LABEL: label,
|
|
723
741
|
}, OUT_DATA, progress=progress)
|
|
724
742
|
|
|
725
|
-
def fetch_binary(self, field_or_tablename, id, type, filename=None, check_only=False, progress=None):
|
|
743
|
+
def fetch_binary(self, field_or_tablename, id, type, filename=None, check_only=False, progress=None, label=None, with_extra=False):
|
|
726
744
|
"""Carica un contenuto binario dal server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
727
745
|
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*
|
|
746
|
+
``Resources``, mentre *filename* e *label* hanno senso solo per identificare rispettivamente le risorse di tipo documento ed immagine
|
|
747
|
+
aggiuntiva.
|
|
729
748
|
La funzione restituisce un oggetto ``asyncio.Future`` il cui risultato una volta completato sarà una tupla di quattro elementi:
|
|
730
749
|
( *dati*, *filename*, *original_filename*, *checksum* ). *dati* sono i dati binari che sono stati caricati dal server; *filename* è
|
|
731
750
|
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
|
-
|
|
751
|
+
all'atto del salvataggio della risorsa sul server, mentre *checksum* è un checksum dei dati. Se *with_extra* è ``True``, la funzione
|
|
752
|
+
ritorna sei elementi, e gli elementi aggiuntivi sono un ``dict`` con i metadata associati alla risorsa, o ``None`` se non ci sono
|
|
753
|
+
metadati associati, e il codice della tipologia allegato se presente. Se *check_only* è ``True``, i dati binari della risorsa non
|
|
754
|
+
verranno effettivamente caricati dal dispositivo di archiviazione in cui sono depositati, e *dati* sarà ``None``; questa modalità è
|
|
755
|
+
utile per verificare l'esistenza di una risorsa e il suo checksum senza effettivamente caricarla da remoto (nel caso di archiviazione
|
|
756
|
+
su cloud il caricamento potrebbe essere lento)."""
|
|
736
757
|
if (type == 0) and (not filename):
|
|
737
758
|
raise ValueError('filename must be specified for document type resources')
|
|
759
|
+
if with_extra:
|
|
760
|
+
out_params = ( OUT_DATA, OUT_FILENAME, OUT_ORIGINAL_FILENAME, OUT_DATA_CHECKSUM, OUT_METADATA, OUT_CODE_TIPOLOGIA )
|
|
761
|
+
else:
|
|
762
|
+
out_params = ( OUT_DATA, OUT_FILENAME, OUT_ORIGINAL_FILENAME, OUT_DATA_CHECKSUM )
|
|
738
763
|
return self._execute(CMD_FETCH_BINARY, {
|
|
739
764
|
IN_FIELD_NAME: field_or_tablename,
|
|
740
765
|
IN_ROW_ID: id,
|
|
741
766
|
IN_TYPE: type,
|
|
742
767
|
IN_FILENAME: filename,
|
|
768
|
+
IN_LABEL: label,
|
|
743
769
|
IN_CHECK: check_only,
|
|
744
|
-
},
|
|
770
|
+
}, out_params, progress=progress)
|
|
745
771
|
|
|
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):
|
|
772
|
+
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
773
|
"""Salva un contenuto binario sul server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
748
774
|
questa tabella unita a *id* identificano la scheda a cui abbinare la risorsa; *type* è uno dei valori della *Choice*``Resources``;
|
|
749
775
|
*filename* permette di specificare un nome file interno con cui identificare la risorsa (se ``None`` il server genererà un nome univoco
|
|
750
776
|
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
|
|
777
|
+
effettivi; *desc* è la descrizione da abbinare alla risorsa; *code_azienda* infine identifica l'azienda su cui si sta operando, mentre
|
|
778
|
+
*code_tipologia* permette di specificare una tipologia da abbinare al dati. Per le risorse di tipo immagine aggiuntiva è necessario
|
|
779
|
+
specificare una *label* da abbinare all'immagine per identificarla univocamente. *metadata* può essere un ``dict`` in cui sia chiavi che
|
|
780
|
+
valori siano delle semplici stringhe, e permette di specificare dei metadati aggiuntivi associati alla risorsa binaria che si sta inserendo.
|
|
752
781
|
La funzione restituisce un oggetto ``asyncio.Future`` il cui risultato una volta completato sarà il nome del file interno usato dal
|
|
753
782
|
server per identificare la risorsa, che come detto sopra è uguale a *filename* se quest'ultimo è diverso da ``None``, altrimenti sarà
|
|
754
783
|
il nome file generato dal server.
|
|
@@ -764,13 +793,17 @@ class AsyncClient(Client):
|
|
|
764
793
|
IN_DATA: data,
|
|
765
794
|
IN_DESC: desc,
|
|
766
795
|
IN_FORCE_DELETE: force_delete,
|
|
767
|
-
|
|
796
|
+
IN_LABEL: label,
|
|
797
|
+
IN_METADATA: metadata,
|
|
798
|
+
IN_CODE_TIPOLOGIA: code_tipologia,
|
|
799
|
+
}, OUT_FILENAME, progress=progress, log=log)
|
|
768
800
|
|
|
769
|
-
def translate(self, field, value, language):
|
|
801
|
+
def translate(self, field, value, language, code_azienda=None):
|
|
770
802
|
return self._execute(CMD_TRANSLATE, {
|
|
771
803
|
IN_FIELD: field,
|
|
772
804
|
IN_VALUE: value,
|
|
773
|
-
IN_LANGUAGE: language
|
|
805
|
+
IN_LANGUAGE: language,
|
|
806
|
+
IN_CODE_AZIENDA: code_azienda,
|
|
774
807
|
}, OUT_TEXT)
|
|
775
808
|
|
|
776
809
|
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,15 @@ 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
|
-
originale da cui è stato caricato il contenuto. Se *type* è specificato, la funzione filtrerà i risultati in
|
|
837
|
-
solo le tuple con il *Tipo* corretto.
|
|
838
|
+
originale da cui è stato caricato il contenuto. Se *type* è specificato, la funzione filtrerà i risultati in base ad esso, ritornando
|
|
839
|
+
solo le tuple con il *Tipo* corretto. Se *full* è ``True`` la n-esima tupla ritornata avrà tre valori in più corrispondenti all'etichetta
|
|
840
|
+
dell'immagine aggiuntiva (se specificata), al codice della tipologia dell'allegato e ai metadati associati (se presenti), e la tupla avrà
|
|
841
|
+
quindi la forma ``( Tipo, NomeAllegato, NomeOriginale, Etichetta, CodiceTipologia, Metadati )``.
|
|
838
842
|
Se *success* è diverso da ``None``, la callback verrà invocata in caso di successo con la lista di tuple di cui sopra.
|
|
839
843
|
"""
|
|
840
844
|
if success is not None:
|
|
@@ -850,17 +854,19 @@ class Client(object):
|
|
|
850
854
|
return self.execute(CMD_LIST_BINARIES, {
|
|
851
855
|
IN_FIELD_NAME: field_or_tablename,
|
|
852
856
|
IN_ROW_ID: id,
|
|
857
|
+
IN_FULL: full,
|
|
853
858
|
}, success=callback, error=errback, progress=progress)
|
|
854
859
|
else:
|
|
855
860
|
output = self.execute(CMD_LIST_BINARIES, {
|
|
856
861
|
IN_FIELD_NAME: field_or_tablename,
|
|
857
862
|
IN_ROW_ID: id,
|
|
863
|
+
IN_FULL: full,
|
|
858
864
|
})
|
|
859
865
|
if output[OUT_ERRNO] == OK:
|
|
860
866
|
return [ tuple(row) for row in output[OUT_LIST] if ((type is None) or (row[0] == type)) ]
|
|
861
867
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
862
868
|
|
|
863
|
-
def fetch_image(self, fieldname, id, type, success=None, error=None, progress=None):
|
|
869
|
+
def fetch_image(self, fieldname, id, type, success=None, error=None, progress=None, label=None):
|
|
864
870
|
"""Piccolo wrapper alla funzione :meth:`.fetch_binary`, dedicato alle immagini, con l'unica differenza che il valore di ritorno sarà
|
|
865
871
|
direttamente il contenuto binario dell'immagine in caso di successo (e questo sarà anche l'unico parametro passato alla callback
|
|
866
872
|
*success*)"""
|
|
@@ -878,25 +884,30 @@ class Client(object):
|
|
|
878
884
|
IN_FIELD_NAME: fieldname,
|
|
879
885
|
IN_ROW_ID: id,
|
|
880
886
|
IN_TYPE: type,
|
|
887
|
+
IN_LABEL: label,
|
|
881
888
|
}, success=callback, error=errback, progress=progress)
|
|
882
889
|
else:
|
|
883
890
|
output = self.execute(CMD_FETCH_BINARY, {
|
|
884
891
|
IN_FIELD_NAME: fieldname,
|
|
885
892
|
IN_ROW_ID: id,
|
|
886
893
|
IN_TYPE: type,
|
|
894
|
+
IN_LABEL: label,
|
|
887
895
|
})
|
|
888
896
|
if output[OUT_ERRNO] == OK:
|
|
889
897
|
return output[OUT_DATA]
|
|
890
898
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
891
899
|
|
|
892
|
-
def fetch_binary(self, field_or_tablename, id, type, filename=None, check_only=False, success=None, error=None, progress=None):
|
|
900
|
+
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
901
|
"""Carica un contenuto binario dal server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
894
902
|
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*
|
|
903
|
+
``Resources``, mentre *filename* e *label* hanno senso solo per identificare rispettivamente le risorse di tipo documento ed immagine
|
|
904
|
+
aggiuntiva.
|
|
896
905
|
La funzione ritorna una tupla di quattro elementi: ( *dati*, *filename*, *original_filename*, *checksum* ). Questi quattro elementi
|
|
897
906
|
sono anche i parametri passati alla callback *success* in caso di successo. *dati* sono i dati binari che sono stati caricati dal
|
|
898
907
|
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.
|
|
908
|
+
stato specificato all'atto del salvataggio della risorsa sul server, mentre *checksum* è un checksum dei dati. Se *with_extra* è
|
|
909
|
+
``True``, la funzione ritorna sei elementi, e gli elementi aggiuntivi sono un ``dict`` con i metadata associati alla risorsa, o ``None``
|
|
910
|
+
se non ci sono metadati associati, e il codice della tipologia allegato se presente.
|
|
900
911
|
Se *check_only* è ``True``, i dati binari della risorsa non verranno effettivamente caricati dal dispositivo di archiviazione in cui
|
|
901
912
|
sono depositati, e *dati* sarà ``None``; questa modalità è utile per verificare l'esistenza di una risorsa e il suo checksum senza
|
|
902
913
|
effettivamente caricarla da remoto (nel caso di archiviazione su cloud il caricamento potrebbe essere lento)."""
|
|
@@ -905,7 +916,10 @@ class Client(object):
|
|
|
905
916
|
if success is not None:
|
|
906
917
|
def callback(output, dummy):
|
|
907
918
|
if output[OUT_ERRNO] == OK:
|
|
908
|
-
|
|
919
|
+
if with_extra:
|
|
920
|
+
success(output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM], output[OUT_METADATA], output[OUT_CODE_TIPOLOGIA])
|
|
921
|
+
else:
|
|
922
|
+
success(output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM])
|
|
909
923
|
elif error is not None:
|
|
910
924
|
error(Error(output[OUT_ERRNO], output[OUT_ERROR]))
|
|
911
925
|
def errback(errno, errstr, dummy):
|
|
@@ -917,6 +931,7 @@ class Client(object):
|
|
|
917
931
|
IN_ROW_ID: id,
|
|
918
932
|
IN_TYPE: type,
|
|
919
933
|
IN_FILENAME: filename,
|
|
934
|
+
IN_LABEL: label,
|
|
920
935
|
IN_CHECK: check_only,
|
|
921
936
|
}, success=callback, error=errback, progress=progress)
|
|
922
937
|
else:
|
|
@@ -925,18 +940,25 @@ class Client(object):
|
|
|
925
940
|
IN_ROW_ID: id,
|
|
926
941
|
IN_TYPE: type,
|
|
927
942
|
IN_FILENAME: filename,
|
|
943
|
+
IN_LABEL: label,
|
|
928
944
|
IN_CHECK: check_only,
|
|
929
945
|
})
|
|
930
946
|
if output[OUT_ERRNO] == OK:
|
|
931
|
-
|
|
947
|
+
if with_extra:
|
|
948
|
+
return output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM], output[OUT_METADATA], output[OUT_CODE_TIPOLOGIA]
|
|
949
|
+
else:
|
|
950
|
+
return output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM]
|
|
932
951
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
933
952
|
|
|
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):
|
|
953
|
+
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
954
|
"""Salva un contenuto binario sul server. *field_or_tablename* può essere un nome tabella o un campo da cui risolvere il nome tabella;
|
|
936
955
|
questa tabella unita a *id* identificano la scheda a cui abbinare la risorsa; *type* è uno dei valori della *Choice*``Resources``;
|
|
937
956
|
*filename* permette di specificare un nome file interno con cui identificare la risorsa (se ``None`` il server genererà un nome univoco
|
|
938
957
|
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
|
|
958
|
+
effettivi; *desc* è la descrizione da abbinare alla risorsa; *code_azienda* infine identifica l'azienda su cui si sta operando, mentre
|
|
959
|
+
*code_tipologia* permette di specificare una tipologia da abbinare al dati. Per le risorse di tipo immagine aggiuntiva è necessario
|
|
960
|
+
specificare una *label* da abbinare all'immagine per identificarla univocamente. *metadata* può essere un ``dict`` in cui sia chiavi che
|
|
961
|
+
valori siano delle semplici stringhe, e permette di specificare dei metadati aggiuntivi associati alla risorsa binaria che si sta inserendo.
|
|
940
962
|
La funzione ritorna il nome del file interno usato dal server per identificare la risorsa, che come detto sopra è uguale a *filename* se
|
|
941
963
|
quest'ultimo è diverso da ``None``, altrimenti verrà ritornato il nome file generato dal server. La callback *success* se specificata
|
|
942
964
|
riceverà *filename* come unico parametro.
|
|
@@ -945,6 +967,8 @@ class Client(object):
|
|
|
945
967
|
if success is not None:
|
|
946
968
|
def callback(output, dummy):
|
|
947
969
|
if output[OUT_ERRNO] == OK:
|
|
970
|
+
if log is not None:
|
|
971
|
+
ErrorList(output[OUT_LOG] or []).prepare_log(log)
|
|
948
972
|
success(output[OUT_FILENAME])
|
|
949
973
|
elif error is not None:
|
|
950
974
|
error(Error(output[OUT_ERRNO], output[OUT_ERROR]))
|
|
@@ -962,6 +986,9 @@ class Client(object):
|
|
|
962
986
|
IN_DATA: data,
|
|
963
987
|
IN_DESC: desc,
|
|
964
988
|
IN_FORCE_DELETE: force_delete,
|
|
989
|
+
IN_LABEL: label,
|
|
990
|
+
IN_METADATA: metadata,
|
|
991
|
+
IN_CODE_TIPOLOGIA: code_tipologia,
|
|
965
992
|
}, success=callback, error=errback, progress=progress)
|
|
966
993
|
else:
|
|
967
994
|
output = self.execute(CMD_STORE_BINARY, {
|
|
@@ -974,16 +1001,22 @@ class Client(object):
|
|
|
974
1001
|
IN_DATA: data,
|
|
975
1002
|
IN_DESC: desc,
|
|
976
1003
|
IN_FORCE_DELETE: force_delete,
|
|
1004
|
+
IN_LABEL: label,
|
|
1005
|
+
IN_METADATA: metadata,
|
|
1006
|
+
IN_CODE_TIPOLOGIA: code_tipologia,
|
|
977
1007
|
})
|
|
978
1008
|
if output[OUT_ERRNO] == OK:
|
|
1009
|
+
if log is not None:
|
|
1010
|
+
ErrorList(output[OUT_LOG] or []).prepare_log(log)
|
|
979
1011
|
return output[OUT_FILENAME]
|
|
980
1012
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|
|
981
1013
|
|
|
982
|
-
def translate(self, field, value, language):
|
|
1014
|
+
def translate(self, field, value, language, code_azienda=None):
|
|
983
1015
|
output = self.execute(CMD_TRANSLATE, {
|
|
984
1016
|
IN_FIELD: field,
|
|
985
1017
|
IN_VALUE: value,
|
|
986
|
-
IN_LANGUAGE: language
|
|
1018
|
+
IN_LANGUAGE: language,
|
|
1019
|
+
IN_CODE_AZIENDA: code_azienda,
|
|
987
1020
|
})
|
|
988
1021
|
if output[OUT_ERRNO] != OK:
|
|
989
1022
|
raise Error(output[OUT_ERRNO], output[OUT_ERROR])
|