kongalib 2.0.0__cp310-cp310-win_amd64.whl → 2.0.2__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.

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,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 baso ad esso, ritornando solo le tuple con il *Tipo* corretto.
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* ha senso solo per identificare le risorse di tipo documento.
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 *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)."""
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
- }, ( OUT_DATA, OUT_FILENAME, OUT_ORIGINAL_FILENAME, OUT_DATA_CHECKSUM ), progress=progress)
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
- }, OUT_FILENAME, progress=progress)
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 ._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,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 baso ad esso, ritornando
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* ha senso solo per identificare le risorse di tipo documento.
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
- success(output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM])
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
- return output[OUT_DATA], output[OUT_FILENAME], output[OUT_ORIGINAL_FILENAME], output[OUT_DATA_CHECKSUM]
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])