kongalib 2.0.0__cp39-cp39-win_amd64.whl → 2.0.0.post1__cp39-cp39-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.

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 ._kongalib import Decimal, Deferred, JSONEncoder, JSONDecoder, 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
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, data, dummy):
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 len(answer) > 0:
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
- if finalize_output is not None:
119
- output = finalize_output(output)
120
- loop.call_soon_threadsafe(self._safe_set_result, future, output)
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
- if finalize_output is not None:
123
- output = finalize_output(output)
124
- loop.call_soon_threadsafe(self._safe_set_result, future, output)
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* ha senso solo per identificare le risorse di tipo documento.
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 *check_only* è ``True``, i dati
733
- binari della risorsa non verranno effettivamente caricati dal dispositivo di archiviazione in cui sono depositati, e *dati* sarà
734
- ``None``; questa modalità è utile per verificare l'esistenza di una risorsa e il suo checksum senza effettivamente caricarla da remoto
735
- (nel caso di archiviazione su cloud il caricamento potrebbe essere lento)."""
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
- }, ( OUT_DATA, OUT_FILENAME, OUT_ORIGINAL_FILENAME, OUT_DATA_CHECKSUM ), progress=progress)
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
- }, OUT_FILENAME, progress=progress)
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 ._kongalib import Client as ClientImpl
27
- from ._kongalib import start_timer
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* ha senso solo per identificare le risorse di tipo documento.
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
- success(output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM])
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
- return output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM]
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])