odm-processors-sdk 1.65.0__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.
- odm_processors_sdk/__init__.py +0 -0
- odm_processors_sdk/transformations/__init__.py +0 -0
- odm_processors_sdk/transformations/api.py +176 -0
- odm_processors_sdk/transformations/client.py +13 -0
- odm_processors_sdk/transformations/configuration.py +22 -0
- odm_processors_sdk/transformations/environment.py +29 -0
- odm_processors_sdk/transformations/logger.py +25 -0
- odm_processors_sdk/transformations/tmp.py +14 -0
- odm_processors_sdk/transformations/util.py +56 -0
- odm_processors_sdk-1.65.0.dist-info/METADATA +8 -0
- odm_processors_sdk-1.65.0.dist-info/RECORD +13 -0
- odm_processors_sdk-1.65.0.dist-info/WHEEL +5 -0
- odm_processors_sdk-1.65.0.dist-info/top_level.txt +1 -0
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import odm_api
|
|
2
|
+
from . import client
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def data_import() -> (
|
|
6
|
+
odm_api.api.data_import_via_direct_file_upload_api.DataImportViaDirectFileUploadApi
|
|
7
|
+
):
|
|
8
|
+
"""
|
|
9
|
+
Get an instance of the Data Import Jobs API.
|
|
10
|
+
"""
|
|
11
|
+
c = client.get()
|
|
12
|
+
return odm_api.api.data_import_via_direct_file_upload_api.DataImportViaDirectFileUploadApi(
|
|
13
|
+
c
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def job_operations() -> odm_api.api.job_operations_api.JobOperationsApi:
|
|
18
|
+
"""
|
|
19
|
+
Get an instance of the Job Operations API.
|
|
20
|
+
"""
|
|
21
|
+
c = client.get()
|
|
22
|
+
return odm_api.api.job_operations_api.JobOperationsApi(c)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def file() -> odm_api.api.files_as_curator_api.FilesAsCuratorApi:
|
|
26
|
+
"""
|
|
27
|
+
Get an instance of the Files As Curator API.
|
|
28
|
+
"""
|
|
29
|
+
c = client.get()
|
|
30
|
+
return odm_api.api.files_as_curator_api.FilesAsCuratorApi(c)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def sample() -> odm_api.api.sample_spo_tas_curator_api.SampleSPoTAsCuratorApi:
|
|
34
|
+
"""
|
|
35
|
+
Get an instance of the SampleSPoT As Curator API.
|
|
36
|
+
"""
|
|
37
|
+
c = client.get()
|
|
38
|
+
return odm_api.api.sample_spo_tas_curator_api.SampleSPoTAsCuratorApi(c)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def library() -> odm_api.api.library_spo_tas_curator_api.LibrarySPoTAsCuratorApi:
|
|
42
|
+
"""
|
|
43
|
+
Get an instance of the LibrarySPoT As Curator API.
|
|
44
|
+
"""
|
|
45
|
+
c = client.get()
|
|
46
|
+
return odm_api.api.library_spo_tas_curator_api.LibrarySPoTAsCuratorApi(c)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def preparation() -> (
|
|
50
|
+
odm_api.api.preparation_spo_tas_curator_api.PreparationSPoTAsCuratorApi
|
|
51
|
+
):
|
|
52
|
+
"""
|
|
53
|
+
Get an instance of the PreparationSPoT As Curator API.
|
|
54
|
+
"""
|
|
55
|
+
c = client.get()
|
|
56
|
+
return odm_api.api.preparation_spo_tas_curator_api.PreparationSPoTAsCuratorApi(c)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def cells() -> odm_api.api.cells_as_curator_api.CellsAsCuratorApi:
|
|
60
|
+
"""
|
|
61
|
+
Get an instance of the Cells As Curator API.
|
|
62
|
+
"""
|
|
63
|
+
c = client.get()
|
|
64
|
+
return odm_api.api.cells_as_curator_api.CellsAsCuratorApi(c)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def expression() -> (
|
|
68
|
+
odm_api.api.expression_spo_tas_curator_api.ExpressionSPoTAsCuratorApi
|
|
69
|
+
):
|
|
70
|
+
"""
|
|
71
|
+
Get an instance of the ExpressionSPoT As Curator API.
|
|
72
|
+
"""
|
|
73
|
+
c = client.get()
|
|
74
|
+
return odm_api.api.expression_spo_tas_curator_api.ExpressionSPoTAsCuratorApi(c)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def study_integration() -> (
|
|
78
|
+
odm_api.api.study_integration_as_curator_api.StudyIntegrationAsCuratorApi
|
|
79
|
+
):
|
|
80
|
+
"""
|
|
81
|
+
Get an instance of the Study Integration As Curator API.
|
|
82
|
+
"""
|
|
83
|
+
c = client.get()
|
|
84
|
+
return odm_api.api.study_integration_as_curator_api.StudyIntegrationAsCuratorApi(c)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def sample_integration() -> (
|
|
88
|
+
odm_api.api.sample_integration_as_curator_api.SampleIntegrationAsCuratorApi
|
|
89
|
+
):
|
|
90
|
+
"""
|
|
91
|
+
Get an instance of the Sample Integration As Curator API.
|
|
92
|
+
"""
|
|
93
|
+
c = client.get()
|
|
94
|
+
return odm_api.api.sample_integration_as_curator_api.SampleIntegrationAsCuratorApi(
|
|
95
|
+
c
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def library_integration() -> (
|
|
100
|
+
odm_api.api.library_integration_as_curator_api.LibraryIntegrationAsCuratorApi
|
|
101
|
+
):
|
|
102
|
+
"""
|
|
103
|
+
Get an instance of the Library Integration As Curator API.
|
|
104
|
+
"""
|
|
105
|
+
c = client.get()
|
|
106
|
+
return (
|
|
107
|
+
odm_api.api.library_integration_as_curator_api.LibraryIntegrationAsCuratorApi(c)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def preparation_integration() -> (
|
|
112
|
+
odm_api.api.preparation_integration_as_curator_api.PreparationIntegrationAsCuratorApi
|
|
113
|
+
):
|
|
114
|
+
"""
|
|
115
|
+
Get an instance of the Preparation Integration As Curator API.
|
|
116
|
+
"""
|
|
117
|
+
c = client.get()
|
|
118
|
+
return odm_api.api.preparation_integration_as_curator_api.PreparationIntegrationAsCuratorApi(
|
|
119
|
+
c
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def cell_integration() -> (
|
|
124
|
+
odm_api.api.cell_integration_as_curator_api.CellIntegrationAsCuratorApi
|
|
125
|
+
):
|
|
126
|
+
"""
|
|
127
|
+
Get an instance of the Cell Integration As Curator API.
|
|
128
|
+
"""
|
|
129
|
+
c = client.get()
|
|
130
|
+
return odm_api.api.cell_integration_as_curator_api.CellIntegrationAsCuratorApi(c)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def expression_integration() -> (
|
|
134
|
+
odm_api.api.expression_integration_as_curator_api.ExpressionIntegrationAsCuratorApi
|
|
135
|
+
):
|
|
136
|
+
"""
|
|
137
|
+
Get an instance of the Expression Integration As Curator API.
|
|
138
|
+
"""
|
|
139
|
+
c = client.get()
|
|
140
|
+
return odm_api.api.expression_integration_as_curator_api.ExpressionIntegrationAsCuratorApi(
|
|
141
|
+
c
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def variant_integration() -> (
|
|
146
|
+
odm_api.api.variant_integration_as_curator_api.VariantIntegrationAsCuratorApi
|
|
147
|
+
):
|
|
148
|
+
"""
|
|
149
|
+
Get an instance of the Variant Integration As Curator API.
|
|
150
|
+
"""
|
|
151
|
+
c = client.get()
|
|
152
|
+
return (
|
|
153
|
+
odm_api.api.variant_integration_as_curator_api.VariantIntegrationAsCuratorApi(c)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def flow_cytometry_facs_integration() -> (
|
|
158
|
+
odm_api.api.flow_cytometry_facs_integration_as_curator_api.FlowCytometryFACSIntegrationAsCuratorApi
|
|
159
|
+
):
|
|
160
|
+
"""
|
|
161
|
+
Get an instance of the Flow Cytometry FACS Integration As Curator API.
|
|
162
|
+
"""
|
|
163
|
+
c = client.get()
|
|
164
|
+
return odm_api.api.flow_cytometry_facs_integration_as_curator_api.FlowCytometryFACSIntegrationAsCuratorApi(
|
|
165
|
+
c
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def omics_queries() -> (
|
|
170
|
+
odm_api.api.omics_queries_as_curator_api.OmicsQueriesAsCuratorApi
|
|
171
|
+
):
|
|
172
|
+
"""
|
|
173
|
+
Get an instance of the Omics Queries As Curator API.
|
|
174
|
+
"""
|
|
175
|
+
c = client.get()
|
|
176
|
+
return odm_api.api.omics_queries_as_curator_api.OmicsQueriesAsCuratorApi(c)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import odm_api
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get() -> odm_api.ApiClient:
|
|
7
|
+
"""
|
|
8
|
+
Create and configure an API client for ODM API.
|
|
9
|
+
"""
|
|
10
|
+
c = odm_api.ApiClient.get_default()
|
|
11
|
+
c.configuration.host = os.environ["ODM_URL"]
|
|
12
|
+
c.default_headers["Genestack-API-Token"] = os.environ["GENESTACK_API_TOKEN"]
|
|
13
|
+
return c
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def read():
|
|
7
|
+
config_path = os.environ.get("CONFIGURATION_PATH")
|
|
8
|
+
|
|
9
|
+
if not config_path:
|
|
10
|
+
logging.warning("CONFIGURATION_PATH environment variable is not set")
|
|
11
|
+
return None
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
with open(config_path, "r") as file:
|
|
15
|
+
return json.load(file)
|
|
16
|
+
except FileNotFoundError:
|
|
17
|
+
logging.warning(f"Configuration file not found at: {config_path}")
|
|
18
|
+
return None
|
|
19
|
+
except json.JSONDecodeError as e:
|
|
20
|
+
raise json.JSONDecodeError(f"Invalid JSON in configuration file: {e}")
|
|
21
|
+
except Exception as e:
|
|
22
|
+
raise Exception(f"Error reading configuration file: {e}")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def input_accessions() -> list[str] | None:
|
|
5
|
+
return os.environ.get("INPUT_ACCESSIONS").split(",")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def dry_run() -> bool | None:
|
|
9
|
+
return os.environ.get("DRY_RUN").lower() == "true"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def image_name() -> str:
|
|
13
|
+
return os.environ.get("IMAGE_NAME")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def image_version() -> str:
|
|
17
|
+
return os.environ.get("IMAGE_VERSION")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def configuration_id() -> str:
|
|
21
|
+
return os.environ.get("CONFIGURATION_ID")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def configuration_version() -> str:
|
|
25
|
+
return os.environ.get("CONFIGURATION_VERSION")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def job_id() -> str:
|
|
29
|
+
return os.environ.get("JOB_ID")
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import sys
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
from loguru import logger
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def make_sink(destination):
|
|
9
|
+
def strip_text_sink(message):
|
|
10
|
+
obj = json.loads(message)
|
|
11
|
+
obj.pop("text", None)
|
|
12
|
+
destination.write(json.dumps(obj) + "\n")
|
|
13
|
+
|
|
14
|
+
return strip_text_sink
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def log():
|
|
18
|
+
logger.remove()
|
|
19
|
+
logger.add(make_sink(sys.stdout), level="INFO", serialize=True)
|
|
20
|
+
warnings.showwarning = (
|
|
21
|
+
lambda message, category, filename, lineno, *args, **kwargs: logger.warning(
|
|
22
|
+
f"{category.__name__} ({filename}:{lineno}): {message}"
|
|
23
|
+
)
|
|
24
|
+
)
|
|
25
|
+
return logger
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import tempfile
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def directory_prefix() -> str | None:
|
|
7
|
+
return os.environ.get("TEMPORARY_DIRECTORY")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def directory():
|
|
11
|
+
"""
|
|
12
|
+
Create a temporary directory using TEMPORARY_DIRECTORY environment variable as prefix.
|
|
13
|
+
"""
|
|
14
|
+
return tempfile.TemporaryDirectory(dir=directory_prefix())
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
from . import api
|
|
4
|
+
from . import logger
|
|
5
|
+
|
|
6
|
+
log = logger.log()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def wait_job(job_exec_id):
|
|
10
|
+
"""
|
|
11
|
+
Wait for a job to complete.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
while True:
|
|
15
|
+
info = api.job_operations().info(job_exec_id)
|
|
16
|
+
if info.status in ("COMPLETED", "FAILED"):
|
|
17
|
+
break
|
|
18
|
+
log.info(f"Job status: {info.status}")
|
|
19
|
+
time.sleep(15)
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# TODO: It should use stream instead of bytes
|
|
24
|
+
def retrieve_attachment_content(accession: str) -> bytes:
|
|
25
|
+
"""
|
|
26
|
+
Retrieve CSV content from a file with the specified accession.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
bytes: The content of the CSV file as bytes.
|
|
30
|
+
"""
|
|
31
|
+
return api.file().get_file_as_curator(accession)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def write_attachment_file(
|
|
35
|
+
accession: str, output_file: str, chunk_size: int = 65536
|
|
36
|
+
) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Write the attachment content to the specified output file by chunks.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
accession: The accession of the attachment file.
|
|
42
|
+
output_file: The path to the output file.
|
|
43
|
+
chunk_size: The chunk size to read the file in. Default is 65536 bytes (64 KB).
|
|
44
|
+
"""
|
|
45
|
+
with api.file().get_file_as_curator_without_preload_content(accession) as response:
|
|
46
|
+
with open(output_file, "wb") as file:
|
|
47
|
+
while True:
|
|
48
|
+
chunk = response.read(chunk_size)
|
|
49
|
+
if not chunk:
|
|
50
|
+
break
|
|
51
|
+
file.write(chunk)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def find_study_accession_from_attachment_accession(accession: str) -> str:
|
|
55
|
+
study = api.study_integration().get_study_by_file_as_curator(accession)
|
|
56
|
+
return study["genestack:accession"]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: odm-processors-sdk
|
|
3
|
+
Version: 1.65.0
|
|
4
|
+
Summary: Software development kit for all of the processors in ODM (transformations, connectors, etc.)
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: odm-api==1.65.0
|
|
8
|
+
Requires-Dist: loguru==0.7.3
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
odm_processors_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
odm_processors_sdk/transformations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
odm_processors_sdk/transformations/api.py,sha256=_b3GGHMdZKoe6VJhD9MyRi3IzEiLbE2RE_b0Jxs24zg,4994
|
|
4
|
+
odm_processors_sdk/transformations/client.py,sha256=tai9MstMVFa9HvFoVQyQUmMPV_TqG-pjKbl17bs5Hrw,311
|
|
5
|
+
odm_processors_sdk/transformations/configuration.py,sha256=RSMxJGZ8OAroutZuHo02R7PaoalkdZu5L6kS5xJ0Mwg,654
|
|
6
|
+
odm_processors_sdk/transformations/environment.py,sha256=soI1OgLkGvBFx9PXJE-FudBqhzRV9KyGb2G7FP_XGlU,567
|
|
7
|
+
odm_processors_sdk/transformations/logger.py,sha256=zfKZdXy2Cj2PyAQ7lOSJP7jdMmRyZ_-5MiGvqXGjwZo,589
|
|
8
|
+
odm_processors_sdk/transformations/tmp.py,sha256=L8PW9olVEjCu6V_zAqLiE4j_N8yVlv8OHHTPOVVfsAA,305
|
|
9
|
+
odm_processors_sdk/transformations/util.py,sha256=pkDEraAN-yNfhb_66zcQqykPJLchO38gD41RpBYXUzY,1567
|
|
10
|
+
odm_processors_sdk-1.65.0.dist-info/METADATA,sha256=buPyTI0WWPSvO0xKWa8Shzm_PdkQ0XYZVSOLOnXS7Mo,290
|
|
11
|
+
odm_processors_sdk-1.65.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
12
|
+
odm_processors_sdk-1.65.0.dist-info/top_level.txt,sha256=pMgCWxFau9Si-S-jGP42_c-KBd-nP-1rq3vFJMEacoc,19
|
|
13
|
+
odm_processors_sdk-1.65.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
odm_processors_sdk
|