@orcabus/platform-cdk-constructs 0.0.5 → 0.0.7-alpha.3

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 (83) hide show
  1. package/.jsii +859 -10
  2. package/api-gateway/api-gateway.js +22 -4
  3. package/deployment-stack-pipeline/pipeline.js +8 -5
  4. package/dynamodb/config.d.ts +3 -0
  5. package/dynamodb/config.js +7 -0
  6. package/dynamodb/index.d.ts +27 -0
  7. package/dynamodb/index.js +106 -0
  8. package/ecs/config.d.ts +4 -0
  9. package/ecs/config.js +8 -0
  10. package/ecs/index.d.ts +46 -0
  11. package/ecs/index.js +103 -0
  12. package/index.d.ts +5 -2
  13. package/index.js +47 -5
  14. package/index.ts +16 -2
  15. package/lambda/build_python/Dockerfile +60 -0
  16. package/lambda/config.d.ts +11 -0
  17. package/lambda/config.js +19 -0
  18. package/lambda/index.d.ts +59 -0
  19. package/lambda/index.js +242 -0
  20. package/lambda/layers/mart_tools/poetry.lock +303 -0
  21. package/lambda/layers/mart_tools/pyproject.toml +27 -0
  22. package/lambda/layers/mart_tools/src/mart_tools/__init__.py +0 -0
  23. package/lambda/layers/mart_tools/src/mart_tools/mart/__init__.py +8 -0
  24. package/lambda/layers/mart_tools/src/mart_tools/mart/aws_helpers.py +79 -0
  25. package/lambda/layers/mart_tools/src/mart_tools/mart/dataframe_helpers.py +29 -0
  26. package/lambda/layers/mart_tools/src/mart_tools/mart/globals.py +5 -0
  27. package/lambda/layers/mart_tools/src/mart_tools/mart/models.py +71 -0
  28. package/lambda/layers/orcabus_api_tools/poetry.lock +273 -0
  29. package/lambda/layers/orcabus_api_tools/pyproject.toml +27 -0
  30. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/__init__.py +0 -0
  31. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/__init__.py +172 -0
  32. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/create_helpers.py +47 -0
  33. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/globals.py +13 -0
  34. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/job_helpers.py +53 -0
  35. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/models.py +253 -0
  36. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/query_helpers.py +248 -0
  37. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/update_helpers.py +221 -0
  38. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq/workflow_helpers.py +25 -0
  39. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/__init__.py +92 -0
  40. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/create_helpers.py +27 -0
  41. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/globals.py +21 -0
  42. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/models.py +51 -0
  43. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/query_helpers.py +52 -0
  44. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/fastq_unarchiving/update_helpers.py +45 -0
  45. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/__init__.py +98 -0
  46. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/errors.py +45 -0
  47. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/file_helpers.py +341 -0
  48. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/globals.py +70 -0
  49. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/filemanager/models.py +59 -0
  50. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/__init__.py +8 -0
  51. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/aws_helpers.py +79 -0
  52. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/dataframe_helpers.py +29 -0
  53. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/globals.py +5 -0
  54. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/mart/models.py +71 -0
  55. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/__init__.py +250 -0
  56. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/contact_helpers.py +109 -0
  57. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/errors.py +104 -0
  58. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/globals.py +16 -0
  59. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/individual_helpers.py +139 -0
  60. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/library_helpers.py +196 -0
  61. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/lims_helpers.py +36 -0
  62. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/models.py +112 -0
  63. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/project_helpers.py +129 -0
  64. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/sample_helpers.py +132 -0
  65. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/metadata/subject_helpers.py +151 -0
  66. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/__init__.py +15 -0
  67. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/globals.py +2 -0
  68. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/models.py +44 -0
  69. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/sequence/sequence_helpers.py +62 -0
  70. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/__init__.py +0 -0
  71. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/aws_helpers.py +123 -0
  72. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/miscell.py +17 -0
  73. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/utils/requests_helpers.py +163 -0
  74. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/__init__.py +0 -0
  75. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/errors.py +37 -0
  76. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/metadata_helpers.py +28 -0
  77. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/models.py +85 -0
  78. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/payload_helpers.py +64 -0
  79. package/lambda/layers/orcabus_api_tools/src/orcabus_api_tools/workflow/workflow_run_helpers.py +80 -0
  80. package/package.json +14 -11
  81. package/typedoc.json +3 -0
  82. package/utils/index.d.ts +3 -0
  83. package/utils/index.js +50 -1
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env python3
2
+
3
+
4
+ """
5
+ Helper functions for a subject
6
+ """
7
+
8
+ # Standard imports
9
+ from typing import List
10
+ from requests import HTTPError
11
+
12
+ # Local imports
13
+ from . import get_metadata_request_response_results, get_item_objs_from_item_id_list
14
+ from .errors import SubjectNotFoundError
15
+ from .globals import SUBJECT_ENDPOINT, ORCABUS_ULID_REGEX_MATCH
16
+ from .models import Subject, Sample, LibraryDetail
17
+
18
+
19
+ def get_subject_from_subject_id(subject_id: str) -> Subject:
20
+ """
21
+ Get subject from the subject id
22
+ :param subject_id:
23
+ :return:
24
+ """
25
+ # We have an internal id, convert to int
26
+ params = {
27
+ "subject_id": subject_id
28
+ }
29
+
30
+ # Get subject
31
+ try:
32
+ query_results = get_metadata_request_response_results(SUBJECT_ENDPOINT, params)
33
+ assert len(query_results) == 1
34
+ return query_results[0]
35
+ except (HTTPError, AssertionError):
36
+ raise SubjectNotFoundError(
37
+ subject_id=subject_id
38
+ )
39
+
40
+
41
+ def get_subjects_list_from_subject_id_list(subject_id_list: List[str], accept_missing: bool = False) -> List[Sample]:
42
+ """
43
+ Get sample from the sample id
44
+ :param sample_id:
45
+ :return:
46
+ """
47
+ # We have an internal id, convert to int
48
+ return list(map(
49
+ lambda sample_iter_: Sample(**sample_iter_),
50
+ get_item_objs_from_item_id_list(
51
+ item_id_list=subject_id_list,
52
+ item_identifier="subjectId",
53
+ endpoint=SUBJECT_ENDPOINT,
54
+ accept_missing=accept_missing
55
+ )
56
+ ))
57
+
58
+
59
+ def coerce_subject_id_or_orcabus_id_to_subject_orcabus_id(id_: str) -> str:
60
+ if ORCABUS_ULID_REGEX_MATCH.match(id_):
61
+ return id_
62
+ else :
63
+ return get_subject_orcabus_id_from_subject_id(id_)
64
+
65
+
66
+ def get_subject_orcabus_id_from_subject_id(subject_id: str) -> str:
67
+ """
68
+ Get the subject orcabus id from the subject id
69
+ :param subject_id:
70
+ :return:
71
+ """
72
+ return get_subject_from_subject_id(subject_id)['orcabusId']
73
+
74
+
75
+ def get_subjects_list_from_subject_orcabus_id_list(subject_orcabus_id_list: List[str], accept_missing: bool = False) -> List[Sample]:
76
+ """
77
+ Get sample from the sample id
78
+ :param sample_id:
79
+ :return:
80
+ """
81
+ # We have an internal id, convert to int
82
+ return list(map(
83
+ lambda sample_iter_: Sample(**sample_iter_),
84
+ get_item_objs_from_item_id_list(
85
+ item_id_list=subject_orcabus_id_list,
86
+ item_identifier="subjectId",
87
+ endpoint=SUBJECT_ENDPOINT,
88
+ accept_missing=accept_missing
89
+ )
90
+ ))
91
+
92
+
93
+ def get_subject_from_subject_orcabus_id(subject_orcabus_id: str) -> Subject:
94
+ """
95
+ Get subject from the subject id
96
+ :param subject_orcabus_id:
97
+ :return:
98
+ """
99
+ # Get subject id
100
+ # We have an internal id, convert to int
101
+ params = {
102
+ "orcabus_id": subject_orcabus_id
103
+ }
104
+
105
+ # Get subject
106
+ try:
107
+ query_results = get_metadata_request_response_results(SUBJECT_ENDPOINT, params)
108
+ assert len(query_results) == 1
109
+ return query_results[0]
110
+ except (HTTPError, AssertionError):
111
+ raise SubjectNotFoundError(
112
+ subject_orcabus_id=subject_orcabus_id
113
+ )
114
+
115
+
116
+ def list_samples_in_subject(subject_orcabus_id: str) -> List[Sample]:
117
+ """
118
+ Given a subject id, list the samples in the subject
119
+ :param subject_orcabus_id:
120
+ :return:
121
+ """
122
+ from .sample_helpers import get_sample_from_sample_orcabus_id
123
+
124
+ # Get the subject
125
+ return list(map(
126
+ # For each subject, get libraries in subject
127
+ lambda library_iter_: get_sample_from_sample_orcabus_id(library_iter_['sample']['orcabusId']),
128
+ # Get list of subject orcabus ids
129
+ list_libraries_in_subject(subject_orcabus_id)
130
+ ))
131
+
132
+
133
+ def list_libraries_in_subject(subject_orcabus_id: str) -> List[LibraryDetail]:
134
+ """
135
+ Given a subject id, return the list of library objects in the subject
136
+ :param subject_orcabus_id:
137
+ :return:
138
+ """
139
+ # Get ID For Subject
140
+ subject = get_subject_from_subject_orcabus_id(subject_orcabus_id)
141
+
142
+ # Get the subject
143
+ return subject.get("librarySet", [])
144
+
145
+
146
+ def get_all_subjects() -> List[Subject]:
147
+ """
148
+ Get all subjects
149
+ :return:
150
+ """
151
+ return get_metadata_request_response_results(SUBJECT_ENDPOINT)
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from sequence_helpers import (
4
+ get_sequence_object_from_instrument_run_id,
5
+ get_sample_sheet_from_orcabus_id,
6
+ get_library_ids_in_sequence,
7
+ )
8
+
9
+ __all__ = [
10
+ "get_sequence_object_from_instrument_run_id",
11
+ "get_sample_sheet_from_orcabus_id",
12
+ "get_library_ids_in_sequence",
13
+ ]
14
+
15
+
@@ -0,0 +1,2 @@
1
+ # Run name for sequence run manager
2
+ SEQUENCE_SUBDOMAIN_NAME = 'sequence'
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from typing import TypedDict, Literal, NotRequired, Optional, Dict
4
+
5
+ statusLiteral = Literal['STARTED', 'FAILED', 'SUCCEEDED', 'ABORTED', 'RESOLVED']
6
+
7
+
8
+ class SequenceDetail(TypedDict):
9
+ orcabusId: str
10
+ instrumentRunId: str
11
+ experimentName: str
12
+ startTime: str
13
+ endTime: str
14
+ status: statusLiteral
15
+
16
+
17
+ class Sequence(TypedDict):
18
+ orcabusId: str
19
+ libraries: str
20
+ sequenceRunId: str
21
+ status: statusLiteral
22
+ startTime: str
23
+ sampleSheetName: str
24
+ v1pre3Id: str
25
+ icaProjectId: str
26
+ apiUrl: str
27
+ endTime: str
28
+ runVolumeName: str
29
+ runFolderPath: str
30
+ runDataUri: str
31
+ instrumentRunId: str
32
+ reagentBarcode: str
33
+ flowcellBarcode: str
34
+ sequenceRunName: str
35
+ experimentName: str
36
+
37
+
38
+ class SampleSheet(TypedDict):
39
+ orcabusId: str
40
+ sampleSheetName: str
41
+ associationStatus: str
42
+ associationTimestamp: str
43
+ sampleSheetContent: Optional[Dict]
44
+ sequence: str
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env python3
2
+ from .globals import SEQUENCE_SUBDOMAIN_NAME
3
+ from .models import Sequence, SequenceDetail, SampleSheet
4
+ from ..utils.requests_helpers import get_request_response_results, get_request, get_url
5
+
6
+
7
+ def get_sequence_url(endpoint: str) -> str:
8
+ """
9
+ Get the URL for the Metadata endpoint
10
+ :param endpoint:
11
+ :return:
12
+ """
13
+ return get_url(
14
+ endpoint,
15
+ SEQUENCE_SUBDOMAIN_NAME
16
+ )
17
+
18
+ def get_sequence_object_from_instrument_run_id(instrument_run_id: str) -> SequenceDetail:
19
+ """
20
+ Get the sequence object from the instrument run id.
21
+ :param instrument_run_id:
22
+ :return:
23
+ """
24
+
25
+ return Sequence(
26
+ **dict(
27
+ get_request_response_results(
28
+ get_sequence_url(endpoint="api/v1/sequence"),
29
+ params={
30
+ "instrumentRunId": instrument_run_id,
31
+ }
32
+ )[0]
33
+ )
34
+ )
35
+
36
+
37
+ def get_sample_sheet_from_orcabus_id(sequence_orcabus_id: str) -> SampleSheet:
38
+ """
39
+ Get the sample sheet from the orcabus id.
40
+ :param sequence_orcabus_id:
41
+ :return:
42
+ """
43
+
44
+ return SampleSheet(
45
+ **dict(
46
+ get_request(
47
+ get_sequence_url(endpoint=f"api/v1/sequence/{sequence_orcabus_id}/sample_sheet")
48
+ )
49
+ )
50
+ )
51
+
52
+
53
+ def get_library_ids_in_sequence(sequence_orcabus_id: str) -> list[str]:
54
+ """
55
+ Get the library ids in the sequence run.
56
+ :param sequence_orcabus_id:
57
+ :return:
58
+ """
59
+
60
+ return get_request(
61
+ get_sequence_url(endpoint=f"api/v1/sequence/{sequence_orcabus_id}")
62
+ )['libraries']
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Standard imports
4
+ import typing
5
+ from typing import Optional
6
+ import boto3
7
+ import json
8
+ from os import environ
9
+ import urllib3
10
+ from urllib.parse import urlunparse
11
+
12
+ # Type hinting
13
+ if typing.TYPE_CHECKING:
14
+ from mypy_boto3_secretsmanager import SecretsManagerClient
15
+ from mypy_boto3_ssm import SSMClient
16
+
17
+ # Set globals
18
+ ORCABUS_TOKEN_STR: Optional[str] = None
19
+ HOSTNAME_STR: Optional[str] = None
20
+
21
+ http = urllib3.PoolManager()
22
+
23
+ LOCAL_HTTP_CACHE_PORT = 2773
24
+ PARAMETER_URL = '/systemsmanager/parameters/get/'
25
+ SECRETS_URL = '/secretsmanager/get/'
26
+
27
+ def retrieve_extension_value(url, query):
28
+ url = str(urlunparse((
29
+ 'http', f'localhost:{LOCAL_HTTP_CACHE_PORT}',
30
+ url, None,
31
+ "&".join(list(map(
32
+ lambda kv: f"{kv[0]}={kv[1]}",
33
+ query.items()
34
+ ))), None
35
+ )))
36
+ headers = {
37
+ "X-Aws-Parameters-Secrets-Token": environ.get('AWS_SESSION_TOKEN')
38
+ }
39
+ response = http.request("GET", url, headers=headers)
40
+ response = json.loads(response.data)
41
+ return response
42
+
43
+
44
+ def get_ssm_value_from_cache(parameter_name: str) -> Optional[str]:
45
+ try:
46
+ return retrieve_extension_value(
47
+ PARAMETER_URL,
48
+ {
49
+ "name": parameter_name,
50
+ }
51
+ )['Parameter']['Value']
52
+ except Exception as e:
53
+ print("Got an exception while trying to get ssm value from cache")
54
+ print(e)
55
+ return None
56
+
57
+
58
+ def get_secret_value_from_cache(secret_id: str) -> Optional[str]:
59
+ try:
60
+ return retrieve_extension_value(
61
+ SECRETS_URL,
62
+ {
63
+ "secretId": secret_id,
64
+ }
65
+ )['SecretString']
66
+ except Exception as e:
67
+ print("Got an exception while trying to get secret value from cache")
68
+ print(e)
69
+ return None
70
+
71
+ def get_secretsmanager_client() -> 'SecretsManagerClient':
72
+ return boto3.client('secretsmanager')
73
+
74
+
75
+ def get_ssm_client() -> 'SSMClient':
76
+ return boto3.client('ssm')
77
+
78
+
79
+ def get_secret_value(secret_id) -> str:
80
+ """
81
+ Collect the secret value
82
+ :param secret_id:
83
+ :return:
84
+ """
85
+ secret_value_cached = get_secret_value_from_cache(secret_id)
86
+ if secret_value_cached is not None:
87
+ return secret_value_cached
88
+
89
+ # Get the boto3 response
90
+ get_secret_value_response = get_secretsmanager_client().get_secret_value(SecretId=secret_id)
91
+
92
+ return get_secret_value_response['SecretString']
93
+
94
+
95
+ def get_ssm_value(parameter_name) -> str:
96
+ """
97
+ Collect the parameter from SSM
98
+ :param parameter_name:
99
+ :return:
100
+ """
101
+ ssm_parameter_cached = get_ssm_value_from_cache(parameter_name)
102
+ if ssm_parameter_cached is not None:
103
+ return ssm_parameter_cached
104
+
105
+ # Get the boto3 response
106
+ get_ssm_parameter_response = get_ssm_client().get_parameter(Name=parameter_name)
107
+
108
+ return get_ssm_parameter_response['Parameter']['Value']
109
+
110
+
111
+ def get_orcabus_token() -> str:
112
+ """
113
+ From the AWS Secrets Manager, retrieve the OrcaBus token.
114
+ :return:
115
+ """
116
+ return (
117
+ json.loads(
118
+ get_secret_value(environ.get("ORCABUS_TOKEN_SECRET_ID"))
119
+ )['id_token']
120
+ )
121
+
122
+ def get_hostname() -> str:
123
+ return get_ssm_value(environ.get("HOSTNAME_SSM_PARAMETER"))
@@ -0,0 +1,17 @@
1
+ from urllib.parse import urlparse
2
+
3
+ def get_bucket_key_pair_from_uri(s3_uri: str) -> (str, str):
4
+ """
5
+ Get the bucket and key from an s3 uri
6
+ :param s3_uri:
7
+ :return:
8
+ """
9
+ url_obj = urlparse(s3_uri)
10
+
11
+ s3_bucket = url_obj.netloc
12
+ s3_key = url_obj.path.lstrip('/')
13
+
14
+ if s3_bucket is None or s3_key is None:
15
+ raise ValueError(f"Invalid S3 URI: {s3_uri}")
16
+
17
+ return s3_bucket, s3_key
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env python3
2
+ from typing import Dict, Optional, List
3
+ from urllib.parse import urlunparse
4
+
5
+ # Standard imports
6
+ import requests
7
+ import logging
8
+ from copy import deepcopy
9
+
10
+ from requests import HTTPError
11
+
12
+ # Locals
13
+ from .aws_helpers import (
14
+ get_orcabus_token, get_hostname
15
+ )
16
+
17
+ # Globals
18
+ DEFAULT_REQUEST_PARAMS = {
19
+ "rowsPerPage": 1000
20
+ }
21
+
22
+ # Set logging
23
+ logger = logging.getLogger(__name__)
24
+ logger.setLevel(logging.INFO)
25
+
26
+
27
+ def get_url(
28
+ endpoint: str,
29
+ subdomain: str
30
+ ) -> str:
31
+ """
32
+ Get the URL for the Metadata endpoint
33
+ :param endpoint:
34
+ :return:
35
+ """
36
+ # Get the hostname
37
+ hostname = get_hostname()
38
+
39
+ return str(urlunparse((
40
+ "https",
41
+ ".".join([subdomain, hostname]),
42
+ endpoint,
43
+ None, None, None
44
+ )))
45
+
46
+
47
+ def get_request_response_results(url: str, params: Optional[Dict] = None) -> List[Dict]:
48
+ """
49
+ Run get response against the Metadata endpoint
50
+ :param url:
51
+ :param params:
52
+ :return:
53
+ """
54
+ # Get authorization header
55
+ headers = {
56
+ "Authorization": f"Bearer {get_orcabus_token()}"
57
+ }
58
+
59
+ req_params = deepcopy(DEFAULT_REQUEST_PARAMS)
60
+
61
+ req_params.update(
62
+ params if params is not None else {}
63
+ )
64
+
65
+
66
+ # Make the request
67
+ response = requests.get(
68
+ url,
69
+ headers=headers,
70
+ params=req_params
71
+ )
72
+
73
+ response.raise_for_status()
74
+
75
+ response_json = response.json()
76
+
77
+ if 'links' not in response_json.keys():
78
+ return [response_json]
79
+
80
+ if 'next' in response_json['links'].keys() and response_json['links']['next'] is not None:
81
+ return response_json['results'] + get_request_response_results(response_json['links']['next'])
82
+ return response_json['results']
83
+
84
+
85
+ def get_request(url: str, params: Optional[Dict] = None) -> Dict:
86
+ # Get authorization header
87
+ headers = {
88
+ "Authorization": f"Bearer {get_orcabus_token()}"
89
+ }
90
+
91
+ # Make the request
92
+ response = requests.get(
93
+ url,
94
+ headers=headers,
95
+ params=params if params is not None else {}
96
+ )
97
+
98
+ try:
99
+ response.raise_for_status()
100
+ except HTTPError as e:
101
+ raise HTTPError(f"Error {e} - {response.text}") from e
102
+
103
+ return response.json()
104
+
105
+
106
+ def patch_request(url: str, params: Optional[Dict] = None) -> Dict:
107
+ # Get authorization header
108
+ headers = {
109
+ "Authorization": f"Bearer {get_orcabus_token()}"
110
+ }
111
+
112
+ req_params = deepcopy(DEFAULT_REQUEST_PARAMS)
113
+
114
+ req_params.update(
115
+ params if params is not None else {}
116
+ )
117
+
118
+ # Make the request
119
+ response = requests.patch(
120
+ url,
121
+ headers=headers,
122
+ json=req_params
123
+ )
124
+
125
+ try:
126
+ response.raise_for_status()
127
+ except HTTPError as e:
128
+ raise HTTPError(f"Error {e} - {response.text}") from e
129
+
130
+ return response.json()
131
+
132
+
133
+ def post_request(url: str, params: Optional[Dict] = None) -> Dict:
134
+ """
135
+ Run post request against the fastq endpoint
136
+ :param url:
137
+ :param params:
138
+ :return:
139
+ """
140
+ # Get authorization header
141
+ headers = {
142
+ "Authorization": f"Bearer {get_orcabus_token()}"
143
+ }
144
+
145
+ req_params = deepcopy(DEFAULT_REQUEST_PARAMS)
146
+
147
+ req_params.update(
148
+ params if params is not None else {}
149
+ )
150
+
151
+ # Make the request
152
+ response = requests.post(
153
+ url,
154
+ headers=headers,
155
+ json=req_params
156
+ )
157
+
158
+ try:
159
+ response.raise_for_status()
160
+ except HTTPError as e:
161
+ raise HTTPError(f"Error {e} - {response.text}") from e
162
+
163
+ return response.json()
@@ -0,0 +1,37 @@
1
+ from typing import Optional
2
+
3
+
4
+ class WorkflowRunNotFoundError(Exception):
5
+ def __init__(
6
+ self,
7
+ workflow_run_id: Optional[str] = None,
8
+ portal_run_id: Optional[str] = None,
9
+ ):
10
+ self.workflow_run_id = workflow_run_id
11
+ self.portal_run_id = portal_run_id
12
+ if workflow_run_id is not None:
13
+ self.message = f"Could not find workflow with orcabus run id '{workflow_run_id}'"
14
+ elif portal_run_id is not None:
15
+ self.message = f"Could not find workflow run portal run id '{portal_run_id}'"
16
+ else:
17
+ self.message = "Could not find workflow"
18
+ super().__init__(self.message)
19
+
20
+
21
+ class WorkflowRunStateNotFoundError(Exception):
22
+ def __init__(
23
+ self,
24
+ workflow_run_id: Optional[str] = None,
25
+ portal_run_id: Optional[str] = None,
26
+ status: Optional[str] = None,
27
+ ):
28
+ self.workflow_run_id = workflow_run_id
29
+ self.portal_run_id = portal_run_id
30
+ self.status = status
31
+ if workflow_run_id is not None:
32
+ self.message = f"Could not find workflow with orcabus run id '{workflow_run_id}', status '{status}'"
33
+ elif portal_run_id is not None:
34
+ self.message = f"Could not find workflow run portal run id '{portal_run_id}', status '{status}'"
35
+ else:
36
+ self.message = "Could not find workflow"
37
+ super().__init__(self.message)
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python
2
+
3
+ """
4
+ Get workflows from library id
5
+ """
6
+
7
+ # Standard imports
8
+ from typing import List
9
+
10
+
11
+ # Local imports
12
+ from .requests_helpers import get_request_response_results
13
+ from .globals import WORKFLOW_RUN_ENDPOINT
14
+ from .models import WorkflowRunDetail
15
+
16
+
17
+ def get_workflows_from_library_id(library_id: str) -> List[WorkflowRunDetail]:
18
+ """
19
+ Use the query libraries__libraryId to get workflows from a library id
20
+ :param library_id:
21
+ :return:
22
+ """
23
+ return get_request_response_results(
24
+ WORKFLOW_RUN_ENDPOINT,
25
+ params={
26
+ "libraries__libraryId": library_id
27
+ }
28
+ )