pinexq-client 1.1.0__py3-none-any.whl → 1.2.1__py3-none-any.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.
- pinexq/client/job_management/__init__.py +2 -2
- pinexq/client/job_management/model/open_api_generated.py +4 -2
- pinexq/client/job_management/tool/__init__.py +3 -3
- pinexq/client/job_management/tool/job.py +156 -15
- pinexq/client/job_management/tool/processing_step.py +143 -2
- pinexq/client/job_management/tool/workdata.py +151 -4
- {pinexq_client-1.1.0.dist-info → pinexq_client-1.2.1.dist-info}/METADATA +1 -1
- {pinexq_client-1.1.0.dist-info → pinexq_client-1.2.1.dist-info}/RECORD +9 -9
- {pinexq_client-1.1.0.dist-info → pinexq_client-1.2.1.dist-info}/WHEEL +1 -1
|
@@ -19,7 +19,7 @@ from .hcos import (
|
|
|
19
19
|
)
|
|
20
20
|
from .known_relations import Relations
|
|
21
21
|
from .model import JobSortPropertiesSortParameter, ProcessingView
|
|
22
|
-
from .tool import Job, JobGroup, ProcessingStep, WorkData
|
|
22
|
+
from .tool import Job, JobGroup, JobQuery, ProcessingStep, ProcessingStepQuery, WorkData, WorkDataQuery
|
|
23
23
|
|
|
24
24
|
# Protocol version the JMA is using
|
|
25
|
-
__jma_version__ = [9,
|
|
25
|
+
__jma_version__ = [9, 3, 0]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# generated by datamodel-codegen:
|
|
2
2
|
# filename: openapi.json
|
|
3
|
-
# timestamp: 2026-
|
|
3
|
+
# timestamp: 2026-02-03T21:15:10+00:00
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
@@ -119,6 +119,8 @@ class DeploymentResourcePresets(StrEnum):
|
|
|
119
119
|
medium = 'Medium'
|
|
120
120
|
large = 'Large'
|
|
121
121
|
x_large = 'XLarge'
|
|
122
|
+
xx_large = 'XXLarge'
|
|
123
|
+
x_small = 'XSmall'
|
|
122
124
|
|
|
123
125
|
|
|
124
126
|
class DeploymentStates(StrEnum):
|
|
@@ -1184,7 +1186,7 @@ class ProcessingStepHtoOpenApiProperties(BaseModel):
|
|
|
1184
1186
|
code_hash: str | None = Field(
|
|
1185
1187
|
None,
|
|
1186
1188
|
alias='CodeHash',
|
|
1187
|
-
description='The hash of the code executing this function. This is intended to inhibit\
|
|
1189
|
+
description='The hash of the code executing this function. This is intended to inhibit\nredeployment of different code for the same function version.',
|
|
1188
1190
|
)
|
|
1189
1191
|
has_parameters: bool | None = Field(None, alias='HasParameters')
|
|
1190
1192
|
is_public: bool | None = Field(None, alias='IsPublic')
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .job import Job
|
|
1
|
+
from .job import Job, JobQuery
|
|
2
2
|
from .job_group import JobGroup
|
|
3
|
-
from .processing_step import ProcessingStep
|
|
4
|
-
from .workdata import WorkData
|
|
3
|
+
from .processing_step import ProcessingStep, ProcessingStepQuery
|
|
4
|
+
from .workdata import WorkData, WorkDataQuery
|
|
@@ -3,14 +3,15 @@ import json as json_
|
|
|
3
3
|
import queue
|
|
4
4
|
import warnings
|
|
5
5
|
from datetime import datetime, timedelta
|
|
6
|
-
from typing import Any, List, Self
|
|
6
|
+
from typing import Any, Iterator, List, Self
|
|
7
7
|
|
|
8
8
|
import httpx
|
|
9
9
|
from httpx import URL
|
|
10
|
-
from pydantic import BaseModel, ConfigDict
|
|
10
|
+
from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict
|
|
11
11
|
|
|
12
12
|
from ...core import ApiException, ClientException, Link, MediaTypes
|
|
13
13
|
from ...core.api_event_manager import ApiEventManagerSingleton
|
|
14
|
+
from ...core.hco.unavailable import UnavailableLink
|
|
14
15
|
from ...core.polling import PollingException, wait_until
|
|
15
16
|
from ..enterjma import enter_jma
|
|
16
17
|
from ..hcos import InputDataSlotHco, OutputDataSlotHco, ProcessingStepLink, WorkDataLink
|
|
@@ -27,8 +28,10 @@ from ..model import (
|
|
|
27
28
|
InputDataSlotParameter,
|
|
28
29
|
JobFilterParameter,
|
|
29
30
|
JobQueryParameters,
|
|
31
|
+
JobSortProperties,
|
|
30
32
|
JobSortPropertiesSortParameter,
|
|
31
33
|
JobStates,
|
|
34
|
+
Pagination,
|
|
32
35
|
ProcessingStepFilterParameter,
|
|
33
36
|
ProcessingStepQueryParameters,
|
|
34
37
|
ProcessingView,
|
|
@@ -37,6 +40,7 @@ from ..model import (
|
|
|
37
40
|
SelectWorkDataCollectionForDataSlotParameters,
|
|
38
41
|
SelectWorkDataForDataSlotParameters,
|
|
39
42
|
SetJobTagsParameters,
|
|
43
|
+
SortTypes,
|
|
40
44
|
)
|
|
41
45
|
from ..tool.processing_step import ProcessingStep
|
|
42
46
|
from ..tool.workdata import WorkData
|
|
@@ -53,10 +57,10 @@ class InputDataSlotParameterFlexible(BaseModel):
|
|
|
53
57
|
|
|
54
58
|
@classmethod
|
|
55
59
|
def create(cls, *,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
index: int,
|
|
61
|
+
work_data_urls: List[WorkDataLink] | None = None,
|
|
62
|
+
work_data_instances: List[WorkData] | None = None
|
|
63
|
+
) -> "InputDataSlotParameterFlexible":
|
|
60
64
|
"""Creates an instance of InputDataSlotParameterFlexible that can be used to assign work data to a job.
|
|
61
65
|
|
|
62
66
|
Args:
|
|
@@ -81,6 +85,7 @@ class InputDataSlotParameterFlexible(BaseModel):
|
|
|
81
85
|
work_data_instances=None
|
|
82
86
|
)
|
|
83
87
|
|
|
88
|
+
|
|
84
89
|
class Job:
|
|
85
90
|
"""Convenience wrapper for handling JobHcos in the JobManagement-Api.
|
|
86
91
|
|
|
@@ -322,7 +327,8 @@ class Job:
|
|
|
322
327
|
result = self.job_hco.result
|
|
323
328
|
return json_.loads(result) if result else None
|
|
324
329
|
|
|
325
|
-
def wait_for_state_sse(self, state: JobStates, timeout_s: float | None = None,
|
|
330
|
+
def wait_for_state_sse(self, state: JobStates, timeout_s: float | None = None,
|
|
331
|
+
fallback_polling_interval_s: float = 300) -> Self:
|
|
326
332
|
self._raise_if_no_hco()
|
|
327
333
|
|
|
328
334
|
# early exit
|
|
@@ -391,10 +397,10 @@ class Job:
|
|
|
391
397
|
try:
|
|
392
398
|
wait_until(
|
|
393
399
|
condition=lambda: self.get_state() == state,
|
|
394
|
-
timeout_ms=
|
|
400
|
+
timeout_ms=int(timeout_s * 1000) if timeout_s is not None else None,
|
|
395
401
|
timeout_message="Waiting for job completion",
|
|
396
402
|
error_condition=lambda: self.job_hco.state == JobStates.error,
|
|
397
|
-
polling_interval_ms=
|
|
403
|
+
polling_interval_ms=int(polling_interval_s * 1000)
|
|
398
404
|
)
|
|
399
405
|
except TimeoutError as timeout:
|
|
400
406
|
raise TimeoutError(
|
|
@@ -578,15 +584,15 @@ class Job:
|
|
|
578
584
|
"""
|
|
579
585
|
wait_until(
|
|
580
586
|
condition=lambda: self.sub_jobs_in_state(JobStates.pending) == 0,
|
|
581
|
-
timeout_ms=
|
|
587
|
+
timeout_ms=int(timeout_s * 1000),
|
|
582
588
|
timeout_message=f"Timeout while waiting for sub-jobs to complete! [timeout: {timeout_s}s]",
|
|
583
|
-
polling_interval_ms=
|
|
589
|
+
polling_interval_ms=int(polling_interval_s * 1000)
|
|
584
590
|
)
|
|
585
591
|
wait_until(
|
|
586
592
|
condition=lambda: self.sub_jobs_in_state(JobStates.processing) == 0,
|
|
587
|
-
timeout_ms=
|
|
593
|
+
timeout_ms=int(timeout_s * 1000),
|
|
588
594
|
timeout_message=f"Timeout while waiting for sub-jobs to complete! [timeout: {timeout_s}ms]",
|
|
589
|
-
polling_interval_ms=
|
|
595
|
+
polling_interval_ms=int(polling_interval_s * 1000)
|
|
590
596
|
)
|
|
591
597
|
|
|
592
598
|
error_count = self.sub_jobs_in_state(JobStates.error)
|
|
@@ -639,7 +645,7 @@ class Job:
|
|
|
639
645
|
delete_output_workdata=delete_output_workdata,
|
|
640
646
|
delete_input_workdata=delete_input_workdata,
|
|
641
647
|
delete_subjobs_with_data=delete_subjobs_with_data,
|
|
642
|
-
recursion_depth
|
|
648
|
+
recursion_depth=0)
|
|
643
649
|
|
|
644
650
|
def _delete_with_associated_internal(
|
|
645
651
|
self,
|
|
@@ -664,7 +670,7 @@ class Job:
|
|
|
664
670
|
delete_output_workdata=delete_output_workdata,
|
|
665
671
|
delete_input_workdata=delete_input_workdata,
|
|
666
672
|
delete_subjobs_with_data=delete_subjobs_with_data,
|
|
667
|
-
recursion_depth
|
|
673
|
+
recursion_depth=recursion_depth + 1)
|
|
668
674
|
if subjob.self_link.exists():
|
|
669
675
|
warnings.warn(f"Could not delete subjob: {subjob.self_link.get_url()}")
|
|
670
676
|
except (ClientException, ApiException) as e:
|
|
@@ -887,3 +893,138 @@ class Job:
|
|
|
887
893
|
def _raise_if_no_hco(self):
|
|
888
894
|
if self.job_hco is None:
|
|
889
895
|
raise Exception("No job hco present. Maybe this class is used after resource deletion.")
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
class JobQuery:
|
|
899
|
+
"""Convenience wrapper for querying Jobs.
|
|
900
|
+
"""
|
|
901
|
+
|
|
902
|
+
_client: httpx.Client
|
|
903
|
+
_entrypoint: EntryPointHco
|
|
904
|
+
_jobs_root: JobsRootHco
|
|
905
|
+
parameters: JobQueryParameters
|
|
906
|
+
|
|
907
|
+
def __init__(self, client: httpx.Client, parameters: JobQueryParameters):
|
|
908
|
+
self._client = client
|
|
909
|
+
self._entrypoint = enter_jma(client)
|
|
910
|
+
self._jobs_root = self._entrypoint.job_root_link.navigate()
|
|
911
|
+
self.parameters = parameters
|
|
912
|
+
|
|
913
|
+
@classmethod
|
|
914
|
+
def from_parameters(cls, client: httpx.Client, parameters: JobQueryParameters) -> Self:
|
|
915
|
+
"""Create a JobQuery from a JobQueryParameters object.
|
|
916
|
+
"""
|
|
917
|
+
return cls(client, parameters)
|
|
918
|
+
|
|
919
|
+
@classmethod
|
|
920
|
+
def create(
|
|
921
|
+
cls,
|
|
922
|
+
client: httpx.Client,
|
|
923
|
+
*,
|
|
924
|
+
page_size: int | None = None,
|
|
925
|
+
page_offset: int | None = None,
|
|
926
|
+
sort_by_property_name: JobSortProperties | None = None,
|
|
927
|
+
sort_by_sort_type: SortTypes | None = None,
|
|
928
|
+
include_remaining_tags: bool | None = None,
|
|
929
|
+
state: JobStates | None = None,
|
|
930
|
+
name: str | None = None,
|
|
931
|
+
show_hidden: bool | None = None,
|
|
932
|
+
work_data_url: AnyUrl | None = None,
|
|
933
|
+
created_before: AwareDatetime | None = None,
|
|
934
|
+
created_after: AwareDatetime | None = None,
|
|
935
|
+
tags_by_and: list[str] | None = None,
|
|
936
|
+
tags_by_or: list[str] | None = None,
|
|
937
|
+
processing_step_url: AnyUrl | None = None,
|
|
938
|
+
is_sub_job: bool | None = None,
|
|
939
|
+
parent_job_url: AnyUrl | None = None
|
|
940
|
+
) -> Self:
|
|
941
|
+
"""Create a JobQuery from flat parameters.
|
|
942
|
+
"""
|
|
943
|
+
filter_param = JobFilterParameter(
|
|
944
|
+
state=state,
|
|
945
|
+
name=name,
|
|
946
|
+
show_hidden=show_hidden,
|
|
947
|
+
work_data_url=work_data_url,
|
|
948
|
+
created_before=created_before,
|
|
949
|
+
created_after=created_after,
|
|
950
|
+
tags_by_and=tags_by_and,
|
|
951
|
+
tags_by_or=tags_by_or,
|
|
952
|
+
processing_step_url=processing_step_url,
|
|
953
|
+
is_sub_job=is_sub_job,
|
|
954
|
+
parent_job_url=parent_job_url
|
|
955
|
+
)
|
|
956
|
+
|
|
957
|
+
sort_by = None
|
|
958
|
+
if sort_by_property_name is not None or sort_by_sort_type is not None:
|
|
959
|
+
sort_by = JobSortPropertiesSortParameter(
|
|
960
|
+
property_name=sort_by_property_name,
|
|
961
|
+
sort_type=sort_by_sort_type
|
|
962
|
+
)
|
|
963
|
+
|
|
964
|
+
pagination = None
|
|
965
|
+
if page_size is not None or page_offset is not None:
|
|
966
|
+
pagination = Pagination(page_size=page_size, page_offset=page_offset)
|
|
967
|
+
|
|
968
|
+
parameters = JobQueryParameters(
|
|
969
|
+
sort_by=sort_by,
|
|
970
|
+
filter=filter_param,
|
|
971
|
+
pagination=pagination,
|
|
972
|
+
include_remaining_tags=include_remaining_tags
|
|
973
|
+
)
|
|
974
|
+
return cls(client, parameters)
|
|
975
|
+
|
|
976
|
+
def execute(self) -> JobQueryResultHco:
|
|
977
|
+
"""Executes the query and returns a JobQueryResultHco.
|
|
978
|
+
"""
|
|
979
|
+
return self._jobs_root.job_query_action.execute(self.parameters)
|
|
980
|
+
|
|
981
|
+
def count(self) -> int:
|
|
982
|
+
"""Returns the total number of entities matching the query.
|
|
983
|
+
"""
|
|
984
|
+
return self.execute().total_entities
|
|
985
|
+
|
|
986
|
+
def exists(self) -> bool:
|
|
987
|
+
"""Returns True if there are any entities matching the query.
|
|
988
|
+
"""
|
|
989
|
+
return self.count() > 0
|
|
990
|
+
|
|
991
|
+
def first(self) -> Job | None:
|
|
992
|
+
"""Returns the first entity matching the query, or None if no entities match.
|
|
993
|
+
"""
|
|
994
|
+
result = self.execute()
|
|
995
|
+
if result.jobs:
|
|
996
|
+
return Job.from_hco(result.jobs[0])
|
|
997
|
+
return None
|
|
998
|
+
|
|
999
|
+
def one(self) -> Job:
|
|
1000
|
+
"""Returns exactly one entity matching the query.
|
|
1001
|
+
Raises an exception if no entities are found or if multiple entities match.
|
|
1002
|
+
"""
|
|
1003
|
+
result = self.execute()
|
|
1004
|
+
if result.total_entities == 0:
|
|
1005
|
+
raise Exception("No entities found matching the query.")
|
|
1006
|
+
if result.total_entities > 1:
|
|
1007
|
+
raise Exception(f"Expected exactly one entity, but found {result.total_entities}.")
|
|
1008
|
+
return Job.from_hco(result.jobs[0])
|
|
1009
|
+
|
|
1010
|
+
def to_list(self) -> list[Job]:
|
|
1011
|
+
"""Returns all entities matching the query as a list.
|
|
1012
|
+
"""
|
|
1013
|
+
return list(self.iter())
|
|
1014
|
+
|
|
1015
|
+
def to_job_group(self) -> 'JobGroup':
|
|
1016
|
+
"""Returns a JobGroup containing all jobs matching the query.
|
|
1017
|
+
"""
|
|
1018
|
+
from .job_group import JobGroup
|
|
1019
|
+
return JobGroup.from_query_result(self.execute())
|
|
1020
|
+
|
|
1021
|
+
def iter(self) -> Iterator[Job]:
|
|
1022
|
+
"""
|
|
1023
|
+
Returns an Iterator of `Job` so that all jobs can be processed in a loop.
|
|
1024
|
+
|
|
1025
|
+
Returns:
|
|
1026
|
+
An iterator of `Job` objects
|
|
1027
|
+
"""
|
|
1028
|
+
for page in self.execute().iter():
|
|
1029
|
+
for job_hco in page.jobs:
|
|
1030
|
+
yield Job.from_hco(job_hco)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
from typing import Any, Optional, Self
|
|
1
|
+
from typing import Any, Iterator, Optional, Self
|
|
2
2
|
|
|
3
3
|
import httpx
|
|
4
4
|
from httpx import URL
|
|
5
5
|
|
|
6
|
+
from pydantic import AnyUrl, AwareDatetime
|
|
7
|
+
|
|
6
8
|
from ...core import Link, MediaTypes
|
|
7
9
|
from ...core.hco.upload_action_hco import UploadParameters
|
|
8
10
|
from ..enterjma import enter_jma
|
|
@@ -23,10 +25,15 @@ from ..model import (
|
|
|
23
25
|
DeploymentStates,
|
|
24
26
|
DeprecatePsActionParameters,
|
|
25
27
|
FunctionNameMatchTypes,
|
|
28
|
+
Pagination,
|
|
26
29
|
ProcessingStepFilterParameter,
|
|
27
30
|
ProcessingStepQueryParameters,
|
|
31
|
+
ProcessingStepSortProperties,
|
|
32
|
+
ProcessingStepSortPropertiesSortParameter,
|
|
28
33
|
ScalingConfiguration,
|
|
29
|
-
SetProcessingStepTagsParameters,
|
|
34
|
+
SetProcessingStepTagsParameters,
|
|
35
|
+
SetProcessingStepTitleParameters,
|
|
36
|
+
SortTypes,
|
|
30
37
|
)
|
|
31
38
|
|
|
32
39
|
|
|
@@ -469,3 +476,137 @@ class ProcessingStep:
|
|
|
469
476
|
def _raise_if_no_hco(self):
|
|
470
477
|
if self.processing_step_hco is None:
|
|
471
478
|
raise Exception("No processing step hco present. Maybe this class is used after resource deletion.")
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class ProcessingStepQuery:
|
|
482
|
+
"""Convenience wrapper for querying ProcessingSteps.
|
|
483
|
+
"""
|
|
484
|
+
|
|
485
|
+
_client: httpx.Client
|
|
486
|
+
_entrypoint: EntryPointHco
|
|
487
|
+
_processing_steps_root: ProcessingStepsRootHco
|
|
488
|
+
parameters: ProcessingStepQueryParameters
|
|
489
|
+
|
|
490
|
+
def __init__(self, client: httpx.Client, parameters: ProcessingStepQueryParameters):
|
|
491
|
+
self._client = client
|
|
492
|
+
self._entrypoint = enter_jma(client)
|
|
493
|
+
self._processing_steps_root = self._entrypoint.processing_step_root_link.navigate()
|
|
494
|
+
self.parameters = parameters
|
|
495
|
+
|
|
496
|
+
@classmethod
|
|
497
|
+
def from_parameters(cls, client: httpx.Client, parameters: ProcessingStepQueryParameters) -> Self:
|
|
498
|
+
"""Create a ProcessingStepQuery from a ProcessingStepQueryParameters object.
|
|
499
|
+
"""
|
|
500
|
+
return cls(client, parameters)
|
|
501
|
+
|
|
502
|
+
@classmethod
|
|
503
|
+
def create(
|
|
504
|
+
cls,
|
|
505
|
+
client: httpx.Client,
|
|
506
|
+
*,
|
|
507
|
+
page_size: int | None = None,
|
|
508
|
+
page_offset: int | None = None,
|
|
509
|
+
sort_by_property_name: ProcessingStepSortProperties | None = None,
|
|
510
|
+
sort_by_sort_type: SortTypes | None = None,
|
|
511
|
+
include_remaining_tags: bool | None = None,
|
|
512
|
+
function_name: str | None = None,
|
|
513
|
+
function_name_match_type: FunctionNameMatchTypes | None = None,
|
|
514
|
+
title_contains: str | None = None,
|
|
515
|
+
version: str | None = None,
|
|
516
|
+
description_contains: str | None = None,
|
|
517
|
+
tags_by_and: list[str] | None = None,
|
|
518
|
+
tags_by_or: list[str] | None = None,
|
|
519
|
+
is_public: bool | None = None,
|
|
520
|
+
show_hidden: bool | None = None,
|
|
521
|
+
show_deprecated: bool | None = None,
|
|
522
|
+
deployment_state: DeploymentStates | None = None,
|
|
523
|
+
show_prerelease: bool | None = None,
|
|
524
|
+
pro_con_version: str | None = None
|
|
525
|
+
) -> Self:
|
|
526
|
+
"""Create a ProcessingStepQuery from flat parameters.
|
|
527
|
+
"""
|
|
528
|
+
filter_param = ProcessingStepFilterParameter(
|
|
529
|
+
function_name=function_name,
|
|
530
|
+
function_name_match_type=function_name_match_type,
|
|
531
|
+
title_contains=title_contains,
|
|
532
|
+
version=version,
|
|
533
|
+
description_contains=description_contains,
|
|
534
|
+
tags_by_and=tags_by_and,
|
|
535
|
+
tags_by_or=tags_by_or,
|
|
536
|
+
is_public=is_public,
|
|
537
|
+
show_hidden=show_hidden,
|
|
538
|
+
show_deprecated=show_deprecated,
|
|
539
|
+
deployment_state=deployment_state,
|
|
540
|
+
show_prerelease=show_prerelease,
|
|
541
|
+
pro_con_version=pro_con_version
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
sort_by = None
|
|
545
|
+
if sort_by_property_name is not None or sort_by_sort_type is not None:
|
|
546
|
+
sort_by = ProcessingStepSortPropertiesSortParameter(
|
|
547
|
+
property_name=sort_by_property_name,
|
|
548
|
+
sort_type=sort_by_sort_type
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
pagination = None
|
|
552
|
+
if page_size is not None or page_offset is not None:
|
|
553
|
+
pagination = Pagination(page_size=page_size, page_offset=page_offset)
|
|
554
|
+
|
|
555
|
+
parameters = ProcessingStepQueryParameters(
|
|
556
|
+
sort_by=sort_by,
|
|
557
|
+
filter=filter_param,
|
|
558
|
+
pagination=pagination,
|
|
559
|
+
include_remaining_tags=include_remaining_tags
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
return cls(client, parameters)
|
|
563
|
+
|
|
564
|
+
def execute(self) -> ProcessingStepQueryResultHco:
|
|
565
|
+
"""Executes the query and returns a ProcessingStepQueryResultHco.
|
|
566
|
+
"""
|
|
567
|
+
return self._processing_steps_root.query_action.execute(self.parameters)
|
|
568
|
+
|
|
569
|
+
def count(self) -> int:
|
|
570
|
+
"""Returns the total number of entities matching the query.
|
|
571
|
+
"""
|
|
572
|
+
return self.execute().total_entities
|
|
573
|
+
|
|
574
|
+
def exists(self) -> bool:
|
|
575
|
+
"""Returns True if there are any entities matching the query.
|
|
576
|
+
"""
|
|
577
|
+
return self.count() > 0
|
|
578
|
+
|
|
579
|
+
def first(self) -> ProcessingStep | None:
|
|
580
|
+
"""Returns the first entity matching the query, or None if no entities match.
|
|
581
|
+
"""
|
|
582
|
+
result = self.execute()
|
|
583
|
+
if result.processing_steps:
|
|
584
|
+
return ProcessingStep.from_hco(result.processing_steps[0])
|
|
585
|
+
return None
|
|
586
|
+
|
|
587
|
+
def one(self) -> ProcessingStep:
|
|
588
|
+
"""Returns exactly one entity matching the query.
|
|
589
|
+
Raises an exception if no entities are found or if multiple entities match.
|
|
590
|
+
"""
|
|
591
|
+
result = self.execute()
|
|
592
|
+
if result.total_entities == 0:
|
|
593
|
+
raise Exception("No entities found matching the query.")
|
|
594
|
+
if result.total_entities > 1:
|
|
595
|
+
raise Exception(f"Expected exactly one entity, but found {result.total_entities}.")
|
|
596
|
+
return ProcessingStep.from_hco(result.processing_steps[0])
|
|
597
|
+
|
|
598
|
+
def to_list(self) -> list[ProcessingStep]:
|
|
599
|
+
"""Returns all entities matching the query as a list.
|
|
600
|
+
"""
|
|
601
|
+
return list(self.iter())
|
|
602
|
+
|
|
603
|
+
def iter(self) -> Iterator[ProcessingStep]:
|
|
604
|
+
"""
|
|
605
|
+
Returns an Iterator of `ProcessingStep` so that all processing steps can be processed in a loop.
|
|
606
|
+
|
|
607
|
+
Returns:
|
|
608
|
+
An iterator of `ProcessingStep` objects
|
|
609
|
+
"""
|
|
610
|
+
for page in self.execute().iter():
|
|
611
|
+
for ps_hco in page.processing_steps:
|
|
612
|
+
yield ProcessingStep.from_hco(ps_hco)
|
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
from io import IOBase
|
|
2
|
-
from typing import Any, AsyncIterable, Iterable, Self
|
|
2
|
+
from typing import Any, AsyncIterable, Iterable, Iterator, Self
|
|
3
3
|
|
|
4
4
|
import httpx
|
|
5
5
|
from httpx import URL
|
|
6
6
|
|
|
7
|
+
from pydantic import AnyUrl, AwareDatetime
|
|
8
|
+
|
|
7
9
|
from ...core import Link, MediaTypes
|
|
8
10
|
from ...core.hco.upload_action_hco import UploadParameters
|
|
9
11
|
from ..enterjma import enter_jma
|
|
10
|
-
from ..hcos import
|
|
12
|
+
from ..hcos import (
|
|
13
|
+
EntryPointHco,
|
|
14
|
+
WorkDataHco,
|
|
15
|
+
WorkDataLink,
|
|
16
|
+
WorkDataQueryResultHco,
|
|
17
|
+
WorkDataRootHco,
|
|
18
|
+
)
|
|
11
19
|
from ..known_relations import Relations
|
|
12
|
-
from ..model import
|
|
20
|
+
from ..model import (
|
|
21
|
+
CopyWorkDataFromUserToOrgActionParameters,
|
|
22
|
+
Pagination,
|
|
23
|
+
SetTagsWorkDataParameters,
|
|
24
|
+
SortTypes,
|
|
25
|
+
WorkDataFilterParameter,
|
|
26
|
+
WorkDataKind,
|
|
27
|
+
WorkDataQueryParameters,
|
|
28
|
+
WorkDataSortProperties,
|
|
29
|
+
WorkDataSortPropertiesSortParameter,
|
|
30
|
+
)
|
|
13
31
|
|
|
14
32
|
|
|
15
33
|
class WorkData:
|
|
@@ -188,4 +206,133 @@ class WorkData:
|
|
|
188
206
|
|
|
189
207
|
def _raise_if_no_hco(self):
|
|
190
208
|
if self.work_data_hco is None:
|
|
191
|
-
raise Exception("No work data hco present. Maybe this class is used after resource deletion.")
|
|
209
|
+
raise Exception("No work data hco present. Maybe this class is used after resource deletion.")
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class WorkDataQuery:
|
|
213
|
+
"""Convenience wrapper for querying WorkData.
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
_client: httpx.Client
|
|
217
|
+
_entrypoint: EntryPointHco
|
|
218
|
+
_work_data_root: WorkDataRootHco
|
|
219
|
+
parameters: WorkDataQueryParameters
|
|
220
|
+
|
|
221
|
+
def __init__(self, client: httpx.Client, parameters: WorkDataQueryParameters):
|
|
222
|
+
self._client = client
|
|
223
|
+
self._entrypoint = enter_jma(client)
|
|
224
|
+
self._work_data_root = self._entrypoint.work_data_root_link.navigate()
|
|
225
|
+
self.parameters = parameters
|
|
226
|
+
|
|
227
|
+
@classmethod
|
|
228
|
+
def from_parameters(cls, client: httpx.Client, parameters: WorkDataQueryParameters) -> Self:
|
|
229
|
+
"""Create a WorkDataQuery from a WorkDataQueryParameters object.
|
|
230
|
+
"""
|
|
231
|
+
return cls(client, parameters)
|
|
232
|
+
|
|
233
|
+
@classmethod
|
|
234
|
+
def create(
|
|
235
|
+
cls,
|
|
236
|
+
client: httpx.Client,
|
|
237
|
+
*,
|
|
238
|
+
page_size: int | None = None,
|
|
239
|
+
page_offset: int | None = None,
|
|
240
|
+
sort_by_property_name: WorkDataSortProperties | None = None,
|
|
241
|
+
sort_by_sort_type: SortTypes | None = None,
|
|
242
|
+
include_remaining_tags: bool | None = None,
|
|
243
|
+
name_contains: str | None = None,
|
|
244
|
+
producer_processing_step_url: AnyUrl | None = None,
|
|
245
|
+
show_hidden: bool | None = None,
|
|
246
|
+
media_type_contains: str | None = None,
|
|
247
|
+
tags_by_and: list[str] | None = None,
|
|
248
|
+
tags_by_or: list[str] | None = None,
|
|
249
|
+
is_kind: WorkDataKind | None = None,
|
|
250
|
+
created_before: AwareDatetime | None = None,
|
|
251
|
+
created_after: AwareDatetime | None = None,
|
|
252
|
+
is_deletable: bool | None = None,
|
|
253
|
+
is_used: bool | None = None
|
|
254
|
+
) -> Self:
|
|
255
|
+
"""Create a WorkDataQuery from flat parameters.
|
|
256
|
+
"""
|
|
257
|
+
filter_param = WorkDataFilterParameter(
|
|
258
|
+
name_contains=name_contains,
|
|
259
|
+
producer_processing_step_url=producer_processing_step_url,
|
|
260
|
+
show_hidden=show_hidden,
|
|
261
|
+
media_type_contains=media_type_contains,
|
|
262
|
+
tags_by_and=tags_by_and,
|
|
263
|
+
tags_by_or=tags_by_or,
|
|
264
|
+
is_kind=is_kind,
|
|
265
|
+
created_before=created_before,
|
|
266
|
+
created_after=created_after,
|
|
267
|
+
is_deletable=is_deletable,
|
|
268
|
+
is_used=is_used
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
sort_by = None
|
|
272
|
+
if sort_by_property_name is not None or sort_by_sort_type is not None:
|
|
273
|
+
sort_by = WorkDataSortPropertiesSortParameter(
|
|
274
|
+
property_name=sort_by_property_name,
|
|
275
|
+
sort_type=sort_by_sort_type
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
pagination = None
|
|
279
|
+
if page_size is not None or page_offset is not None:
|
|
280
|
+
pagination = Pagination(page_size=page_size, page_offset=page_offset)
|
|
281
|
+
|
|
282
|
+
parameters = WorkDataQueryParameters(
|
|
283
|
+
sort_by=sort_by,
|
|
284
|
+
filter=filter_param,
|
|
285
|
+
pagination=pagination,
|
|
286
|
+
include_remaining_tags=include_remaining_tags
|
|
287
|
+
)
|
|
288
|
+
return cls(client, parameters)
|
|
289
|
+
|
|
290
|
+
def execute(self) -> WorkDataQueryResultHco:
|
|
291
|
+
"""Executes the query and returns a WorkDataQueryResultHco.
|
|
292
|
+
"""
|
|
293
|
+
return self._work_data_root.query_action.execute(self.parameters)
|
|
294
|
+
|
|
295
|
+
def count(self) -> int:
|
|
296
|
+
"""Returns the total number of entities matching the query.
|
|
297
|
+
"""
|
|
298
|
+
return self.execute().total_entities
|
|
299
|
+
|
|
300
|
+
def exists(self) -> bool:
|
|
301
|
+
"""Returns True if there are any entities matching the query.
|
|
302
|
+
"""
|
|
303
|
+
return self.count() > 0
|
|
304
|
+
|
|
305
|
+
def first(self) -> WorkData | None:
|
|
306
|
+
"""Returns the first entity matching the query, or None if no entities match.
|
|
307
|
+
"""
|
|
308
|
+
result = self.execute()
|
|
309
|
+
if result.workdatas:
|
|
310
|
+
return WorkData.from_hco(result.workdatas[0])
|
|
311
|
+
return None
|
|
312
|
+
|
|
313
|
+
def one(self) -> WorkData:
|
|
314
|
+
"""Returns exactly one entity matching the query.
|
|
315
|
+
Raises an exception if no entities are found or if multiple entities match.
|
|
316
|
+
"""
|
|
317
|
+
result = self.execute()
|
|
318
|
+
if result.total_entities == 0:
|
|
319
|
+
raise Exception("No entities found matching the query.")
|
|
320
|
+
if result.total_entities > 1:
|
|
321
|
+
raise Exception(f"Expected exactly one entity, but found {result.total_entities}.")
|
|
322
|
+
return WorkData.from_hco(result.workdatas[0])
|
|
323
|
+
|
|
324
|
+
def to_list(self) -> list[WorkData]:
|
|
325
|
+
"""Returns all entities matching the query as a list.
|
|
326
|
+
"""
|
|
327
|
+
return list(self.iter())
|
|
328
|
+
|
|
329
|
+
def iter(self) -> Iterator[WorkData]:
|
|
330
|
+
"""
|
|
331
|
+
Returns an Iterator of `WorkData` so that all work data can be processed in a loop.
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
An iterator of `WorkData` objects
|
|
335
|
+
"""
|
|
336
|
+
for page in self.execute().iter():
|
|
337
|
+
for work_data_hco in page.workdatas:
|
|
338
|
+
yield WorkData.from_hco(work_data_hco)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pinexq-client
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: A hypermedia-based client for the DataCybernetics PinexQ platform.
|
|
5
5
|
Author: Sebastian Höfer, Mathias Reichardt, Pratik Poudel
|
|
6
6
|
Author-email: Sebastian Höfer <hoefer@data-cybernetics.com>, Mathias Reichardt <reichardt@data-cybernetics.com>, Pratik Poudel <poudel@data-cybernetics.com>
|
|
@@ -18,7 +18,7 @@ pinexq/client/core/model/error.py,sha256=ZDbUlwsj7d8XPMolSSLTFwgs3RBLvOvgmlEtoBu
|
|
|
18
18
|
pinexq/client/core/model/sirenmodels.py,sha256=vGRQlhM2cSa2caxQel91Jr48KWqM-vMYX32iaQCzIds,5547
|
|
19
19
|
pinexq/client/core/polling.py,sha256=nNEDONEkB3Gu5WUMm2u9RFG1OIclnixaiy7l_U2Z4No,1146
|
|
20
20
|
pinexq/client/core/sirenaccess.py,sha256=F7eZI5Pz79el0D30SYNGsiS2qWaAZF_jrCrUy-q2GgY,6992
|
|
21
|
-
pinexq/client/job_management/__init__.py,sha256=
|
|
21
|
+
pinexq/client/job_management/__init__.py,sha256=s2rP7K9AVbmSExyC8PF7rZ6U1tuvaO8-p4xY3okfYuc,644
|
|
22
22
|
pinexq/client/job_management/enterjma.py,sha256=N_jNM2UhQmWL8e-xBrTHbjZzP7WkX98MyFuKsYgD-XQ,3252
|
|
23
23
|
pinexq/client/job_management/hcos/__init__.py,sha256=TZgs5kuBk3lSBxPfn5ehgbdUgzPy2jn1PC3Ea6VQY-k,584
|
|
24
24
|
pinexq/client/job_management/hcos/entrypoint_hco.py,sha256=omFPggY7XGRWI5ogR85I7BHUi5o6OBnLyMggYh76JEg,2204
|
|
@@ -40,13 +40,13 @@ pinexq/client/job_management/hcos/workdata_used_tags_query_result_hco.py,sha256=
|
|
|
40
40
|
pinexq/client/job_management/hcos/workdataroot_hco.py,sha256=WRAFihgbyxJBrGKEhAzQwds57G_WndoS0EAW1AZ38tU,4221
|
|
41
41
|
pinexq/client/job_management/known_relations.py,sha256=do-u2wjb6u_HK2-y604f2gs3rk9O19MTIZpvbkfTSpA,905
|
|
42
42
|
pinexq/client/job_management/model/__init__.py,sha256=iuAKRXdW_Mxo0i3HsBfEzhJJZUKkNe3qs4gLW-ge1PU,63
|
|
43
|
-
pinexq/client/job_management/model/open_api_generated.py,sha256=
|
|
43
|
+
pinexq/client/job_management/model/open_api_generated.py,sha256=ydfwdMAoO1Bb9Cqmqmm5IhzMrEM6CUcZLVK-rhRdy_8,41544
|
|
44
44
|
pinexq/client/job_management/model/sirenentities.py,sha256=E29Z2MSAYIO1RYvOW_rDpzUHZUMNMioQd_-k_S4KnbQ,3958
|
|
45
|
-
pinexq/client/job_management/tool/__init__.py,sha256=
|
|
46
|
-
pinexq/client/job_management/tool/job.py,sha256=
|
|
45
|
+
pinexq/client/job_management/tool/__init__.py,sha256=4cPlrnA3lhaqFH2OFB6wyMjidgMpr05QczVJU_59kx4,174
|
|
46
|
+
pinexq/client/job_management/tool/job.py,sha256=cSc-YJh96-ljEDWbx-JLjHCoIwzID8mk9lTQxvG3vDM,39624
|
|
47
47
|
pinexq/client/job_management/tool/job_group.py,sha256=ZFUHTk6j3oZOD52D6SOsREdBm5hVn9iUhLykrN_Ghes,11117
|
|
48
|
-
pinexq/client/job_management/tool/processing_step.py,sha256=
|
|
49
|
-
pinexq/client/job_management/tool/workdata.py,sha256=
|
|
50
|
-
pinexq_client-1.1.
|
|
51
|
-
pinexq_client-1.1.
|
|
52
|
-
pinexq_client-1.1.
|
|
48
|
+
pinexq/client/job_management/tool/processing_step.py,sha256=9NzbE8btG3mKGiS6cRAqehgVoolvQQZZDi2MRgvW2mA,20920
|
|
49
|
+
pinexq/client/job_management/tool/workdata.py,sha256=_X-v0t6oIBK-0hwvnpFwcdcO4rEkXmyKwobjZtOfGl0,11131
|
|
50
|
+
pinexq_client-1.2.1.dist-info/WHEEL,sha256=5DEXXimM34_d4Gx1AuF9ysMr1_maoEtGKjaILM3s4w4,80
|
|
51
|
+
pinexq_client-1.2.1.dist-info/METADATA,sha256=GauZDDEAm_tSDA1OfBkqWThWFZ0naqaYfNVDo5bs6eY,3459
|
|
52
|
+
pinexq_client-1.2.1.dist-info/RECORD,,
|