fusion-platform-python-sdk 1.16.6__tar.gz → 1.17.6__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.
- {fusion_platform_python_sdk-1.16.6/fusion_platform_python_sdk.egg-info → fusion_platform_python_sdk-1.17.6}/PKG-INFO +3 -3
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/README.md +1 -1
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/__init__.py +2 -2
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/command.py +94 -36
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/fusion_platform_sdk.pdf +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/model.py +3 -1
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process.py +14 -3
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process_service_execution.md +3 -1
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process_service_execution.py +2 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/translations.py +15 -1
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6/fusion_platform_python_sdk.egg-info}/PKG-INFO +3 -3
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/setup.py +2 -2
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_session.py +1 -1
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/LICENSE.txt +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/MANIFEST.in +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/__main__.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/base.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/common/__init__.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/common/raise_thread.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/common/utilities.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/detailed_example.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/documentation.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/glasgow.geojson +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/lake_district.geojson +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/localisations.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/localise.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/__init__.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/credit.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/credit.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/data.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/data.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/data_file.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/data_file.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/fields.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/organisation.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/organisation.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process_execution.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process_execution.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process_service_execution_log.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/process_service_execution_log.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/service.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/service.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/user.md +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/models/user.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/quick_example.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/session.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform_python_sdk.egg-info/SOURCES.txt +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform_python_sdk.egg-info/dependency_links.txt +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform_python_sdk.egg-info/entry_points.txt +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform_python_sdk.egg-info/requires.txt +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform_python_sdk.egg-info/top_level.txt +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/setup.cfg +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_base.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_command.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_init.py +0 -0
- {fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_localise.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: fusion-platform-python-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17.6
|
|
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
|
|
@@ -8,11 +8,11 @@ Author-email: support@d-cat.co.uk
|
|
|
8
8
|
License: MIT
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.9
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
18
|
Requires-Dist: marshmallow
|
|
@@ -48,7 +48,7 @@ API, and this is defined within the corresponding OpenAPI 3.0 specification, whi
|
|
|
48
48
|
|
|
49
49
|
## Installation
|
|
50
50
|
|
|
51
|
-
The SDK has been built for Python 3, and is tested against Python 3.
|
|
51
|
+
The SDK has been built for Python 3, and is tested against Python 3.9, 3.10, 3.11, 3.12 and 3.13. To install the SDK into a suitable Python environment containing
|
|
52
52
|
`pip`, execute the following:
|
|
53
53
|
|
|
54
54
|
```shell
|
|
@@ -12,7 +12,7 @@ API, and this is defined within the corresponding OpenAPI 3.0 specification, whi
|
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
15
|
-
The SDK has been built for Python 3, and is tested against Python 3.
|
|
15
|
+
The SDK has been built for Python 3, and is tested against Python 3.9, 3.10, 3.11, 3.12 and 3.13. To install the SDK into a suitable Python environment containing
|
|
16
16
|
`pip`, execute the following:
|
|
17
17
|
|
|
18
18
|
```shell
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/__init__.py
RENAMED
|
@@ -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
|
-
__version_date__ = '2025-
|
|
14
|
+
__version__ = '1.17.6'
|
|
15
|
+
__version_date__ = '2025-03-26T16:04:58Z'
|
|
16
16
|
|
|
17
17
|
# Exclude certain sub-modules from documentation.
|
|
18
18
|
# @formatter:off
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/command.py
RENAMED
|
@@ -39,7 +39,7 @@ Localise.setup()
|
|
|
39
39
|
|
|
40
40
|
import fusion_platform
|
|
41
41
|
from fusion_platform.base import Base
|
|
42
|
-
from fusion_platform.common.utilities import json_default
|
|
42
|
+
from fusion_platform.common.utilities import json_default, string_blank
|
|
43
43
|
from fusion_platform.models.data import Data
|
|
44
44
|
from fusion_platform.models.model import Model
|
|
45
45
|
from fusion_platform.session import RequestError
|
|
@@ -103,7 +103,9 @@ class Command(Base):
|
|
|
103
103
|
_METRIC_S3_INPUT_SIZE = 'input_size'
|
|
104
104
|
_METRIC_S3_OUTPUT_SIZE = 'output_size'
|
|
105
105
|
_METRIC_S3_TRANSFER_BYTES = 's3_transfer_bytes'
|
|
106
|
+
_METRIC_GCS_TRANSFER_BYTES = 'gcs_transfer_bytes'
|
|
106
107
|
_METRIC_EXTERNAL_TRANSFER_BYTES = 'external_transfer_bytes'
|
|
108
|
+
_METRIC_INTERNAL_TRANSFER_BYTES = 'internal_transfer_bytes'
|
|
107
109
|
|
|
108
110
|
# Process other field constants.
|
|
109
111
|
_MODEL_FIELDS = ['output_storage_period', 'run_type', 'repeat_count', 'repeat_start', 'repeat_end', 'repeat_gap', 'repeat_offset']
|
|
@@ -193,6 +195,7 @@ class Command(Base):
|
|
|
193
195
|
while not finished:
|
|
194
196
|
# Either find the dispatchers from what has been loaded from the YAML file or prompt the user.
|
|
195
197
|
add = False
|
|
198
|
+
dispatch_intermediate = False
|
|
196
199
|
dispatcher_options = {}
|
|
197
200
|
|
|
198
201
|
if dispatchers is not None:
|
|
@@ -204,6 +207,8 @@ class Command(Base):
|
|
|
204
207
|
selected_dispatcher = filtered_dispatchers[0]
|
|
205
208
|
selected_dispatcher[Model._FIELD_USED] = True
|
|
206
209
|
add = True
|
|
210
|
+
dispatch_intermediate = selected_dispatcher.get(Model._FIELD_DISPATCH_INTERMEDIATE) if selected_dispatcher.get(
|
|
211
|
+
Model._FIELD_DISPATCH_INTERMEDIATE) is not None else False
|
|
207
212
|
dispatcher_options = selected_dispatcher.get(Model._FIELD_OPTIONS) if selected_dispatcher.get(Model._FIELD_OPTIONS) is not None else {}
|
|
208
213
|
|
|
209
214
|
else:
|
|
@@ -213,8 +218,29 @@ class Command(Base):
|
|
|
213
218
|
if (response is not None) and response.lower().startswith(i18n.t('command.prompt_yes').lower()[0]):
|
|
214
219
|
add = True
|
|
215
220
|
|
|
221
|
+
if hasattr(dispatcher, Model._FIELD_DISPATCH_INTERMEDIATE):
|
|
222
|
+
response = self.__get_input(i18n.t('command.dispatch_intermediate'),
|
|
223
|
+
constrained_values=[i18n.t('command.prompt_no'), i18n.t('command.prompt_yes')])
|
|
224
|
+
|
|
225
|
+
if (response is not None) and response.lower().startswith(i18n.t('command.prompt_yes').lower()[0]):
|
|
226
|
+
dispatch_intermediate = True
|
|
227
|
+
|
|
216
228
|
for option in dispatcher.options:
|
|
217
|
-
|
|
229
|
+
finished_options = False
|
|
230
|
+
option_value = None
|
|
231
|
+
|
|
232
|
+
while not finished_options:
|
|
233
|
+
constrained_values = option.constrained_values if option.data_type == fusion_platform.DATA_TYPE_CONSTRAINED else None
|
|
234
|
+
|
|
235
|
+
prompt_constrained_values = i18n.t('models.process.option.representation_constrained_values',
|
|
236
|
+
constrained_values=constrained_values) if constrained_values is not None else ''
|
|
237
|
+
prompt_required = i18n.t('models.process.option.representation_required') if option.required else ''
|
|
238
|
+
prompt = i18n.t('command.prompt_option', title=option.title, name=option.name, data_type=option.data_type,
|
|
239
|
+
constrained_values=prompt_constrained_values, required=prompt_required)
|
|
240
|
+
|
|
241
|
+
option_value = self.__get_input(prompt, default=option.value, constrained_values=constrained_values)
|
|
242
|
+
finished_options = (not option.required) or (
|
|
243
|
+
option.required and (option_value is not None) and (not string_blank(str(option_value))))
|
|
218
244
|
|
|
219
245
|
if option_value is not None:
|
|
220
246
|
dispatcher_options[option.name] = option_value
|
|
@@ -224,7 +250,8 @@ class Command(Base):
|
|
|
224
250
|
dispatchers_added += 1
|
|
225
251
|
|
|
226
252
|
for option_name, option_value in dispatcher_options.items():
|
|
227
|
-
process.update(dispatcher_number=dispatchers_added, option_name=option_name, value=option_value
|
|
253
|
+
process.update(dispatcher_number=dispatchers_added, option_name=option_name, value=option_value, coerce_value=True,
|
|
254
|
+
dispatch_intermediate=dispatch_intermediate)
|
|
228
255
|
else:
|
|
229
256
|
finished = True
|
|
230
257
|
|
|
@@ -233,6 +260,18 @@ class Command(Base):
|
|
|
233
260
|
|
|
234
261
|
return process
|
|
235
262
|
|
|
263
|
+
def __data_name_to_file_name(self, data_name):
|
|
264
|
+
"""
|
|
265
|
+
Converts a data item name into a sane file name (without extension).
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
data_name: The data item name to convert.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
The corresponding file name.
|
|
272
|
+
"""
|
|
273
|
+
return re.sub(r"[^A-Za-z_\-]", '_', str(data_name)) if data_name is not None else None
|
|
274
|
+
|
|
236
275
|
def define_process(self, organisation, process_name, download_inputs=False, download_storage=False):
|
|
237
276
|
"""
|
|
238
277
|
Obtains the process definition for a process.
|
|
@@ -254,12 +293,19 @@ class Command(Base):
|
|
|
254
293
|
# Get the underlying service name.
|
|
255
294
|
service, _ = organisation.find_services(ssd_id=process.ssd_id)
|
|
256
295
|
|
|
257
|
-
# Get the options and dispatchers.
|
|
296
|
+
# Get the options and dispatchers, optionally add in whether intermediate services are being dispatched.
|
|
258
297
|
options = {option.name: self.__format_value(option.value, data_type=option.data_type) for option in process.options}
|
|
259
|
-
dispatchers = [
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
298
|
+
dispatchers = []
|
|
299
|
+
|
|
300
|
+
for dispatcher in process.dispatchers:
|
|
301
|
+
found_dispatcher = {Model._FIELD_NAME: dispatcher.name}
|
|
302
|
+
|
|
303
|
+
if hasattr(dispatcher, Model._FIELD_DISPATCH_INTERMEDIATE):
|
|
304
|
+
found_dispatcher[Model._FIELD_DISPATCH_INTERMEDIATE] = dispatcher.dispatch_intermediate
|
|
305
|
+
|
|
306
|
+
found_dispatcher[Model._FIELD_OPTIONS] = {option.name: self.__format_value(option.value, data_type=option.data_type) for option in dispatcher.options}
|
|
307
|
+
|
|
308
|
+
dispatchers.append(found_dispatcher)
|
|
263
309
|
|
|
264
310
|
# Add in the standard options.
|
|
265
311
|
for field in Command._MODEL_FIELDS:
|
|
@@ -418,7 +464,8 @@ class Command(Base):
|
|
|
418
464
|
|
|
419
465
|
return found
|
|
420
466
|
|
|
421
|
-
def __download_execution(self, process, download_inputs, download_outputs, download_storage, download_intermediate, download_components, output_dir,
|
|
467
|
+
def __download_execution(self, process, download_inputs, download_outputs, download_storage, download_intermediate, download_components, output_dir, wait,
|
|
468
|
+
execution):
|
|
422
469
|
"""
|
|
423
470
|
Downloads an execution.
|
|
424
471
|
|
|
@@ -430,6 +477,7 @@ class Command(Base):
|
|
|
430
477
|
download_intermediate: Should intermediate components be downloaded?
|
|
431
478
|
download_components: The names of the components that should be downloaded? If None or [], then all components are downloaded.
|
|
432
479
|
output_dir: The output directory.
|
|
480
|
+
wait: Wait for the execution to complete?
|
|
433
481
|
execution: The execution to be downloaded.
|
|
434
482
|
|
|
435
483
|
Returns:
|
|
@@ -441,10 +489,10 @@ class Command(Base):
|
|
|
441
489
|
metrics = []
|
|
442
490
|
downloads = []
|
|
443
491
|
|
|
444
|
-
#
|
|
492
|
+
# Optionally wait for the execution to complete. We explicitly wait in this method to keep the SDK free.
|
|
445
493
|
complete = False
|
|
446
494
|
|
|
447
|
-
while not complete:
|
|
495
|
+
while wait and (not complete):
|
|
448
496
|
try:
|
|
449
497
|
complete = execution.check_complete()
|
|
450
498
|
except:
|
|
@@ -480,15 +528,20 @@ class Command(Base):
|
|
|
480
528
|
if (started_at is None) or (execution.started_at < started_at):
|
|
481
529
|
started_at = execution.started_at
|
|
482
530
|
|
|
483
|
-
if (
|
|
484
|
-
|
|
531
|
+
execution_ended_at = execution.ended_at if hasattr(execution, Model._FIELD_ENDED_AT) and (execution.ended_at is not None) else datetime.now(timezone.utc)
|
|
532
|
+
|
|
533
|
+
if (ended_at is None) or (execution_ended_at > ended_at):
|
|
534
|
+
ended_at = execution_ended_at
|
|
485
535
|
|
|
486
536
|
for j, component in enumerate(components):
|
|
487
537
|
# Download the component.
|
|
488
538
|
component_name = '_'.join([item for item in re.sub(r'[\W]', '_', component.name).split('_') if len(item) > 0])
|
|
489
539
|
component_dir = f"{str(j + 1)}_{component_name[:25]}"
|
|
490
540
|
component_options = {item.get(Model._FIELD_NAME): item.get(Model._FIELD_VALUE) for item in component.options} if hasattr(component,
|
|
491
|
-
Model._FIELD_OPTIONS)
|
|
541
|
+
Model._FIELD_OPTIONS) and (
|
|
542
|
+
component.options is not None) else {}
|
|
543
|
+
component_success = component.success if hasattr(component, Model._FIELD_SUCCESS) and (component.success is not None) else False
|
|
544
|
+
component_runtime = component.runtime if hasattr(component, Model._FIELD_RUNTIME) and (component.runtime is not None) else 0
|
|
492
545
|
|
|
493
546
|
# Save the metrics for each component in the execution.
|
|
494
547
|
# @formatter:off
|
|
@@ -497,25 +550,22 @@ class Command(Base):
|
|
|
497
550
|
Command._METRICS_PROCESS: process.name,
|
|
498
551
|
Command._METRICS_DURATION: ended_at - started_at if (started_at is not None) and (ended_at is not None) else 0,
|
|
499
552
|
Command._METRICS_COMPONENT: component.name,
|
|
500
|
-
Command._METRICS_SUCCESS:
|
|
553
|
+
Command._METRICS_SUCCESS: component_success,
|
|
501
554
|
Command._METRICS_CPU: component.cpu,
|
|
502
555
|
Command._METRICS_MEMORY: component.memory,
|
|
503
|
-
Command._METRICS_RUNTIME:
|
|
556
|
+
Command._METRICS_RUNTIME: component_runtime
|
|
504
557
|
}
|
|
505
558
|
# @formatter:on
|
|
506
559
|
|
|
507
560
|
# Only D-CAT services have metrics.
|
|
508
|
-
s3_transfer_bytes = 0
|
|
509
|
-
external_transfer_bytes = 0
|
|
510
|
-
|
|
511
561
|
if hasattr(component, Command._METRICS_METRICS) and (component.metrics is not None):
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
562
|
+
for key in [
|
|
563
|
+
Command._METRIC_S3_TRANSFER_BYTES,
|
|
564
|
+
Command._METRIC_GCS_TRANSFER_BYTES,
|
|
565
|
+
Command._METRIC_EXTERNAL_TRANSFER_BYTES,
|
|
566
|
+
Command._METRIC_INTERNAL_TRANSFER_BYTES
|
|
567
|
+
]:
|
|
568
|
+
metric[key] = sum([metric[key] for metric in component.metrics if metric.get(key) is not None])
|
|
519
569
|
|
|
520
570
|
# Find each input, output and storage to download. While traversing each, save the input and output size. The size might not be immediately available
|
|
521
571
|
# for every file, so wait for all items to be analysed.
|
|
@@ -543,7 +593,8 @@ class Command(Base):
|
|
|
543
593
|
# Download the data item once it is complete.
|
|
544
594
|
data_item.check_analysis_complete(wait=True)
|
|
545
595
|
|
|
546
|
-
|
|
596
|
+
name = re.sub('_+', '_', f"{data_type.capitalize()}_{str(k)}_{self.__data_name_to_file_name(data_item.name)}").rstrip('_')
|
|
597
|
+
download_dir = os.path.join(execution_dir, component_dir, name)
|
|
547
598
|
os.makedirs(download_dir, exist_ok=True)
|
|
548
599
|
|
|
549
600
|
# We also create the corresponding STAC definitions.
|
|
@@ -574,8 +625,8 @@ class Command(Base):
|
|
|
574
625
|
with open(os.path.join(download_dir, stac_file_name), 'w') as stac_file:
|
|
575
626
|
stac_file.write(json.dumps(stac_definition, default=json_default))
|
|
576
627
|
|
|
577
|
-
metric[Command._METRIC_S3_INPUT_SIZE] = sum(input_sizes)
|
|
578
|
-
metric[Command._METRIC_S3_OUTPUT_SIZE] = sum(output_sizes)
|
|
628
|
+
metric[Command._METRIC_S3_INPUT_SIZE] = sum(input_sizes) if len(input_sizes) > 0 else ''
|
|
629
|
+
metric[Command._METRIC_S3_OUTPUT_SIZE] = sum(output_sizes) if len(output_sizes) > 0 else ''
|
|
579
630
|
metrics.append(metric)
|
|
580
631
|
|
|
581
632
|
return downloads, metrics
|
|
@@ -649,7 +700,7 @@ class Command(Base):
|
|
|
649
700
|
progress_bar.close()
|
|
650
701
|
|
|
651
702
|
def download_process_execution(self, organisation, process_name, download_inputs, download_outputs, download_storage, download_intermediate,
|
|
652
|
-
download_components, save_metrics):
|
|
703
|
+
download_components, save_metrics, wait_for_execution_to_complete):
|
|
653
704
|
"""
|
|
654
705
|
Downloads the inputs and/or outputs from a process or execution(s).
|
|
655
706
|
|
|
@@ -662,6 +713,7 @@ class Command(Base):
|
|
|
662
713
|
download_intermediate: Should intermediate components be downloaded?
|
|
663
714
|
download_components: The names of the components that should be downloaded? If None or [], then all components are downloaded.
|
|
664
715
|
save_metrics: Save process metrics to file?
|
|
716
|
+
wait_for_execution_to_complete: Optionally wait for completion of the execution?
|
|
665
717
|
|
|
666
718
|
Returns:
|
|
667
719
|
The process model.
|
|
@@ -707,7 +759,8 @@ class Command(Base):
|
|
|
707
759
|
|
|
708
760
|
# Do all the downloads in batches. We use small batches so that we do not swamp memory.
|
|
709
761
|
batch_size = 2 * os.cpu_count() # Downloads don't swamp CPU.
|
|
710
|
-
|
|
762
|
+
wait = i18n.t('command.wait_for_completion') if wait_for_execution_to_complete else ''
|
|
763
|
+
self.__print(logging.INFO, i18n.t('command.download_executions', wait=wait, executions=len(executions)))
|
|
711
764
|
progress_bar = tqdm(total=len(executions), bar_format=Command.__PROGRESS_BAR_FORMAT, colour=Command.__PROGRESS_BAR_COLOUR_ACTIVE,
|
|
712
765
|
unit='execution') # Unit matches keyword argument.
|
|
713
766
|
progress_bar.set_postfix(execution=1)
|
|
@@ -715,7 +768,7 @@ class Command(Base):
|
|
|
715
768
|
try:
|
|
716
769
|
# Now download each execution in batches.
|
|
717
770
|
partial_download_execution = partial(self.__download_execution, process, download_inputs, download_outputs, download_storage, download_intermediate,
|
|
718
|
-
download_components, output_dir)
|
|
771
|
+
download_components, output_dir, wait_for_execution_to_complete)
|
|
719
772
|
results = []
|
|
720
773
|
|
|
721
774
|
with Pool(nodes=batch_size) as pool:
|
|
@@ -855,7 +908,7 @@ class Command(Base):
|
|
|
855
908
|
The user response.
|
|
856
909
|
"""
|
|
857
910
|
default = constrained_values[0] if (default is None) and (constrained_values is not None) and (len(constrained_values) > 0) else default
|
|
858
|
-
input_prompt = f"{input_prompt}{' [' + default + ']' if default is not None else ''}: "
|
|
911
|
+
input_prompt = f"{input_prompt}{' [' + str(default) + ']' if default is not None else ''}: "
|
|
859
912
|
constrained_values = [''] + constrained_values if constrained_values is not None else constrained_values
|
|
860
913
|
|
|
861
914
|
# Set up any validation against constrained values.
|
|
@@ -1089,7 +1142,8 @@ class Command(Base):
|
|
|
1089
1142
|
# Also perform the download, if required.
|
|
1090
1143
|
if arguments.download:
|
|
1091
1144
|
process = self.download_process_execution(organisation, process_name, arguments.inputs, arguments.outputs, arguments.storage,
|
|
1092
|
-
arguments.intermediate, arguments.component, arguments.metrics
|
|
1145
|
+
arguments.intermediate, arguments.component, arguments.metrics,
|
|
1146
|
+
not arguments.no_wait_for_completion)
|
|
1093
1147
|
|
|
1094
1148
|
# And optionally remove the process and its inputs.
|
|
1095
1149
|
if arguments.remove:
|
|
@@ -1112,7 +1166,7 @@ class Command(Base):
|
|
|
1112
1166
|
for process_name in arguments.process:
|
|
1113
1167
|
# Download the process.
|
|
1114
1168
|
process = self.download_process_execution(organisation, process_name, arguments.inputs, arguments.outputs, arguments.storage,
|
|
1115
|
-
arguments.intermediate, arguments.component, arguments.metrics)
|
|
1169
|
+
arguments.intermediate, arguments.component, arguments.metrics, not arguments.no_wait_for_completion)
|
|
1116
1170
|
|
|
1117
1171
|
# And optionally remove the process and its inputs.
|
|
1118
1172
|
if arguments.remove:
|
|
@@ -1189,6 +1243,8 @@ class Command(Base):
|
|
|
1189
1243
|
default=False, action="store_true")
|
|
1190
1244
|
parser_start.add_argument(i18n.t('command.start.component_short'), i18n.t('command.start.component_long'), help=i18n.t('command.start.component_help'),
|
|
1191
1245
|
nargs='*')
|
|
1246
|
+
parser_start.add_argument(i18n.t('command.start.no_wait_for_completion_short'), i18n.t('command.start.no_wait_for_completion_long'),
|
|
1247
|
+
help=i18n.t('command.start.no_wait_for_completion_help'), default=False, action="store_true")
|
|
1192
1248
|
|
|
1193
1249
|
# Define arguments.
|
|
1194
1250
|
parser_define.add_argument(i18n.t('command.define.process_long'), help=i18n.t('command.define.process_help'), nargs='+')
|
|
@@ -1213,6 +1269,8 @@ class Command(Base):
|
|
|
1213
1269
|
default=False, action="store_true")
|
|
1214
1270
|
parser_download.add_argument(i18n.t('command.start.component_short'), i18n.t('command.start.component_long'), help=i18n.t('command.start.component_help'),
|
|
1215
1271
|
nargs='*')
|
|
1272
|
+
parser_download.add_argument(i18n.t('command.start.no_wait_for_completion_short'), i18n.t('command.start.no_wait_for_completion_long'),
|
|
1273
|
+
help=i18n.t('command.start.no_wait_for_completion_help'), default=False, action="store_true")
|
|
1216
1274
|
|
|
1217
1275
|
return parser.parse_args()
|
|
1218
1276
|
|
|
@@ -1378,7 +1436,7 @@ class Command(Base):
|
|
|
1378
1436
|
|
|
1379
1437
|
def __process_name_to_file_name(self, process_name):
|
|
1380
1438
|
"""
|
|
1381
|
-
Converts a process name into a
|
|
1439
|
+
Converts a process name into a sane file name (without extension).
|
|
1382
1440
|
|
|
1383
1441
|
Args:
|
|
1384
1442
|
process_name: The process name to convert.
|
|
Binary file
|
|
@@ -92,6 +92,7 @@ class Model(Base):
|
|
|
92
92
|
_FIELD_OUTPUTS = 'outputs'
|
|
93
93
|
_FIELD_PROCESS_STATUS = 'process_status'
|
|
94
94
|
_FIELD_RESOLUTION = 'resolution'
|
|
95
|
+
_FIELD_RUNTIME = 'runtime'
|
|
95
96
|
_FIELD_SD = 'sd'
|
|
96
97
|
_FIELD_SELECTOR = 'selector'
|
|
97
98
|
_FIELD_SELECTORS = 'selectors'
|
|
@@ -99,6 +100,7 @@ class Model(Base):
|
|
|
99
100
|
_FIELD_STAC_ITEM = 'stac_item'
|
|
100
101
|
_FIELD_STAC_ITEM_FILE = 'stac_item_file'
|
|
101
102
|
_FIELD_STARTED_AT = 'started_at'
|
|
103
|
+
_FIELD_SUCCESS = 'success'
|
|
102
104
|
_FIELD_PUBLISHABLE = 'publishable'
|
|
103
105
|
_FIELD_SIZE = 'size'
|
|
104
106
|
_FIELD_UNIT = 'unit'
|
|
@@ -770,7 +772,7 @@ class Model(Base):
|
|
|
770
772
|
Returns:
|
|
771
773
|
A string representation of the object.
|
|
772
774
|
"""
|
|
773
|
-
return
|
|
775
|
+
return i18n.t('models.model.representation', name=self.__class__.__name__, attributes=self.attributes)
|
|
774
776
|
|
|
775
777
|
def to_csv(self, exclude=None):
|
|
776
778
|
"""
|
|
@@ -228,7 +228,12 @@ class Option(Model):
|
|
|
228
228
|
Returns:
|
|
229
229
|
A string representation of the object.
|
|
230
230
|
"""
|
|
231
|
-
|
|
231
|
+
constrained_values = i18n.t('models.process.option.representation_constrained_values',
|
|
232
|
+
constrained_values=self.constrained_values) if self.data_type == fusion_platform.DATA_TYPE_CONSTRAINED else ''
|
|
233
|
+
required = i18n.t('models.process.option.representation_required') if self.required else ''
|
|
234
|
+
|
|
235
|
+
return i18n.t('models.process.option.representation', title=self.title, name=self.name, data_type=self.data_type, constrained_values=constrained_values,
|
|
236
|
+
required=required, value=self.value, description=self.description)
|
|
232
237
|
|
|
233
238
|
|
|
234
239
|
# Define a model class for an input which overrides the representation to display more relevant information.
|
|
@@ -243,7 +248,10 @@ class Input(Model):
|
|
|
243
248
|
Returns:
|
|
244
249
|
A string representation of the object.
|
|
245
250
|
"""
|
|
246
|
-
|
|
251
|
+
name = i18n.t('models.process.input.representation_name', name=self.name) if hasattr(self, self.__class__._FIELD_NAME) else ''
|
|
252
|
+
id = i18n.t('models.process.input.representation_id', id=self.id) if hasattr(self, self.__class__._FIELD_ID) else ''
|
|
253
|
+
|
|
254
|
+
return i18n.t('models.process.input.representation', title=self.title, file_type=self.file_type, name=name, id=id, description=self.description)
|
|
247
255
|
|
|
248
256
|
|
|
249
257
|
# Define a model class for a dispatcher which overrides the representation to display more relevant information.
|
|
@@ -268,7 +276,10 @@ class Dispatcher(Model):
|
|
|
268
276
|
Returns:
|
|
269
277
|
A string representation of the object.
|
|
270
278
|
"""
|
|
271
|
-
|
|
279
|
+
dispatch_intermediate = self.dispatch_intermediate if hasattr(self, self.__class__._FIELD_DISPATCH_INTERMEDIATE) else False
|
|
280
|
+
|
|
281
|
+
return i18n.t('models.process.dispatcher.representation', name=self.name, ssd_id=self.ssd_id, dispatch_intermediate=dispatch_intermediate,
|
|
282
|
+
documentation_summary=self.documentation_summary)
|
|
272
283
|
|
|
273
284
|
|
|
274
285
|
# Define the model schema classes. These are maintained from the API definitions.
|
|
@@ -51,5 +51,7 @@
|
|
|
51
51
|
* **tmp_total_bytes**: The total temporary disk space in bytes.
|
|
52
52
|
* **tmp_free_bytes**: The free temporary disk space in bytes.
|
|
53
53
|
* **s3_transfer_bytes**: The number of bytes transferred in from S3.
|
|
54
|
-
* **
|
|
54
|
+
* **gcs_transfer_bytes**: The number of bytes transferred in from Google Cloud Storage.
|
|
55
|
+
* **external_transfer_bytes**: The number of bytes transferred in externally.
|
|
56
|
+
* **internal_transfer_bytes**: The number of bytes transferred in internally.
|
|
55
57
|
* **comment**: Any comment recorded with the metric.
|
|
@@ -93,7 +93,9 @@ class ProcessServiceExecutionMetricSchema(Schema):
|
|
|
93
93
|
tmp_total_bytes = fields.Integer(allow_none=True)
|
|
94
94
|
tmp_free_bytes = fields.Integer(allow_none=True)
|
|
95
95
|
s3_transfer_bytes = fields.Integer(allow_none=True)
|
|
96
|
+
gcs_transfer_bytes = fields.Integer(allow_none=True)
|
|
96
97
|
external_transfer_bytes = fields.Integer(allow_none=True)
|
|
98
|
+
internal_transfer_bytes = fields.Integer(allow_none=True)
|
|
97
99
|
comment = fields.String(allow_none=True)
|
|
98
100
|
|
|
99
101
|
class Meta:
|
|
@@ -46,6 +46,7 @@ i18n.add_translation('command.log_field', '%{field}: %{value}', 'en')
|
|
|
46
46
|
i18n.add_translation('command.log_subdivider', '................................................................................................', 'en')
|
|
47
47
|
i18n.add_translation('command.log_divider', '------------------------------------------------------------------------------------------------', 'en')
|
|
48
48
|
i18n.add_translation('command.log_bookend', '************************************************************************************************', 'en')
|
|
49
|
+
i18n.add_translation('command.wait_for_completion', ' and waiting for completion', 'en')
|
|
49
50
|
i18n.add_translation('command.wait_for_next', 'Waiting for next execution...', 'en')
|
|
50
51
|
i18n.add_translation('command.using_storage', 'Uploading storage \'%{filename}\' with id %{storage_id} to \'%{storage_name}\'', 'en')
|
|
51
52
|
i18n.add_translation('command.using_service', 'Using service \'%{service}\'', 'en')
|
|
@@ -58,6 +59,7 @@ i18n.add_translation('command.remove_process', 'Removing input \'%{process}\'',
|
|
|
58
59
|
i18n.add_translation('command.remove_input', 'Removing input \'%{input}\'', 'en')
|
|
59
60
|
i18n.add_translation('command.prompt_yes', 'Yes', 'en')
|
|
60
61
|
i18n.add_translation('command.prompt_no', 'No', 'en')
|
|
62
|
+
i18n.add_translation('command.prompt_option', '%{title} (\'%{name}\', %{data_type}%{constrained_values}%{required})', 'en')
|
|
61
63
|
i18n.add_translation('command.password', 'Password', 'en')
|
|
62
64
|
i18n.add_translation('command.organisation', 'Organisation', 'en')
|
|
63
65
|
i18n.add_translation('command.find_inputs', 'Finding %{inputs} input file(s)...', 'en')
|
|
@@ -66,11 +68,12 @@ i18n.add_translation('command.email', 'Email', 'en')
|
|
|
66
68
|
i18n.add_translation('command.download_process_execution', 'Downloading \'%{process}\' (inputs %{inputs}, outputs %{outputs}, storage %{storage}, intermediate %{intermediate}, metrics %{metrics}, components %{components})', 'en')
|
|
67
69
|
i18n.add_translation('command.download_process', 'Downloading process \'%{process}\' to %{output}', 'en')
|
|
68
70
|
i18n.add_translation('command.download_files', 'Downloading %{files} file(s)...', 'en')
|
|
69
|
-
i18n.add_translation('command.download_executions', 'Gathering files for %{executions} execution(s)...', 'en')
|
|
71
|
+
i18n.add_translation('command.download_executions', 'Gathering files%{wait} for %{executions} execution(s)...', 'en')
|
|
70
72
|
i18n.add_translation('command.download_execution', 'Downloading execution %{execution} to %{output}', 'en')
|
|
71
73
|
i18n.add_translation('command.define_storage', 'Defining storage file(s) for %{slices} slice(s)...', 'en')
|
|
72
74
|
i18n.add_translation('command.define_process', 'Defining \'%{process}\' (inputs %{inputs}, storage %{storage})', 'en')
|
|
73
75
|
i18n.add_translation('command.define_inputs', 'Defining %{files} input file(s)...', 'en')
|
|
76
|
+
i18n.add_translation('command.dispatch_intermediate', 'Dispatch intermediate components?', 'en')
|
|
74
77
|
i18n.add_translation('command.add_dispatcher', 'Add %{dispatcher} dispatcher?', 'en')
|
|
75
78
|
i18n.add_translation('command.download.process_help', 'the name of the process, the process id or execution id to download', 'en')
|
|
76
79
|
i18n.add_translation('command.download.process_long', 'process', 'en')
|
|
@@ -80,6 +83,9 @@ i18n.add_translation('command.define.process_help', 'the name of the process, th
|
|
|
80
83
|
i18n.add_translation('command.define.process_long', 'process', 'en')
|
|
81
84
|
i18n.add_translation('command.define.help', 'outputs a YAML file for each existing process', 'en')
|
|
82
85
|
i18n.add_translation('command.define.command', 'define', 'en')
|
|
86
|
+
i18n.add_translation('command.start.no_wait_for_completion_help', 'do not wait for the execution to complete (default %%(default)s)\'', 'en')
|
|
87
|
+
i18n.add_translation('command.start.no_wait_for_completion_long', '--no_wait_for_completion', 'en')
|
|
88
|
+
i18n.add_translation('command.start.no_wait_for_completion_short', '-n', 'en')
|
|
83
89
|
i18n.add_translation('command.start.metrics_help', 'save process metrics to file (default %%(default)s)', 'en')
|
|
84
90
|
i18n.add_translation('command.start.metrics_long', '--metrics', 'en')
|
|
85
91
|
i18n.add_translation('command.start.metrics_short', '-t', 'en')
|
|
@@ -280,6 +286,7 @@ i18n.add_translation('models.model.no_such_keys', 'No such keys %{keys}', 'en')
|
|
|
280
286
|
i18n.add_translation('models.model.readonly_property', 'Property %{property} is read-only and cannot be set', 'en')
|
|
281
287
|
i18n.add_translation('models.model.not_persisted', 'Model is not persisted in the Fusion Platform(r)', 'en')
|
|
282
288
|
i18n.add_translation('models.model.already_persisted', 'Model is already persisted in the Fusion Platform(r)', 'en')
|
|
289
|
+
i18n.add_translation('models.model.representation', '%{name}%{attributes}', 'en')
|
|
283
290
|
i18n.add_translation('models.process.failed_copy', 'Failed to get process from copy response', 'en')
|
|
284
291
|
i18n.add_translation('models.process.execution_should_have_started', 'Process execution should have started by now', 'en')
|
|
285
292
|
i18n.add_translation('models.process.execution_stopped', 'Process execution has been stopped', 'en')
|
|
@@ -298,4 +305,11 @@ i18n.add_translation('models.process.option.constrained_values.description', 'Th
|
|
|
298
305
|
i18n.add_translation('models.process.option.constrained_values.title', 'Constrained Values', 'en')
|
|
299
306
|
i18n.add_translation('models.process.option.constrained_names.description', 'The constrained value names for the option.', 'en')
|
|
300
307
|
i18n.add_translation('models.process.option.constrained_names.title', 'Constrained Names', 'en')
|
|
308
|
+
i18n.add_translation('models.process.option.representation_required', ', required', 'en')
|
|
309
|
+
i18n.add_translation('models.process.option.representation_constrained_values', ' %{constrained_values}', 'en')
|
|
310
|
+
i18n.add_translation('models.process.option.representation', '%{title} (\'%{name}\', %{data_type}%{constrained_values}%{required}) = %{value}: %{description}', 'en')
|
|
311
|
+
i18n.add_translation('models.process.input.representation_id', ' (%{id})', 'en')
|
|
312
|
+
i18n.add_translation('models.process.input.representation_name', ' %{name}', 'en')
|
|
313
|
+
i18n.add_translation('models.process.input.representation', '%{title} (%{file_type}) =%{name}%{id}: %{description}', 'en')
|
|
314
|
+
i18n.add_translation('models.process.dispatcher.representation', '%{name} (%{ssd_id}, intermediate %{dispatch_intermediate}): %{documentation_summary}', 'en')
|
|
301
315
|
# @formatter:on
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: fusion-platform-python-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.17.6
|
|
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
|
|
@@ -8,11 +8,11 @@ Author-email: support@d-cat.co.uk
|
|
|
8
8
|
License: MIT
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.9
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
18
|
Requires-Dist: marshmallow
|
|
@@ -48,7 +48,7 @@ API, and this is defined within the corresponding OpenAPI 3.0 specification, whi
|
|
|
48
48
|
|
|
49
49
|
## Installation
|
|
50
50
|
|
|
51
|
-
The SDK has been built for Python 3, and is tested against Python 3.
|
|
51
|
+
The SDK has been built for Python 3, and is tested against Python 3.9, 3.10, 3.11, 3.12 and 3.13. To install the SDK into a suitable Python environment containing
|
|
52
52
|
`pip`, execute the following:
|
|
53
53
|
|
|
54
54
|
```shell
|
|
@@ -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.
|
|
22
|
+
version='1.17.6',
|
|
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',
|
|
@@ -30,11 +30,11 @@ setup(
|
|
|
30
30
|
classifiers=[
|
|
31
31
|
'License :: OSI Approved :: MIT License',
|
|
32
32
|
'Programming Language :: Python :: 3',
|
|
33
|
-
'Programming Language :: Python :: 3.8',
|
|
34
33
|
'Programming Language :: Python :: 3.9',
|
|
35
34
|
'Programming Language :: Python :: 3.10',
|
|
36
35
|
'Programming Language :: Python :: 3.11',
|
|
37
36
|
'Programming Language :: Python :: 3.12',
|
|
37
|
+
'Programming Language :: Python :: 3.13',
|
|
38
38
|
],
|
|
39
39
|
packages=find_packages(exclude='tests'),
|
|
40
40
|
include_package_data=True,
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_session.py
RENAMED
|
@@ -66,7 +66,7 @@ class TestSession(CustomTestCase):
|
|
|
66
66
|
session = Session()
|
|
67
67
|
|
|
68
68
|
with pytest.raises(RequestError):
|
|
69
|
-
session.download_file('https://www.d-cat.co.uk
|
|
69
|
+
session.download_file('https://www.d-cat.co.uk/assets/test.html', destination)
|
|
70
70
|
|
|
71
71
|
self.assertFalse(os.path.exists(destination))
|
|
72
72
|
session.download_file('https://www.d-cat.co.uk/home', destination, self.download_callback)
|
|
File without changes
|
|
File without changes
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/__main__.py
RENAMED
|
File without changes
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/localise.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/fusion_platform/session.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{fusion_platform_python_sdk-1.16.6 → fusion_platform_python_sdk-1.17.6}/tests/test_localise.py
RENAMED
|
File without changes
|