fusion-platform-python-sdk 1.15.11__tar.gz → 1.15.12__tar.gz

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.
Files changed (57) hide show
  1. {fusion_platform_python_sdk-1.15.11/fusion_platform_python_sdk.egg-info → fusion_platform_python_sdk-1.15.12}/PKG-INFO +1 -1
  2. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/__init__.py +2 -2
  3. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/base.py +1 -1
  4. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/command.py +222 -26
  5. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/fusion_platform_sdk.pdf +0 -0
  6. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/model.py +7 -0
  7. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/translations.py +38 -8
  8. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12/fusion_platform_python_sdk.egg-info}/PKG-INFO +1 -1
  9. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/setup.py +1 -1
  10. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/LICENSE.txt +0 -0
  11. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/MANIFEST.in +0 -0
  12. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/README.md +0 -0
  13. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/__main__.py +0 -0
  14. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/common/__init__.py +0 -0
  15. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/common/raise_thread.py +0 -0
  16. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/common/utilities.py +0 -0
  17. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/detailed_example.py +0 -0
  18. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/documentation.py +0 -0
  19. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/glasgow.geojson +0 -0
  20. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/lake_district.geojson +0 -0
  21. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/localisations.py +0 -0
  22. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/localise.py +0 -0
  23. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/__init__.py +0 -0
  24. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/credit.md +0 -0
  25. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/credit.py +0 -0
  26. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/data.md +0 -0
  27. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/data.py +0 -0
  28. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/data_file.md +0 -0
  29. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/data_file.py +0 -0
  30. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/fields.py +0 -0
  31. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/organisation.md +0 -0
  32. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/organisation.py +0 -0
  33. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process.md +0 -0
  34. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process.py +0 -0
  35. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process_execution.md +0 -0
  36. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process_execution.py +0 -0
  37. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process_service_execution.md +0 -0
  38. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process_service_execution.py +0 -0
  39. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process_service_execution_log.md +0 -0
  40. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/process_service_execution_log.py +0 -0
  41. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/service.md +0 -0
  42. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/service.py +0 -0
  43. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/user.md +0 -0
  44. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/models/user.py +0 -0
  45. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/quick_example.py +0 -0
  46. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform/session.py +0 -0
  47. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform_python_sdk.egg-info/SOURCES.txt +0 -0
  48. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform_python_sdk.egg-info/dependency_links.txt +0 -0
  49. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform_python_sdk.egg-info/entry_points.txt +0 -0
  50. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform_python_sdk.egg-info/requires.txt +0 -0
  51. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/fusion_platform_python_sdk.egg-info/top_level.txt +0 -0
  52. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/setup.cfg +0 -0
  53. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/tests/test_base.py +0 -0
  54. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/tests/test_command.py +0 -0
  55. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/tests/test_init.py +0 -0
  56. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/tests/test_localise.py +0 -0
  57. {fusion_platform_python_sdk-1.15.11 → fusion_platform_python_sdk-1.15.12}/tests/test_session.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fusion-platform-python-sdk
3
- Version: 1.15.11
3
+ Version: 1.15.12
4
4
  Summary: Python SDK used to interact with the Fusion Platform(r)
5
5
  Home-page: https://github.com/d-cat-support/fusion-platform-python-sdk
6
6
  Author: Digital Content Analysis Technology Ltd
@@ -11,8 +11,8 @@ API, and this is defined within the corresponding OpenAPI 3.0 specification, whi
11
11
  """
12
12
 
13
13
  # Do not modify the following two lines as they are maintained by the version.sh script.
14
- __version__ = '1.15.11'
15
- __version_date__ = '2024-12-13T13:48:29Z'
14
+ __version__ = '1.15.12'
15
+ __version_date__ = '2024-12-20T11:33:56Z'
16
16
 
17
17
  # Exclude certain sub-modules from documentation.
18
18
  # @formatter:off
@@ -31,7 +31,7 @@ class Base:
31
31
  Localise.setup()
32
32
 
33
33
  # Set up logging.
34
- logging.basicConfig(format='%(asctime)s.%(msecs)03d [%(levelname)s] %(pathname)s:%(funcName)s:%(lineno)d - %(message)s')
34
+ logging.basicConfig(format='%(asctime)s.%(msecs)03d [%(levelname)s] %(filename)s:%(funcName)s:%(lineno)d - %(message)s')
35
35
  self._logger = logging.getLogger(fusion_platform.FUSION_PLATFORM_LOGGER)
36
36
  self._logger.debug('sdk %s (%s): %s', fusion_platform.__version__, fusion_platform.__version_date__, self.__class__.__name__)
37
37
 
@@ -345,6 +345,60 @@ class Command(Base):
345
345
 
346
346
  return process_definition
347
347
 
348
+ def display_service(self, organisation, service_name):
349
+ """
350
+ Displays the documentation for the service. If the service does not exist, it will be ignored.
351
+
352
+ Args:
353
+ organisation: The logged in organisation.
354
+ service_name: The name of the service to display.
355
+
356
+ Returns:
357
+ True if a service was displayed.
358
+ """
359
+ found = False
360
+
361
+ # Try to find any existing service, ignoring any error.
362
+ try:
363
+ service = self.get_service(organisation, service_name)
364
+ found = True
365
+
366
+ self.__print_service(service)
367
+
368
+ except CommandError as e:
369
+ self.__print(logging.DEBUG, str(e))
370
+
371
+ return found
372
+
373
+ def display_process(self, organisation, process_name):
374
+ """
375
+ Displays the current configuration of the process. If the process does not exist, it will be ignored.
376
+
377
+ Args:
378
+ organisation: The logged in organisation.
379
+ process_name: The name of the process to display.
380
+
381
+ Returns:
382
+ True if a process was displayed.
383
+ """
384
+ found = False
385
+
386
+ # Try to find any existing process, ignoring any error.
387
+ try:
388
+ process, _ = self.get_process_or_execution(organisation, process_name)
389
+ found = True
390
+
391
+ self.__print_process(process)
392
+
393
+ # Display the status of any execution.
394
+ for execution in process.executions:
395
+ self.__print_execution(execution)
396
+
397
+ except CommandError as e:
398
+ self.__print(logging.DEBUG, str(e))
399
+
400
+ return found
401
+
348
402
  def __download_execution(self, process, download_inputs, download_outputs, download_storage, download_intermediate, download_components, output_dir, execution):
349
403
  """
350
404
  Downloads an execution.
@@ -756,10 +810,13 @@ class Command(Base):
756
810
 
757
811
  Args:
758
812
  organisation: The logged in organisation.
759
- process_name: The name of the process to be downloaded. This can also be the id of a process or an execution.
813
+ process_name: The name of the process. This can also be the id of a process or an execution.
760
814
 
761
815
  Returns:
762
816
  The found process and/or execution.
817
+
818
+ Raises:
819
+ CommandError: if a process or execution could not be found.
763
820
  """
764
821
 
765
822
  # Attempt to find the process.
@@ -782,6 +839,37 @@ class Command(Base):
782
839
 
783
840
  return process, execution
784
841
 
842
+ def get_service(self, organisation, service_name):
843
+ """
844
+ Attempts to find a service using the given service name, service id or SSD id.
845
+
846
+ Args:
847
+ organisation: The logged in organisation.
848
+ service_name: The name of the service. This can also be the id or SSD id of a service.
849
+
850
+ Returns:
851
+ The found service.
852
+
853
+ Raises:
854
+ CommandError: if a service could not be found.
855
+ """
856
+
857
+ # Find the service using its case-sensitive name (starts with).
858
+ service, _ = organisation.find_services(name=service_name)
859
+
860
+ # If the service cannot be found, try to find it by its id or SSD id.
861
+ if service is None:
862
+ service = next((item for item in organisation.services if (str(item.id) == service_name) or (str(item.ssd_id) == service_name)), None)
863
+
864
+ # If the service still cannot be found, then try it as a specific service for the organisation.
865
+ if service is None:
866
+ service = next((item for item in organisation.own_services if (str(item.id) == service_name) or (str(item.ssd_id) == service_name)), None)
867
+
868
+ if service is None:
869
+ raise CommandError(i18n.t('command.no_such_service', service=service_name))
870
+
871
+ return service
872
+
785
873
  def __get_storage_data_item(self, process, group_index, group_count, ssd_id, chain_index):
786
874
  """
787
875
  Gets the storage date item for a process' group and chain index.
@@ -897,6 +985,7 @@ class Command(Base):
897
985
  self._logger.setLevel(logging.CRITICAL)
898
986
 
899
987
  if arguments.debug:
988
+ self._logger.setLevel(logging.DEBUG)
900
989
  self.__print_level = logging.DEBUG
901
990
  else:
902
991
  self.__print_level = logging.INFO
@@ -905,8 +994,15 @@ class Command(Base):
905
994
  # Login to the correct deployment and select the organisation.
906
995
  organisation, _, _ = self.login(arguments.deployment, arguments.email, arguments.organisation)
907
996
 
908
- # Perform the start, define or download.
909
- if arguments.command == i18n.t('command.start.command'):
997
+ # Perform the display, start, define or download.
998
+ if arguments.command == i18n.t('command.display.command'):
999
+ # Display a service or process with the specified name or ids. If a service is displayed, we do not display a process.
1000
+ for process_or_service in arguments.process_or_service:
1001
+ if not self.display_service(organisation, process_or_service):
1002
+ if not self.display_process(organisation, process_or_service):
1003
+ self.__print(logging.WARNING, i18n.t('command.no_process_or_service', process_or_service=process_or_service))
1004
+
1005
+ elif arguments.command == i18n.t('command.start.command'):
910
1006
  # Start one or more processes.
911
1007
  for service_or_yaml in arguments.service_or_yaml:
912
1008
  # Extract the command line or YAML file arguments.
@@ -983,12 +1079,13 @@ class Command(Base):
983
1079
  version=i18n.t('command.version_content', version=fusion_platform.__version__, version_date=fusion_platform.__version_date__))
984
1080
 
985
1081
  subparsers.required = True
1082
+ parser_display = subparsers.add_parser(i18n.t('command.display.command'), help=i18n.t('command.display.help'))
986
1083
  parser_start = subparsers.add_parser(i18n.t('command.start.command'), help=i18n.t('command.start.help'))
987
1084
  parser_define = subparsers.add_parser(i18n.t('command.define.command'), help=i18n.t('command.define.help'))
988
1085
  parser_download = subparsers.add_parser(i18n.t('command.download.command'), help=i18n.t('command.download.help'))
989
1086
 
990
1087
  # Add in the common arguments.
991
- for subparser in [parser_start, parser_define, parser_download]:
1088
+ for subparser in [parser_display, parser_start, parser_define, parser_download]:
992
1089
  subparser.add_argument(i18n.t('command.deployment_short'), i18n.t('command.deployment_long'), help=i18n.t('command.deployment_help'),
993
1090
  default=Command._DEPLOYMENT_PRODUCTION_IRL)
994
1091
  subparser.add_argument(i18n.t('command.email_short'), i18n.t('command.email_long'), help=i18n.t('command.email_help'))
@@ -996,6 +1093,9 @@ class Command(Base):
996
1093
  subparser.add_argument(i18n.t('command.debug_short'), i18n.t('command.debug_long'), help=i18n.t('command.debug_help'), default=False,
997
1094
  action="store_true")
998
1095
 
1096
+ # Display arguments.
1097
+ parser_display.add_argument(i18n.t('command.display.service_or_process_long'), help=i18n.t('command.display.service_or_process_help'), nargs='+')
1098
+
999
1099
  # Start arguments.
1000
1100
  parser_start.add_argument(i18n.t('command.start.definition_long'), help=i18n.t('command.start.definition_help'), nargs='+')
1001
1101
  parser_start.add_argument(i18n.t('command.start.input_list_short'), i18n.t('command.start.input_list_long'), help=i18n.t('command.start.input_list_help'),
@@ -1062,6 +1162,48 @@ class Command(Base):
1062
1162
  else:
1063
1163
  print(message)
1064
1164
 
1165
+ def __print_execution(self, execution):
1166
+ """
1167
+ Prints an execution. This just shows the status in a simple format.
1168
+
1169
+ Args:
1170
+ execution: The execution to be logged.
1171
+ """
1172
+
1173
+ # Form the status of the execution.
1174
+ status = ''
1175
+ group = ''
1176
+
1177
+ if execution.success:
1178
+ status = i18n.t('command.log_execution_success')
1179
+
1180
+ elif execution.stopped:
1181
+ status = i18n.t('command.log_execution_stopped')
1182
+
1183
+ elif execution.progress < 100:
1184
+ status = i18n.t('command.log_execution_progress', progress=execution.progress)
1185
+
1186
+ else:
1187
+ abort_reason = i18n.t('command.log_execution_abort_reason', abort_reason=execution.abort_reason) if hasattr(execution,
1188
+ Model._FIELD_ABORT_REASON) else ''
1189
+ exit_type = i18n.t('command.log_execution_exit_type', exit_type=execution.exit_type) if hasattr(execution, Model._FIELD_EXIT_TYPE) else ''
1190
+ status = i18n.t('command.log_execution_failed', exit_type=exit_type, abort_reason=abort_reason)
1191
+
1192
+ started_at = execution.started_at.strftime('%Y-%m-%d %H:%M:%S')
1193
+ ended_at = i18n.t('command.log_execution_ended_at', ended_at=execution.ended_at.strftime('%Y-%m-%d %H:%M:%S')) if hasattr(execution,
1194
+ Model._FIELD_ENDED_AT) else ''
1195
+ period = i18n.t('command.log_execution_period', started_at=started_at, ended_at=ended_at)
1196
+ duration = i18n.t('command.log_execution_duration', minutes=round((execution.ended_at - execution.started_at).total_seconds() // 60)) if hasattr(execution,
1197
+ Model._FIELD_ENDED_AT) and (
1198
+ execution.ended_at is not None) else ''
1199
+
1200
+ if (hasattr(execution, Model._FIELD_GROUP_ID) and (execution.group_id is not None)) and (
1201
+ hasattr(execution, Model._FIELD_GROUP_INDEX) and (execution.group_index is not None)) and (
1202
+ hasattr(execution, Model._FIELD_GROUP_COUNT) and (execution.group_count is not None)):
1203
+ group = i18n.t('command.log_execution_group', group_id=execution.group_id, group_index=execution.group_index, group_count=execution.group_count)
1204
+
1205
+ self.__print(logging.INFO, i18n.t('command.log_execution', id=execution.id, period=period, status=status, duration=duration, group=group))
1206
+
1065
1207
  def __print_process(self, process):
1066
1208
  """
1067
1209
  Prints a process.
@@ -1076,26 +1218,88 @@ class Command(Base):
1076
1218
  if hasattr(process, field):
1077
1219
  self.__print(logging.INFO, i18n.t('command.log_field', field=field, value=getattr(process, field)))
1078
1220
 
1079
- self.__print(logging.INFO, i18n.t('command.log_divider'))
1080
- self.__print(logging.INFO, i18n.t('command.log_inputs'))
1221
+ process_inputs = [input for input in process.inputs]
1222
+
1223
+ if len(process_inputs) > 0:
1224
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1225
+ self.__print(logging.INFO, i18n.t('command.log_inputs'))
1226
+
1227
+ for data_item in process_inputs:
1228
+ self.__print(logging.INFO, str(data_item), format=False)
1229
+
1230
+ process_options = [option for option in process.options]
1231
+
1232
+ if len(process_options) > 0:
1233
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1234
+ self.__print(logging.INFO, i18n.t('command.log_options'))
1235
+
1236
+ for option in process_options:
1237
+ self.__print(logging.INFO, str(option), format=False)
1238
+
1239
+ process_dispatchers = [dispatcher for dispatcher in process.dispatchers]
1240
+
1241
+ if len(process_dispatchers) > 0:
1242
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1243
+ self.__print(logging.INFO, i18n.t('command.log_dispatchers'))
1081
1244
 
1082
- for data_item in process.inputs:
1083
- self.__print(logging.INFO, str(data_item), format=False)
1245
+ for dispatcher in process_dispatchers:
1246
+ self.__print(logging.INFO, i18n.t('command.log_subdivider'))
1247
+ self.__print(logging.INFO, str(dispatcher), format=False)
1248
+
1249
+ for option in dispatcher.options:
1250
+ self.__print(logging.INFO, str(option), format=False)
1251
+
1252
+ self.__print(logging.INFO, i18n.t('command.log_bookend'))
1253
+
1254
+ def __print_service(self, service):
1255
+ """
1256
+ Prints the documentation for a service.
1257
+
1258
+ Args:
1259
+ service: The service to be logged.
1260
+ """
1261
+ self.__print(logging.INFO, i18n.t('command.log_bookend'))
1262
+ self.__print(logging.INFO, i18n.t('command.log_service', service=service.name))
1263
+
1264
+ self.__print(logging.INFO, i18n.t('command.log_field', field=Model._FIELD_CATEGORIES, value=service.categories))
1265
+ self.__print(logging.INFO, i18n.t('command.log_field', field=Model._FIELD_KEYWORDS, value=service.keywords))
1084
1266
 
1085
1267
  self.__print(logging.INFO, i18n.t('command.log_divider'))
1086
- self.__print(logging.INFO, i18n.t('command.log_options'))
1268
+ self.__print(logging.INFO, i18n.t('command.log_summary'))
1269
+ self.__print(logging.INFO, service.documentation_summary, format=False)
1087
1270
 
1088
- for option in process.options:
1089
- self.__print(logging.INFO, str(option), format=False)
1271
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1272
+ self.__print(logging.INFO, i18n.t('command.log_description'))
1273
+ self.__print(logging.INFO, service.documentation_description, format=False)
1090
1274
 
1091
1275
  self.__print(logging.INFO, i18n.t('command.log_divider'))
1092
- self.__print(logging.INFO, i18n.t('command.log_dispatchers'))
1276
+ self.__print(logging.INFO, i18n.t('command.log_assumptions'))
1277
+ self.__print(logging.INFO, service.documentation_assumptions, format=False)
1278
+
1279
+ if len(service.documentation_actions.strip()) > 0:
1280
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1281
+ self.__print(logging.INFO, i18n.t('command.log_actions'))
1282
+ self.__print(logging.INFO, service.documentation_actions, format=False)
1093
1283
 
1094
- for dispatcher in process.dispatchers:
1095
- self.__print(logging.INFO, i18n.t('command.log_subdivider'))
1096
- self.__print(logging.INFO, str(dispatcher), format=False)
1284
+ if hasattr(service, Model._FIELD_DOCUMENTATION_INPUTS):
1285
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1286
+ self.__print(logging.INFO, i18n.t('command.log_inputs'))
1097
1287
 
1098
- for option in dispatcher.options:
1288
+ for input in service.documentation_inputs:
1289
+ self.__print(logging.INFO, str(input), format=False)
1290
+
1291
+ if hasattr(service, Model._FIELD_DOCUMENTATION_OUTPUTS):
1292
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1293
+ self.__print(logging.INFO, i18n.t('command.log_outputs'))
1294
+
1295
+ for output in service.documentation_outputs:
1296
+ self.__print(logging.INFO, str(output), format=False)
1297
+
1298
+ if hasattr(service, Model._FIELD_DOCUMENTATION_OPTIONS):
1299
+ self.__print(logging.INFO, i18n.t('command.log_divider'))
1300
+ self.__print(logging.INFO, i18n.t('command.log_options'))
1301
+
1302
+ for option in service.documentation_options:
1099
1303
  self.__print(logging.INFO, str(option), format=False)
1100
1304
 
1101
1305
  self.__print(logging.INFO, i18n.t('command.log_bookend'))
@@ -1237,16 +1441,8 @@ class Command(Base):
1237
1441
  else:
1238
1442
  data_items = []
1239
1443
 
1240
- # Find the service using its case-sensitive name (starts with).
1241
- service, _ = organisation.find_services(name=service_name)
1242
-
1243
- # If the service cannot be found, then try it as a specific service for the organisation.
1244
- if service is None:
1245
- service = next((item for item in organisation.own_services if item.name == service_name), None)
1246
-
1247
- if service is None:
1248
- raise CommandError(i18n.t('command.no_such_service', service=service_name))
1249
-
1444
+ # Find the service.
1445
+ service = self.get_service(organisation, service_name)
1250
1446
  self.__print(logging.DEBUG, i18n.t('command.using_service', service=service.name))
1251
1447
 
1252
1448
  # Create the process with its options and inputs.
@@ -45,9 +45,11 @@ class Model(Base):
45
45
  _EXTRAS_LIST = None
46
46
 
47
47
  # Useful fields and templates.
48
+ _FIELD_ABORT_REASON = 'abort_reason'
48
49
  _FIELD_AVAILABLE_DISPATCHERS = 'available_dispatchers'
49
50
  _FIELD_BOUNDS = 'bounds'
50
51
  _FIELD_CATEGORY = 'category'
52
+ _FIELD_CATEGORIES = 'categories'
51
53
  _FIELD_CHAINS = 'chains'
52
54
  _FIELD_CHAIN_INDEX = 'chain_index'
53
55
  _FIELD_CONSTRAINED_NAMES = 'constrained_names'
@@ -58,8 +60,13 @@ class Model(Base):
58
60
  _FIELD_DISPATCHERS = 'dispatchers'
59
61
  _FIELD_DOCUMENTATION_SUMMARY = 'documentation_summary'
60
62
  _FIELD_DOCUMENTATION_DESCRIPTION = 'documentation_description'
63
+ _FIELD_DOCUMENTATION_INPUTS = 'documentation_inputs'
64
+ _FIELD_DOCUMENTATION_OUTPUTS = 'documentation_outputs'
65
+ _FIELD_DOCUMENTATION_OPTIONS = 'documentation_options'
66
+ _FIELD_ENDED_AT = 'ended_at'
61
67
  _FIELD_ERROR = 'error'
62
68
  _FIELD_EXECUTIONS = 'executions'
69
+ _FIELD_EXIT_TYPE = 'exit_type'
63
70
  _FIELD_EXTENSIONS = 'extensions'
64
71
  _FIELD_FILE = 'file'
65
72
  _FIELD_FILE_NAME = 'file_name'
@@ -13,19 +13,37 @@ import i18n
13
13
  # @formatter:off
14
14
  i18n.add_translation('command.validate_constrained_error', 'Not one of %{constrained}', 'en')
15
15
  i18n.add_translation('command.unknown_command', 'Unknown command \'%{command}\'', 'en')
16
+ i18n.add_translation('command.no_process_or_service', 'No such service, process or execution \'%{process_or_service}\'', 'en')
16
17
  i18n.add_translation('command.no_such_service', 'No such service \'%{service}\'', 'en')
17
18
  i18n.add_translation('command.no_such_process', 'No such process or execution \'%{process}\'', 'en')
18
19
  i18n.add_translation('command.no_such_organisation', 'No such organisation \'%{organisation}\'', 'en')
19
20
  i18n.add_translation('command.no_such_input', 'No such input \'%{input_name}\'', 'en')
20
21
  i18n.add_translation('command.no_executions', 'No executions for process \'%{process}\'', 'en')
21
22
  i18n.add_translation('command.invalid_login_response', 'Incorrect username or password', 'en')
22
- i18n.add_translation('command.log_subdivider', '................................................................................................', 'en')
23
- i18n.add_translation('command.log_process', 'Process \'%{process}\'', 'en')
23
+ i18n.add_translation('command.log_execution_group', ' (group \'%{group_id}\' %{group_index} of %{group_count})', 'en')
24
+ i18n.add_translation('command.log_execution_duration', ' - %{minutes} minute(s)', 'en')
25
+ i18n.add_translation('command.log_execution_period', ' (%{started_at}%{ended_at})', 'en')
26
+ i18n.add_translation('command.log_execution_ended_at', ' -> %{ended_at}', 'en')
27
+ i18n.add_translation('command.log_execution_failed', 'failed%{exit_type}%{abort_reason}', 'en')
28
+ i18n.add_translation('command.log_execution_exit_type', ' (%{exit_type})', 'en')
29
+ i18n.add_translation('command.log_execution_abort_reason', ': %{abort_reason}', 'en')
30
+ i18n.add_translation('command.log_execution_stopped', 'stopped', 'en')
31
+ i18n.add_translation('command.log_execution_progress', 'processing %{progress}%%', 'en')
32
+ i18n.add_translation('command.log_execution_success', 'success', 'en')
33
+ i18n.add_translation('command.log_actions', 'Actions:', 'en')
34
+ i18n.add_translation('command.log_assumptions', 'Assumptions:', 'en')
35
+ i18n.add_translation('command.log_description', 'Description:', 'en')
36
+ i18n.add_translation('command.log_summary', 'Summary:', 'en')
37
+ i18n.add_translation('command.log_dispatchers', 'Dispatchers:', 'en')
24
38
  i18n.add_translation('command.log_options', 'Options:', 'en')
39
+ i18n.add_translation('command.log_outputs', 'Outputs:', 'en')
25
40
  i18n.add_translation('command.log_inputs', 'Inputs:', 'en')
41
+ i18n.add_translation('command.log_execution', 'Execution \'%{id}\'%{period}: %{status}%{duration}%{group}', 'en')
42
+ i18n.add_translation('command.log_service', 'Service \'%{service}\'', 'en')
43
+ i18n.add_translation('command.log_process', 'Process \'%{process}\'', 'en')
26
44
  i18n.add_translation('command.log_field', '%{field}: %{value}', 'en')
45
+ i18n.add_translation('command.log_subdivider', '................................................................................................', 'en')
27
46
  i18n.add_translation('command.log_divider', '------------------------------------------------------------------------------------------------', 'en')
28
- i18n.add_translation('command.log_dispatchers', 'Dispatchers:', 'en')
29
47
  i18n.add_translation('command.log_bookend', '************************************************************************************************', 'en')
30
48
  i18n.add_translation('command.wait_for_next', 'Waiting for next execution...', 'en')
31
49
  i18n.add_translation('command.using_storage', 'Uploading storage \'%{filename}\' with id %{storage_id} to \'%{storage_name}\'', 'en')
@@ -97,7 +115,11 @@ i18n.add_translation('command.start.definition_help', 'the names of the service
97
115
  i18n.add_translation('command.start.definition_long', 'service_or_yaml', 'en')
98
116
  i18n.add_translation('command.start.help', 'starts a process', 'en')
99
117
  i18n.add_translation('command.start.command', 'start', 'en')
100
- i18n.add_translation('command.subparser', 'starts, defines or downloads a process', 'en')
118
+ i18n.add_translation('command.display.service_or_process_help', 'the names of the service, id, SSD id, process, process id or associated execution id that are to be displayed', 'en')
119
+ i18n.add_translation('command.display.service_or_process_long', 'process_or_service', 'en')
120
+ i18n.add_translation('command.display.help', 'displays service information or a configured process', 'en')
121
+ i18n.add_translation('command.display.command', 'display', 'en')
122
+ i18n.add_translation('command.subparser', 'displays a service or process, or starts, defines or downloads a process', 'en')
101
123
  i18n.add_translation('command.version_content', '%%(prog)s %{version} (%{version_date})', 'en')
102
124
  i18n.add_translation('command.version_help', 'show the version information and exit', 'en')
103
125
  i18n.add_translation('command.version_long', '--version', 'en')
@@ -117,18 +139,26 @@ i18n.add_translation('command.deployment_short', '-y', 'en')
117
139
  i18n.add_translation('command.epilog', '''
118
140
  For more detailed options, use:
119
141
 
142
+ fusion_platform display --help
120
143
  fusion_platform start --help
121
144
  fusion_platform define --help
122
145
  fusion_platform download --help
123
146
 
124
147
  ''', 'en')
125
148
  i18n.add_translation('command.description', '''
126
- Use this command to execute any service (by case-sensitive name) or to retrieve its inputs and outputs. The service can be selected via command line options or
127
- defined by a YAML file. This command can also be used to build a YAML file from an existing process.
149
+ Use this command to display service information and processes, and to start, download or define processes. Processes can be selected via command line options or
150
+ defined by a YAML file.
128
151
 
129
152
  Usage:
130
- The following will attempt to create one or more processes from the given \'service_name\' to use the inputs (in order) and options and execute them. All processes
131
- will use the same inputs and options:
153
+ The following will display information about one or more services or processes from the given \'service_or_process_name\'.
154
+
155
+ fusion_platform display <service_or_process_name> ...
156
+
157
+ For a service, this will display the full service documentation, including its expected inputs and options. For a process, it will show the current process
158
+ configuration.
159
+
160
+ The following will attempt to create one or more processes from the given \'service_name\' to use the inputs (in order) and options and execute them. All
161
+ processes will use the same inputs and options:
132
162
 
133
163
  fusion_platform start <service_name> ... -l <input_file|input_name> ... -p <option=value> ...
134
164
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fusion-platform-python-sdk
3
- Version: 1.15.11
3
+ Version: 1.15.12
4
4
  Summary: Python SDK used to interact with the Fusion Platform(r)
5
5
  Home-page: https://github.com/d-cat-support/fusion-platform-python-sdk
6
6
  Author: Digital Content Analysis Technology Ltd
@@ -19,7 +19,7 @@ PACKAGE_DIR = pathlib.Path(__file__).parent
19
19
  # @formatter:off
20
20
  setup(
21
21
  name='fusion-platform-python-sdk',
22
- version='1.15.11',
22
+ version='1.15.12',
23
23
  description='Python SDK used to interact with the Fusion Platform(r)',
24
24
  long_description=(PACKAGE_DIR / 'README.md').read_text(),
25
25
  long_description_content_type='text/markdown',