pybiolib 0.2.951__py3-none-any.whl → 1.2.1890__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.
Files changed (262) hide show
  1. biolib/__init__.py +357 -11
  2. biolib/_data_record/data_record.py +380 -0
  3. biolib/_index/__init__.py +0 -0
  4. biolib/_index/index.py +55 -0
  5. biolib/_index/query_result.py +103 -0
  6. biolib/_internal/__init__.py +0 -0
  7. biolib/_internal/add_copilot_prompts.py +58 -0
  8. biolib/_internal/add_gui_files.py +81 -0
  9. biolib/_internal/data_record/__init__.py +1 -0
  10. biolib/_internal/data_record/data_record.py +85 -0
  11. biolib/_internal/data_record/push_data.py +116 -0
  12. biolib/_internal/data_record/remote_storage_endpoint.py +43 -0
  13. biolib/_internal/errors.py +5 -0
  14. biolib/_internal/file_utils.py +125 -0
  15. biolib/_internal/fuse_mount/__init__.py +1 -0
  16. biolib/_internal/fuse_mount/experiment_fuse_mount.py +209 -0
  17. biolib/_internal/http_client.py +159 -0
  18. biolib/_internal/lfs/__init__.py +1 -0
  19. biolib/_internal/lfs/cache.py +51 -0
  20. biolib/_internal/libs/__init__.py +1 -0
  21. biolib/_internal/libs/fusepy/__init__.py +1257 -0
  22. biolib/_internal/push_application.py +488 -0
  23. biolib/_internal/runtime.py +22 -0
  24. biolib/_internal/string_utils.py +13 -0
  25. biolib/_internal/templates/__init__.py +1 -0
  26. biolib/_internal/templates/copilot_template/.github/instructions/general-app-knowledge.instructions.md +10 -0
  27. biolib/_internal/templates/copilot_template/.github/instructions/style-general.instructions.md +20 -0
  28. biolib/_internal/templates/copilot_template/.github/instructions/style-python.instructions.md +16 -0
  29. biolib/_internal/templates/copilot_template/.github/instructions/style-react-ts.instructions.md +47 -0
  30. biolib/_internal/templates/copilot_template/.github/prompts/biolib_app_inputs.prompt.md +11 -0
  31. biolib/_internal/templates/copilot_template/.github/prompts/biolib_onboard_repo.prompt.md +19 -0
  32. biolib/_internal/templates/copilot_template/.github/prompts/biolib_run_apps.prompt.md +12 -0
  33. biolib/_internal/templates/dashboard_template/.biolib/config.yml +5 -0
  34. biolib/_internal/templates/github_workflow_template/.github/workflows/biolib.yml +21 -0
  35. biolib/_internal/templates/gitignore_template/.gitignore +10 -0
  36. biolib/_internal/templates/gui_template/.yarnrc.yml +1 -0
  37. biolib/_internal/templates/gui_template/App.tsx +53 -0
  38. biolib/_internal/templates/gui_template/Dockerfile +27 -0
  39. biolib/_internal/templates/gui_template/biolib-sdk.ts +82 -0
  40. biolib/_internal/templates/gui_template/dev-data/output.json +7 -0
  41. biolib/_internal/templates/gui_template/index.css +5 -0
  42. biolib/_internal/templates/gui_template/index.html +13 -0
  43. biolib/_internal/templates/gui_template/index.tsx +10 -0
  44. biolib/_internal/templates/gui_template/package.json +27 -0
  45. biolib/_internal/templates/gui_template/tsconfig.json +24 -0
  46. biolib/_internal/templates/gui_template/vite-plugin-dev-data.ts +50 -0
  47. biolib/_internal/templates/gui_template/vite.config.mts +10 -0
  48. biolib/_internal/templates/init_template/.biolib/config.yml +19 -0
  49. biolib/_internal/templates/init_template/Dockerfile +14 -0
  50. biolib/_internal/templates/init_template/requirements.txt +1 -0
  51. biolib/_internal/templates/init_template/run.py +12 -0
  52. biolib/_internal/templates/init_template/run.sh +4 -0
  53. biolib/_internal/templates/templates.py +25 -0
  54. biolib/_internal/tree_utils.py +106 -0
  55. biolib/_internal/utils/__init__.py +65 -0
  56. biolib/_internal/utils/auth.py +46 -0
  57. biolib/_internal/utils/job_url.py +33 -0
  58. biolib/_internal/utils/multinode.py +263 -0
  59. biolib/_runtime/runtime.py +157 -0
  60. biolib/_session/session.py +44 -0
  61. biolib/_shared/__init__.py +0 -0
  62. biolib/_shared/types/__init__.py +74 -0
  63. biolib/_shared/types/account.py +12 -0
  64. biolib/_shared/types/account_member.py +8 -0
  65. biolib/_shared/types/app.py +9 -0
  66. biolib/_shared/types/data_record.py +40 -0
  67. biolib/_shared/types/experiment.py +32 -0
  68. biolib/_shared/types/file_node.py +17 -0
  69. biolib/_shared/types/push.py +6 -0
  70. biolib/_shared/types/resource.py +37 -0
  71. biolib/_shared/types/resource_deploy_key.py +11 -0
  72. biolib/_shared/types/resource_permission.py +14 -0
  73. biolib/_shared/types/resource_version.py +19 -0
  74. biolib/_shared/types/result.py +14 -0
  75. biolib/_shared/types/typing.py +10 -0
  76. biolib/_shared/types/user.py +19 -0
  77. biolib/_shared/utils/__init__.py +7 -0
  78. biolib/_shared/utils/resource_uri.py +75 -0
  79. biolib/api/__init__.py +6 -0
  80. biolib/api/client.py +168 -0
  81. biolib/app/app.py +252 -49
  82. biolib/app/search_apps.py +45 -0
  83. biolib/biolib_api_client/api_client.py +126 -31
  84. biolib/biolib_api_client/app_types.py +24 -4
  85. biolib/biolib_api_client/auth.py +31 -8
  86. biolib/biolib_api_client/biolib_app_api.py +147 -52
  87. biolib/biolib_api_client/biolib_job_api.py +161 -141
  88. biolib/biolib_api_client/job_types.py +21 -5
  89. biolib/biolib_api_client/lfs_types.py +7 -23
  90. biolib/biolib_api_client/user_state.py +56 -0
  91. biolib/biolib_binary_format/__init__.py +1 -4
  92. biolib/biolib_binary_format/file_in_container.py +105 -0
  93. biolib/biolib_binary_format/module_input.py +24 -7
  94. biolib/biolib_binary_format/module_output_v2.py +149 -0
  95. biolib/biolib_binary_format/remote_endpoints.py +34 -0
  96. biolib/biolib_binary_format/remote_stream_seeker.py +59 -0
  97. biolib/biolib_binary_format/saved_job.py +3 -2
  98. biolib/biolib_binary_format/{attestation_document.py → stdout_and_stderr.py} +8 -8
  99. biolib/biolib_binary_format/system_status_update.py +3 -2
  100. biolib/biolib_binary_format/utils.py +175 -0
  101. biolib/biolib_docker_client/__init__.py +11 -2
  102. biolib/biolib_errors.py +36 -0
  103. biolib/biolib_logging.py +27 -10
  104. biolib/cli/__init__.py +38 -0
  105. biolib/cli/auth.py +46 -0
  106. biolib/cli/data_record.py +164 -0
  107. biolib/cli/index.py +32 -0
  108. biolib/cli/init.py +421 -0
  109. biolib/cli/lfs.py +101 -0
  110. biolib/cli/push.py +50 -0
  111. biolib/cli/run.py +63 -0
  112. biolib/cli/runtime.py +14 -0
  113. biolib/cli/sdk.py +16 -0
  114. biolib/cli/start.py +56 -0
  115. biolib/compute_node/cloud_utils/cloud_utils.py +110 -161
  116. biolib/compute_node/job_worker/cache_state.py +66 -88
  117. biolib/compute_node/job_worker/cache_types.py +1 -6
  118. biolib/compute_node/job_worker/docker_image_cache.py +112 -37
  119. biolib/compute_node/job_worker/executors/__init__.py +0 -3
  120. biolib/compute_node/job_worker/executors/docker_executor.py +532 -199
  121. biolib/compute_node/job_worker/executors/docker_types.py +9 -1
  122. biolib/compute_node/job_worker/executors/types.py +19 -9
  123. biolib/compute_node/job_worker/job_legacy_input_wait_timeout_thread.py +30 -0
  124. biolib/compute_node/job_worker/job_max_runtime_timer_thread.py +3 -5
  125. biolib/compute_node/job_worker/job_storage.py +108 -0
  126. biolib/compute_node/job_worker/job_worker.py +397 -212
  127. biolib/compute_node/job_worker/large_file_system.py +87 -38
  128. biolib/compute_node/job_worker/network_alloc.py +99 -0
  129. biolib/compute_node/job_worker/network_buffer.py +240 -0
  130. biolib/compute_node/job_worker/utilization_reporter_thread.py +197 -0
  131. biolib/compute_node/job_worker/utils.py +9 -24
  132. biolib/compute_node/remote_host_proxy.py +400 -98
  133. biolib/compute_node/utils.py +31 -9
  134. biolib/compute_node/webserver/compute_node_results_proxy.py +189 -0
  135. biolib/compute_node/webserver/proxy_utils.py +28 -0
  136. biolib/compute_node/webserver/webserver.py +130 -44
  137. biolib/compute_node/webserver/webserver_types.py +2 -6
  138. biolib/compute_node/webserver/webserver_utils.py +77 -12
  139. biolib/compute_node/webserver/worker_thread.py +183 -42
  140. biolib/experiments/__init__.py +0 -0
  141. biolib/experiments/experiment.py +356 -0
  142. biolib/jobs/__init__.py +1 -0
  143. biolib/jobs/job.py +741 -0
  144. biolib/jobs/job_result.py +185 -0
  145. biolib/jobs/types.py +50 -0
  146. biolib/py.typed +0 -0
  147. biolib/runtime/__init__.py +14 -0
  148. biolib/sdk/__init__.py +91 -0
  149. biolib/tables.py +34 -0
  150. biolib/typing_utils.py +2 -7
  151. biolib/user/__init__.py +1 -0
  152. biolib/user/sign_in.py +54 -0
  153. biolib/utils/__init__.py +162 -0
  154. biolib/utils/cache_state.py +94 -0
  155. biolib/utils/multipart_uploader.py +194 -0
  156. biolib/utils/seq_util.py +150 -0
  157. biolib/utils/zip/remote_zip.py +640 -0
  158. pybiolib-1.2.1890.dist-info/METADATA +41 -0
  159. pybiolib-1.2.1890.dist-info/RECORD +177 -0
  160. {pybiolib-0.2.951.dist-info → pybiolib-1.2.1890.dist-info}/WHEEL +1 -1
  161. pybiolib-1.2.1890.dist-info/entry_points.txt +2 -0
  162. README.md +0 -17
  163. biolib/app/app_result.py +0 -68
  164. biolib/app/utils.py +0 -62
  165. biolib/biolib-js/0-biolib.worker.js +0 -1
  166. biolib/biolib-js/1-biolib.worker.js +0 -1
  167. biolib/biolib-js/2-biolib.worker.js +0 -1
  168. biolib/biolib-js/3-biolib.worker.js +0 -1
  169. biolib/biolib-js/4-biolib.worker.js +0 -1
  170. biolib/biolib-js/5-biolib.worker.js +0 -1
  171. biolib/biolib-js/6-biolib.worker.js +0 -1
  172. biolib/biolib-js/index.html +0 -10
  173. biolib/biolib-js/main-biolib.js +0 -1
  174. biolib/biolib_api_client/biolib_account_api.py +0 -21
  175. biolib/biolib_api_client/biolib_large_file_system_api.py +0 -108
  176. biolib/biolib_binary_format/aes_encrypted_package.py +0 -42
  177. biolib/biolib_binary_format/module_output.py +0 -58
  178. biolib/biolib_binary_format/rsa_encrypted_aes_package.py +0 -57
  179. biolib/biolib_push.py +0 -114
  180. biolib/cli.py +0 -203
  181. biolib/cli_utils.py +0 -273
  182. biolib/compute_node/cloud_utils/enclave_parent_types.py +0 -7
  183. biolib/compute_node/enclave/__init__.py +0 -2
  184. biolib/compute_node/enclave/enclave_remote_hosts.py +0 -53
  185. biolib/compute_node/enclave/nitro_secure_module_utils.py +0 -64
  186. biolib/compute_node/job_worker/executors/base_executor.py +0 -18
  187. biolib/compute_node/job_worker/executors/pyppeteer_executor.py +0 -173
  188. biolib/compute_node/job_worker/executors/remote/__init__.py +0 -1
  189. biolib/compute_node/job_worker/executors/remote/nitro_enclave_utils.py +0 -81
  190. biolib/compute_node/job_worker/executors/remote/remote_executor.py +0 -51
  191. biolib/lfs.py +0 -196
  192. biolib/pyppeteer/.circleci/config.yml +0 -100
  193. biolib/pyppeteer/.coveragerc +0 -3
  194. biolib/pyppeteer/.gitignore +0 -89
  195. biolib/pyppeteer/.pre-commit-config.yaml +0 -28
  196. biolib/pyppeteer/CHANGES.md +0 -253
  197. biolib/pyppeteer/CONTRIBUTING.md +0 -26
  198. biolib/pyppeteer/LICENSE +0 -12
  199. biolib/pyppeteer/README.md +0 -137
  200. biolib/pyppeteer/docs/Makefile +0 -177
  201. biolib/pyppeteer/docs/_static/custom.css +0 -28
  202. biolib/pyppeteer/docs/_templates/layout.html +0 -10
  203. biolib/pyppeteer/docs/changes.md +0 -1
  204. biolib/pyppeteer/docs/conf.py +0 -299
  205. biolib/pyppeteer/docs/index.md +0 -21
  206. biolib/pyppeteer/docs/make.bat +0 -242
  207. biolib/pyppeteer/docs/reference.md +0 -211
  208. biolib/pyppeteer/docs/server.py +0 -60
  209. biolib/pyppeteer/poetry.lock +0 -1699
  210. biolib/pyppeteer/pyppeteer/__init__.py +0 -135
  211. biolib/pyppeteer/pyppeteer/accessibility.py +0 -286
  212. biolib/pyppeteer/pyppeteer/browser.py +0 -401
  213. biolib/pyppeteer/pyppeteer/browser_fetcher.py +0 -194
  214. biolib/pyppeteer/pyppeteer/command.py +0 -22
  215. biolib/pyppeteer/pyppeteer/connection/__init__.py +0 -242
  216. biolib/pyppeteer/pyppeteer/connection/cdpsession.py +0 -101
  217. biolib/pyppeteer/pyppeteer/coverage.py +0 -346
  218. biolib/pyppeteer/pyppeteer/device_descriptors.py +0 -787
  219. biolib/pyppeteer/pyppeteer/dialog.py +0 -79
  220. biolib/pyppeteer/pyppeteer/domworld.py +0 -597
  221. biolib/pyppeteer/pyppeteer/emulation_manager.py +0 -53
  222. biolib/pyppeteer/pyppeteer/errors.py +0 -48
  223. biolib/pyppeteer/pyppeteer/events.py +0 -63
  224. biolib/pyppeteer/pyppeteer/execution_context.py +0 -156
  225. biolib/pyppeteer/pyppeteer/frame/__init__.py +0 -299
  226. biolib/pyppeteer/pyppeteer/frame/frame_manager.py +0 -306
  227. biolib/pyppeteer/pyppeteer/helpers.py +0 -245
  228. biolib/pyppeteer/pyppeteer/input.py +0 -371
  229. biolib/pyppeteer/pyppeteer/jshandle.py +0 -598
  230. biolib/pyppeteer/pyppeteer/launcher.py +0 -683
  231. biolib/pyppeteer/pyppeteer/lifecycle_watcher.py +0 -169
  232. biolib/pyppeteer/pyppeteer/models/__init__.py +0 -103
  233. biolib/pyppeteer/pyppeteer/models/_protocol.py +0 -12460
  234. biolib/pyppeteer/pyppeteer/multimap.py +0 -82
  235. biolib/pyppeteer/pyppeteer/network_manager.py +0 -678
  236. biolib/pyppeteer/pyppeteer/options.py +0 -8
  237. biolib/pyppeteer/pyppeteer/page.py +0 -1728
  238. biolib/pyppeteer/pyppeteer/pipe_transport.py +0 -59
  239. biolib/pyppeteer/pyppeteer/target.py +0 -147
  240. biolib/pyppeteer/pyppeteer/task_queue.py +0 -24
  241. biolib/pyppeteer/pyppeteer/timeout_settings.py +0 -36
  242. biolib/pyppeteer/pyppeteer/tracing.py +0 -93
  243. biolib/pyppeteer/pyppeteer/us_keyboard_layout.py +0 -305
  244. biolib/pyppeteer/pyppeteer/util.py +0 -18
  245. biolib/pyppeteer/pyppeteer/websocket_transport.py +0 -47
  246. biolib/pyppeteer/pyppeteer/worker.py +0 -101
  247. biolib/pyppeteer/pyproject.toml +0 -97
  248. biolib/pyppeteer/spell.txt +0 -137
  249. biolib/pyppeteer/tox.ini +0 -72
  250. biolib/pyppeteer/utils/generate_protocol_types.py +0 -603
  251. biolib/start_cli.py +0 -7
  252. biolib/utils.py +0 -47
  253. biolib/validators/validate_app_version.py +0 -183
  254. biolib/validators/validate_argument.py +0 -134
  255. biolib/validators/validate_module.py +0 -323
  256. biolib/validators/validate_zip_file.py +0 -40
  257. biolib/validators/validator_utils.py +0 -103
  258. pybiolib-0.2.951.dist-info/LICENSE +0 -21
  259. pybiolib-0.2.951.dist-info/METADATA +0 -61
  260. pybiolib-0.2.951.dist-info/RECORD +0 -153
  261. pybiolib-0.2.951.dist-info/entry_points.txt +0 -3
  262. /LICENSE → /pybiolib-1.2.1890.dist-info/licenses/LICENSE +0 -0
@@ -1,21 +0,0 @@
1
- import requests
2
-
3
- from biolib.biolib_api_client.auth import BearerAuth
4
- from biolib.biolib_api_client import BiolibApiClient
5
- from biolib.biolib_errors import BioLibError
6
-
7
-
8
- class BiolibAccountApi:
9
-
10
- @staticmethod
11
- def fetch_by_handle(account_handle):
12
- response = requests.get(
13
- f'{BiolibApiClient.get().base_url}/api/account/{account_handle}',
14
- auth=BearerAuth(BiolibApiClient.get().access_token),
15
- timeout=5
16
- )
17
-
18
- if not response.ok:
19
- raise BioLibError(response.content.decode())
20
-
21
- return response.json()
@@ -1,108 +0,0 @@
1
- import requests
2
-
3
- from biolib.biolib_api_client.auth import BearerAuth
4
- from biolib.biolib_api_client import BiolibApiClient
5
- from biolib.biolib_api_client.lfs_types import LfsVersionPresignedUploadUrlResponse, LfsUploadPartMetadata, \
6
- LargeFileSystemVersion, LargeFileSystem, ZipProxyFileListResponse
7
- from biolib.biolib_errors import BioLibError
8
- from biolib.typing_utils import List
9
-
10
-
11
- class BiolibLargeFileSystemApi:
12
-
13
- @staticmethod
14
- def create(account_uuid: str, name: str) -> LargeFileSystem:
15
- response = requests.post(
16
- f'{BiolibApiClient.get().base_url}/api/lfs/',
17
- auth=BearerAuth(BiolibApiClient.get().access_token),
18
- timeout=5,
19
- json={'account_uuid': account_uuid, 'name': name}
20
- )
21
-
22
- if not response.ok:
23
- raise BioLibError(response.content.decode())
24
-
25
- lfs: LargeFileSystem = response.json()
26
- return lfs
27
-
28
- @staticmethod
29
- def fetch_version(lfs_version_uuid: str) -> LargeFileSystemVersion:
30
- response = requests.get(
31
- f'{BiolibApiClient.get().base_url}/api/lfs/versions/{lfs_version_uuid}/',
32
- auth=BearerAuth(BiolibApiClient.get().access_token),
33
- timeout=5,
34
- )
35
-
36
- if not response.ok:
37
- raise BioLibError(response.content.decode())
38
-
39
- lfs_version: LargeFileSystemVersion = response.json()
40
- return lfs_version
41
-
42
- @staticmethod
43
- def fetch_file_list(presigned_download_url: str) -> ZipProxyFileListResponse:
44
- base_url = BiolibApiClient.get().base_url
45
- if base_url == 'https://biolib.com':
46
- source_file_proxy_url = 'https://blbcdn.com/source-file-proxy'
47
- elif base_url == 'https://staging.biolib.com':
48
- source_file_proxy_url = 'https://staging.blbcdn.com/source-file-proxy'
49
- else:
50
- source_file_proxy_url = f'{base_url}/source-file-proxy'
51
-
52
- response = requests.post(
53
- f'{source_file_proxy_url}/files/',
54
- timeout=10,
55
- json={'zip_url': presigned_download_url},
56
- )
57
-
58
- if not response.ok:
59
- raise BioLibError(response.content.decode())
60
-
61
- response_dict: ZipProxyFileListResponse = response.json()
62
- return response_dict
63
-
64
- @staticmethod
65
- def create_version(resource_uuid: str) -> LargeFileSystemVersion:
66
- response = requests.post(
67
- f'{BiolibApiClient.get().base_url}/api/lfs/versions/',
68
- auth=BearerAuth(BiolibApiClient.get().access_token),
69
- json={'resource_uuid': resource_uuid},
70
- timeout=5,
71
- )
72
-
73
- if not response.ok:
74
- raise BioLibError(response.content.decode())
75
-
76
- lfs_version: LargeFileSystemVersion = response.json()
77
- return lfs_version
78
-
79
- @staticmethod
80
- def get_upload_url(resource_version_uuid: str, part_number: int) -> LfsVersionPresignedUploadUrlResponse:
81
- response = requests.get(
82
- f'{BiolibApiClient.get().base_url}/api/lfs/versions/{resource_version_uuid}/presigned_upload_url/',
83
- auth=BearerAuth(BiolibApiClient.get().access_token),
84
- params={'part_number': part_number},
85
- timeout=5,
86
- )
87
-
88
- if not response.ok:
89
- raise BioLibError(response.content.decode())
90
-
91
- presigned_upload_url_response: LfsVersionPresignedUploadUrlResponse = response.json()
92
- return presigned_upload_url_response
93
-
94
- @staticmethod
95
- def complete_upload(
96
- resource_version_uuid: str,
97
- parts: List[LfsUploadPartMetadata],
98
- size_bytes: int,
99
- ) -> None:
100
- response = requests.post(
101
- f'{BiolibApiClient.get().base_url}/api/lfs/versions/{resource_version_uuid}/complete_upload/',
102
- auth=BearerAuth(BiolibApiClient.get().access_token),
103
- json={'parts': parts, 'size_bytes': size_bytes},
104
- timeout=5,
105
- )
106
-
107
- if not response.ok:
108
- raise BioLibError(response.content.decode())
@@ -1,42 +0,0 @@
1
- from Crypto.Cipher import AES
2
-
3
- from biolib.biolib_binary_format.base_bbf_package import BioLibBinaryFormatBasePackage
4
-
5
-
6
- class AesEncryptedPackage(BioLibBinaryFormatBasePackage):
7
- def __init__(self, bbf=None):
8
- super().__init__(bbf)
9
- self.package_type = 7
10
- self.iv_len = 12
11
- self.tag_len = 16
12
-
13
- def decrypt(self, aes_key_buffer):
14
- iv, _, encrypted_data = self.deserialize()
15
- aes_key = AES.new(aes_key_buffer, AES.MODE_GCM, iv)
16
- return aes_key.decrypt(encrypted_data)
17
-
18
- def serialize(self, iv, tag, encrypted_data):
19
- bbf_data = bytearray()
20
- bbf_data.extend(self.version.to_bytes(1, 'big'))
21
- bbf_data.extend(self.package_type.to_bytes(1, 'big'))
22
-
23
- bbf_data.extend(iv)
24
- bbf_data.extend(tag)
25
-
26
- bbf_data.extend(len(encrypted_data).to_bytes(8, 'big'))
27
- bbf_data.extend(encrypted_data)
28
-
29
- return bbf_data
30
-
31
- def deserialize(self):
32
- version = self.get_data(1, output_type='int')
33
- package_type = self.get_data(1, output_type='int')
34
- self.check_version_and_type(version=version, package_type=package_type, expected_package_type=self.package_type)
35
-
36
- iv = self.get_data(self.iv_len)
37
- tag = self.get_data(self.tag_len)
38
-
39
- encrypted_data_len = self.get_data(8, output_type='int')
40
- encrypted_data = self.get_data(encrypted_data_len)
41
-
42
- return iv, tag, encrypted_data
@@ -1,58 +0,0 @@
1
- from biolib.biolib_binary_format.base_bbf_package import BioLibBinaryFormatBasePackage
2
-
3
-
4
- class ModuleOutput(BioLibBinaryFormatBasePackage):
5
- def __init__(self, bbf=None):
6
- super().__init__(bbf)
7
- self.package_type = 2
8
-
9
- def serialize(self, stdout, stderr, exit_code, files):
10
- bbf_data = bytearray()
11
- bbf_data.extend(self.version.to_bytes(1, 'big'))
12
- bbf_data.extend(self.package_type.to_bytes(1, 'big'))
13
-
14
- # Length of stdout and stderr
15
- bbf_data.extend(len(stdout).to_bytes(8, 'big'))
16
- bbf_data.extend(len(stderr).to_bytes(8, 'big'))
17
-
18
- file_data_len = sum([len(data) + len(path.encode()) for path, data in files.items()]) + (12 * len(files))
19
- bbf_data.extend(file_data_len.to_bytes(8, 'big'))
20
-
21
- bbf_data.extend(exit_code.to_bytes(2, 'big'))
22
- bbf_data.extend(stdout)
23
- bbf_data.extend(stderr)
24
-
25
- for path, data in files.items():
26
- # Path length and data length
27
- bbf_data.extend(len(path.encode()).to_bytes(4, 'big'))
28
- bbf_data.extend(len(data).to_bytes(8, 'big'))
29
-
30
- bbf_data.extend(path.encode())
31
- # The file data
32
- bbf_data.extend(data)
33
-
34
- return bbf_data
35
-
36
- def deserialize(self):
37
- version = self.get_data(1, output_type='int')
38
- package_type = self.get_data(1, output_type='int')
39
- self.check_version_and_type(version=version, package_type=package_type, expected_package_type=self.package_type)
40
-
41
- stdout_len = self.get_data(8, output_type='int')
42
- stderr_len = self.get_data(8, output_type='int')
43
- files_data_len = self.get_data(8, output_type='int')
44
- exit_code = self.get_data(2, output_type='int')
45
- stdout = self.get_data(stdout_len)
46
- stderr = self.get_data(stderr_len)
47
-
48
- end_of_files = self.pointer + files_data_len
49
- files = {}
50
-
51
- while self.pointer < end_of_files:
52
- path_len = self.get_data(4, output_type='int')
53
- data_len = self.get_data(8, output_type='int')
54
- path = self.get_data(path_len, output_type='str')
55
- data = self.get_data(data_len)
56
- files[path] = bytes(data)
57
-
58
- return {'stdout': stdout, 'stderr': stderr, 'exit_code': exit_code, 'files': files}
@@ -1,57 +0,0 @@
1
- from Crypto.Cipher import PKCS1_OAEP, AES
2
- from Crypto.PublicKey import RSA
3
- from Crypto.Random import get_random_bytes
4
- from Crypto.Hash import SHA256
5
-
6
- from biolib.biolib_binary_format.base_bbf_package import BioLibBinaryFormatBasePackage
7
-
8
-
9
- class RsaEncryptedAesPackage(BioLibBinaryFormatBasePackage):
10
- def __init__(self, bbf=None):
11
- super().__init__(bbf)
12
- self.package_type = 6
13
- self.iv_len = 12
14
- self.aes_key_len = 32
15
- self.tag_len = 16
16
-
17
- def create(self, rsa_public_key_der, unencrypted_bytes):
18
- public_key = RSA.import_key(rsa_public_key_der)
19
- rsa_cipher = PKCS1_OAEP.new(public_key, hashAlgo=SHA256)
20
-
21
- iv = get_random_bytes(self.iv_len)
22
- aes_key_buffer = get_random_bytes(self.aes_key_len)
23
- aes_key = AES.new(aes_key_buffer, AES.MODE_GCM, iv)
24
- rsa_encrypted_aes_key_buffer = rsa_cipher.encrypt(aes_key_buffer)
25
- aes_encrypted_data, tag = aes_key.encrypt_and_digest(bytes(unencrypted_bytes))
26
-
27
- return self.serialize(rsa_encrypted_aes_key_buffer, iv, tag, aes_encrypted_data), aes_key_buffer
28
-
29
- def serialize(self, encrypted_aes_key, iv, tag, encrypted_data):
30
- bbf_data = bytearray()
31
- bbf_data.extend(self.version.to_bytes(1, 'big'))
32
- bbf_data.extend(self.package_type.to_bytes(1, 'big'))
33
-
34
- bbf_data.extend(len(encrypted_aes_key).to_bytes(2, 'big'))
35
- bbf_data.extend(encrypted_aes_key)
36
- bbf_data.extend(iv)
37
- bbf_data.extend(tag)
38
-
39
- bbf_data.extend(len(encrypted_data).to_bytes(8, 'big'))
40
- bbf_data.extend(encrypted_data)
41
-
42
- return bbf_data
43
-
44
- def deserialize(self):
45
- version = self.get_data(1, output_type='int')
46
- package_type = self.get_data(1, output_type='int')
47
- self.check_version_and_type(version=version, package_type=package_type, expected_package_type=self.package_type)
48
-
49
- encrypted_aes_key_len = self.get_data(2, output_type='int')
50
- encrypted_aes_key = self.get_data(encrypted_aes_key_len)
51
- iv = self.get_data(self.iv_len)
52
- tag = self.get_data(self.tag_len)
53
-
54
- encrypted_data_len = self.get_data(8, output_type='int')
55
- encrypted_data = self.get_data(encrypted_data_len)
56
-
57
- return encrypted_aes_key, iv, tag, encrypted_data
biolib/biolib_push.py DELETED
@@ -1,114 +0,0 @@
1
- from pathlib import Path
2
- import yaml
3
-
4
- from biolib import cli_utils
5
- from biolib.biolib_api_client import BiolibApiClient
6
- from biolib.biolib_docker_client import BiolibDockerClient
7
- from biolib.biolib_api_client.biolib_app_api import BiolibAppApi
8
- from biolib.biolib_errors import BioLibError
9
- from biolib.biolib_logging import logger
10
- from biolib.utils import get_absolute_container_image_uri
11
-
12
-
13
- def push_application(app_uri: str, app_path: str):
14
- api_client = BiolibApiClient.get()
15
- if not api_client.is_signed_in:
16
- # TODO: Create an exception class for expected errors like this that does not print stacktrace
17
- raise Exception(
18
- 'You must be authenticated to push an application.\n'
19
- 'Please set the environment variable "BIOLIB_TOKEN=[your_api_token]"\n'
20
- 'You can get an API token at: https://biolib.com/settings/api-tokens/'
21
- ) from None
22
-
23
- # prepare zip file
24
- if not Path(f'{app_path}/.biolib/config.yml').is_file():
25
- raise BioLibError('The file .biolib/config.yml was not found in the application directory')
26
-
27
- tmp_directory, source_files_zip_path = cli_utils.create_temporary_directory_with_source_files_zip(app_path)
28
-
29
- try:
30
- with open(source_files_zip_path, mode='rb') as zip_file:
31
- source_files_zip_bytes = zip_file.read()
32
- except IOError:
33
- raise Exception('Failed to read temporary source files zip') from None
34
-
35
- try:
36
- tmp_directory.cleanup()
37
- except IOError:
38
- raise Exception('Failed to clean up temporary source files zip directory') from None
39
-
40
- # TODO: Raise exception if app_uri contains version
41
- app_response = BiolibAppApi.get_by_uri(app_uri)
42
- app = app_response['app']
43
- # push new app version
44
- new_app_version_json = BiolibAppApi.push_app_version(
45
- app_id=app['public_id'],
46
- app_name=app['name'],
47
- author=app['account_handle'],
48
- set_as_active=False,
49
- zip_binary=source_files_zip_bytes,
50
- )
51
-
52
- docker_tags = new_app_version_json.get('docker_tags', {})
53
- if docker_tags:
54
- logger.info('Found docker images to push.')
55
-
56
- try:
57
- yaml_file = open(f'{app_path}/.biolib/config.yml', 'r', encoding='utf-8')
58
-
59
- except Exception as error: # pylint: disable=broad-except
60
- raise BioLibError('Could not open the config file .biolib/config.yml') from error
61
-
62
- try:
63
- config_data = yaml.safe_load(yaml_file)
64
-
65
- except Exception as error: # pylint: disable=broad-except
66
- raise BioLibError('Could not parse .biolib/config.yml. Please make sure it is valid YAML') from error
67
-
68
- # Auth to be sent to proxy
69
- # The tokens are sent as "{access_token},{job_id}". We leave job_id blank on push.
70
- tokens = f'{BiolibApiClient.get().access_token},'
71
- auth_config = {'username': 'biolib', 'password': tokens}
72
-
73
- docker_client = BiolibDockerClient.get_docker_client()
74
-
75
- for module_name, repo_and_tag in docker_tags.items():
76
- docker_image_definition = config_data['modules'][module_name]['image']
77
- repo, tag = repo_and_tag.split(':')
78
-
79
- if docker_image_definition.startswith('dockerhub://'):
80
- docker_image_name = docker_image_definition.replace('dockerhub://', 'docker.io/', 1)
81
- logger.info(
82
- f'Pulling image {docker_image_name} defined on module {module_name} from Dockerhub.')
83
- dockerhub_repo, dockerhub_tag = docker_image_name.split(':')
84
- docker_client.images.pull(dockerhub_repo, tag=dockerhub_tag)
85
-
86
- elif docker_image_definition.startswith('local-docker://'):
87
- docker_image_name = docker_image_definition.replace('local-docker://', '', 1)
88
-
89
- try:
90
- logger.info(f'Trying to push image {docker_image_name} defined on module {module_name}.')
91
- image = docker_client.images.get(docker_image_name)
92
- image_uri = get_absolute_container_image_uri(
93
- base_url=api_client.base_url,
94
- relative_image_uri=repo
95
- )
96
- image.tag(image_uri, tag)
97
- for line in docker_client.images.push(image_uri, tag=tag, stream=True,
98
- decode=True, auth_config=auth_config):
99
- logger.info(line)
100
-
101
- except Exception as exception: # pylint: disable=broad-except
102
- raise BioLibError(f'Failed to tag and push image {docker_image_name}.') from exception
103
-
104
- logger.info(f'Successfully pushed {docker_image_name}')
105
-
106
- logger.info('Successfully pushed all docker images')
107
-
108
- # Set new app version as active
109
- BiolibAppApi.update_app_version(
110
- app_version_id=new_app_version_json['public_id'],
111
- data={
112
- 'set_as_active': True
113
- }
114
- )
biolib/cli.py DELETED
@@ -1,203 +0,0 @@
1
- import argparse
2
- import logging
3
- import os
4
- import sys
5
- import platform
6
-
7
- from docker.errors import ImageNotFound # type: ignore
8
-
9
- from biolib import cli_utils, utils, biolib_errors
10
- from biolib.app import BioLibApp
11
- from biolib.app.utils import run_job
12
- from biolib.biolib_push import push_application
13
- from biolib.biolib_api_client import Job
14
- from biolib.biolib_binary_format import ModuleInput
15
- from biolib.cli_utils import BiolibValidationError
16
- from biolib.validators.validate_zip_file import validate_zip_file # type: ignore
17
- from biolib.biolib_docker_client import BiolibDockerClient
18
- from biolib.biolib_logging import logger
19
- from biolib.lfs import create_large_file_system, push_large_file_system, describe_large_file_system
20
-
21
-
22
- class IllegalArgumentError(ValueError):
23
- pass
24
-
25
-
26
- def file_path(path):
27
- if path.startswith('/'):
28
- full_path = path
29
- else:
30
- full_path = os.path.normpath(os.path.join(os.getcwd(), path))
31
- if not os.path.exists(full_path):
32
- raise IllegalArgumentError(f'The path {full_path} does not exist')
33
- return full_path
34
-
35
-
36
- def port_number(port):
37
- if not port.isdigit():
38
- raise IllegalArgumentError(f'Port number {port} is not a number. Ports can only be numbers')
39
-
40
- if not (0 < int(port) < 65000): # pylint: disable=superfluous-parens
41
- raise IllegalArgumentError('Port can only be between 0 and 65000')
42
-
43
- return port
44
-
45
-
46
- def main():
47
- # set more restrictive default log level for CLI
48
- logger.configure(default_log_level=logging.WARNING)
49
-
50
- def _get_stdin():
51
- stdin = None
52
- if not sys.stdin.isatty() and not utils.IS_DEV:
53
- stdin = sys.stdin.read()
54
- return stdin
55
-
56
- if len(sys.argv) > 2 and sys.argv[1] == 'run':
57
- try:
58
- app = BioLibApp(uri=sys.argv[2])
59
- except biolib_errors.BioLibError as error:
60
- print(f'An error occurred:\n {error.message}', file=sys.stderr)
61
- sys.exit(1)
62
-
63
- app_args = sys.argv[3:]
64
- result = app.cli(args=app_args, stdin=_get_stdin(), files=None)
65
- result.save_files('biolib_results')
66
- sys.stdout.buffer.write(result.stdout)
67
- sys.stderr.buffer.write(result.stderr)
68
- sys.exit(result.exitcode)
69
-
70
- elif len(sys.argv) > 2 and sys.argv[1] == 'run-dev':
71
- provided_app_path = sys.argv[2]
72
- app_path = cli_utils.validate_and_get_app_path(provided_app_path)
73
- logger.info(f'Running BioLib application in local directory {app_path}...')
74
- tmp_directory, source_files_zip_path = cli_utils.create_temporary_directory_with_source_files_zip(app_path)
75
-
76
- try:
77
- validate_zip_file(source_files_zip_path, app_path)
78
- yaml_data = cli_utils.get_yaml_data(app_path)
79
- cli_utils.validate_yaml_config(yaml_data, source_files_zip_path)
80
- app_version_mocked = cli_utils.get_mocked_app_version_from_yaml(yaml_data, source_files_zip_path)
81
-
82
- for module in app_version_mocked['modules']:
83
- try:
84
- BiolibDockerClient.get_docker_client().images.get(module['image_uri'])
85
- except ImageNotFound:
86
- raise Exception(
87
- f"Could not find local docker image {module['image_uri']} specified in .biolib/config.yml"
88
- ) from None
89
-
90
- app_args = sys.argv[3:]
91
- args = cli_utils.validate_and_get_args(app_args)
92
- files_dict, args = cli_utils.get_files_dict_and_file_args(files=None, args=args)
93
-
94
- module_input_serialized = ModuleInput().serialize(
95
- stdin=_get_stdin() or b'',
96
- files=files_dict,
97
- arguments=args,
98
- )
99
-
100
- module_output = run_job(
101
- module_input_serialized=module_input_serialized,
102
- job=Job(
103
- app_version=app_version_mocked,
104
- caller_job=None,
105
- created_at='',
106
- public_id=utils.RUN_DEV_JOB_ID,
107
- remote_hosts_with_warning=[],
108
- user_id=None,
109
- ),
110
- )
111
-
112
- cli_utils.write_output_files(module_output['files'])
113
-
114
- print(cli_utils.get_pretty_print_module_output_string(
115
- exitcode=module_output['exit_code'],
116
- stderr=module_output['stderr'],
117
- stdout=module_output['stdout'],
118
- ))
119
-
120
- except Exception as exception:
121
- # Exit on BiolibValidationError as we have already printed the validation errors
122
- if isinstance(exception, BiolibValidationError):
123
- logger.error('Validation check failed for config file at .biolib/config.yml')
124
- sys.exit(1)
125
- raise exception
126
-
127
- finally:
128
- try:
129
- tmp_directory.cleanup()
130
- except IOError:
131
- logger.error('Failed to clean up temporary source files zip directory')
132
-
133
- else:
134
- parser = argparse.ArgumentParser()
135
- parser.add_argument('--version', action='version', version=utils.BIOLIB_PACKAGE_VERSION)
136
-
137
- subparsers = parser.add_subparsers(help='command', dest='command')
138
-
139
- # Add subparser for run to help message makes sense
140
- # The actual code for running applications is above this
141
- _parser_run = subparsers.add_parser('run', help='Run an application on BioLib')
142
-
143
- # Add subparser for run to help message makes sense
144
- # The actual code for running local applications is above this
145
- _parser_run_dev = subparsers.add_parser('run-dev', help='Run an application from a local directory')
146
-
147
- # add subparser for push
148
- parser_push = subparsers.add_parser('push', help='Push an application to BioLib')
149
- parser_push.add_argument('app_uri')
150
- parser_push.add_argument('--path', default='.', required=False)
151
-
152
- # add subparser for run-compute-node
153
- parser_start = subparsers.add_parser('start', help='Start a compute node')
154
- parser_start.add_argument('--port', default='5000', required=False, type=port_number)
155
- parser_start.add_argument('--host', default='127.0.0.1', required=False)
156
-
157
- # add subparser for lfs
158
- parser_lfs = subparsers.add_parser('lfs', help='Work with large file systems')
159
- subparsers_lfs = parser_lfs.add_subparsers(help='lfs command', dest='lfs_command')
160
-
161
- parser_lfs_create = subparsers_lfs.add_parser('create', help='Create a large filesystem')
162
- parser_lfs_create.add_argument('lfs_uri', type=str)
163
-
164
- parser_lfs_push = subparsers_lfs.add_parser('push', help='Push data to a large filesystem')
165
- parser_lfs_push.add_argument('lfs_uri', type=str)
166
- parser_lfs_push.add_argument('--path', type=str)
167
-
168
- parser_lfs_push = subparsers_lfs.add_parser('describe', help='Describe a large filesystem')
169
- parser_lfs_push.add_argument('lfs_uri', type=str)
170
- parser_lfs_push.add_argument('--json', action='store_true')
171
-
172
- args = parser.parse_args()
173
-
174
- if args.command == 'push':
175
- logger.configure(default_log_level=logging.INFO)
176
- push_application(args.app_uri, args.path)
177
-
178
- elif args.command == 'start':
179
- logger.configure(default_log_level=logging.INFO)
180
- if platform.system() == 'Windows':
181
- raise Exception('Starting a compute node is currently not supported on Windows')
182
-
183
- from biolib.compute_node.webserver import webserver # pylint: disable=import-outside-toplevel
184
- webserver.start_webserver(host=args.host, port=args.port)
185
-
186
- elif args.command == 'lfs':
187
- if args.lfs_command == 'create':
188
- logger.configure(default_log_level=logging.INFO)
189
- create_large_file_system(lfs_uri=args.lfs_uri)
190
- elif args.lfs_command == 'push':
191
- logger.configure(default_log_level=logging.INFO)
192
- push_large_file_system(lfs_uri=args.lfs_uri, input_dir=args.path)
193
- elif args.lfs_command == 'describe':
194
- describe_large_file_system(lfs_uri=args.lfs_uri, output_as_json=args.json)
195
-
196
- else:
197
- print('Unrecognized command, please run biolib --help to see available options.')
198
- sys.exit(1)
199
-
200
-
201
- # allow this script to be called without poetry in dev e.g. by an IDE debugger
202
- if utils.IS_DEV and __name__ == '__main__':
203
- main()