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,53 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """Emulation Manager module."""
5
- import asyncio
6
-
7
- from biolib.pyppeteer.pyppeteer.connection import CDPSession
8
- from biolib.pyppeteer.pyppeteer.models import Protocol
9
-
10
-
11
- class EmulationManager:
12
- """EmulationManager class."""
13
-
14
- def __init__(self, client: CDPSession) -> None:
15
- """Make new emulation manager."""
16
- self._client = client
17
- self._emulatingMobile = False
18
- self._hasTouch = False
19
- self._emulatingMobile = False
20
-
21
- async def emulateViewport(self, viewport: Protocol.Page.Viewport) -> bool:
22
- """
23
- Evaluate viewport.
24
- :param viewport: dictionary which supports keys: isMobile, width, height,
25
- deviceScaleFactor, isLandscape, hasTouch
26
- """
27
- mobile = viewport.get('isMobile', False)
28
- width = viewport.get('width')
29
- height = viewport.get('height')
30
- deviceScaleFactor = viewport.get('deviceScaleFactor', 1)
31
- if viewport.get('isLandscape'):
32
- screenOrientation = {'angle': 90, 'type': 'landscapePrimary'}
33
- else:
34
- screenOrientation = {'angle': 0, 'type': 'portraitPrimary'}
35
- hasTouch = viewport.get('hasTouch', False)
36
-
37
- await asyncio.gather(
38
- self._client.send(
39
- 'Emulation.setDeviceMetricsOverride',
40
- {
41
- 'mobile': mobile,
42
- 'width': width,
43
- 'height': height,
44
- 'deviceScaleFactor': deviceScaleFactor,
45
- 'screenOrientation': screenOrientation,
46
- },
47
- ),
48
- self._client.send('Emulation.setTouchEmulationEnabled', {'enabled': hasTouch}),
49
- )
50
- reloadNeeded = self._emulatingMobile != mobile or self._hasTouch != hasTouch
51
- self._emulatingMobile = mobile
52
- self._hasTouch = hasTouch
53
- return reloadNeeded
@@ -1,48 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """Exceptions for pyppeteer package."""
5
-
6
- import asyncio
7
-
8
-
9
- class PyppeteerError(Exception): # noqa: D204
10
- """Base exception for pyppeteer."""
11
-
12
- pass
13
-
14
-
15
- class BrowserError(PyppeteerError): # noqa: D204
16
- """Exception raised from browser."""
17
-
18
- pass
19
-
20
-
21
- class ElementHandleError(PyppeteerError): # noqa: D204
22
- """ElementHandle related exception."""
23
-
24
- pass
25
-
26
-
27
- class NetworkError(PyppeteerError): # noqa: D204
28
- """Network/Protocol related exception."""
29
-
30
- pass
31
-
32
-
33
- class PageError(PyppeteerError): # noqa: D204
34
- """Page/Frame related exception."""
35
-
36
- pass
37
-
38
-
39
- class TimeoutError(asyncio.TimeoutError): # noqa: D204
40
- """Timeout Error class."""
41
-
42
- pass
43
-
44
-
45
- class DeprecationError(PyppeteerError): # noqa: D204
46
- """Deprecated Error class"""
47
-
48
- pass
@@ -1,63 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Events module
5
-
6
- puppeteer equivalent: Events.js
7
- """
8
-
9
-
10
- class Events:
11
- class Page:
12
- Close = 'close'
13
- Console = 'console'
14
- Dialog = 'dialog'
15
- DOMContentLoaded = 'domcontentloaded'
16
- Error = 'error'
17
- # Can't use just 'error' due to node.js special treatment of error events.
18
- # @see https://nodejs.org/api/events.html#events_error_events
19
- PageError = 'pageerror'
20
- Request = 'request'
21
- Response = 'response'
22
- RequestFailed = 'requestfailed'
23
- RequestFinished = 'requestfinished'
24
- FrameAttached = 'frameattached'
25
- FrameDetached = 'framedetached'
26
- FrameNavigated = 'framenavigated'
27
- Load = 'load'
28
- Metrics = 'metrics'
29
- Popup = 'popup'
30
- WorkerCreated = 'workercreated'
31
- WorkerDestroyed = 'workerdestroyed'
32
-
33
- class Browser:
34
- TargetCreated = 'targetcreated'
35
- TargetDestroyed = 'targetdestroyed'
36
- TargetChanged = 'targetchanged'
37
- Disconnected = 'disconnected'
38
-
39
- class BrowserContext:
40
- TargetCreated = 'targetcreated'
41
- TargetDestroyed = 'targetdestroyed'
42
- TargetChanged = 'targetchanged'
43
-
44
- class NetworkManager:
45
- Request = 'Events.NetworkManager.Request'
46
- Response = 'Events.NetworkManager.Response'
47
- RequestFailed = 'Events.NetworkManager.RequestFailed'
48
- RequestFinished = 'Events.NetworkManager.RequestFinished'
49
-
50
- class FrameManager:
51
- FrameAttached = 'Events.FrameManager.FrameAttached'
52
- FrameNavigated = 'Events.FrameManager.FrameNavigated'
53
- FrameDetached = 'Events.FrameManager.FrameDetached'
54
- LifecycleEvent = 'Events.FrameManager.LifecycleEvent'
55
- FrameNavigatedWithinDocument = 'Events.FrameManager.FrameNavigatedWithinDocument'
56
- ExecutionContextCreated = 'Events.FrameManager.ExecutionContextCreated'
57
- ExecutionContextDestroyed = 'Events.FrameManager.ExecutionContextDestroyed'
58
-
59
- class Connection:
60
- Disconnected = 'Events.Connection.Disconnected'
61
-
62
- class CDPSession:
63
- Disconnected = 'Events.CDPSession.Disconnected'
@@ -1,156 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
- """Execution Context Module."""
5
-
6
- import logging
7
- import math
8
- import re
9
- from typing import TYPE_CHECKING, Any, Dict, Optional, Union
10
-
11
- from biolib.pyppeteer.pyppeteer import helpers
12
- from biolib.pyppeteer.pyppeteer.connection import CDPSession
13
- from biolib.pyppeteer.pyppeteer.errors import ElementHandleError
14
- from biolib.pyppeteer.pyppeteer.jshandle import ElementHandle, JSHandle, createJSHandle
15
- from biolib.pyppeteer.pyppeteer.models import JSFunctionArg
16
-
17
- if TYPE_CHECKING:
18
- from pyppeteer.frame import Frame
19
- from pyppeteer.domworld import DOMWorld
20
-
21
- logger = logging.getLogger(__name__)
22
-
23
- EVALUATION_SCRIPT_URL = '__pyppeteer_evaluation_script__'
24
- SOURCE_URL_REGEX = re.compile(r'^[ \t]*//[@#] sourceURL=\s*(\S*?)\s*$', re.MULTILINE,)
25
-
26
- class ExecutionContext:
27
- """Execution Context class."""
28
-
29
- def __init__(self, client: CDPSession, contextPayload: Dict, world: Optional['DOMWorld']) -> None:
30
- self._client = client
31
- self._world = world
32
- self._contextId = contextPayload['id']
33
-
34
- @property
35
- def frame(self) -> Optional['Frame']:
36
- """Return frame associated with this execution context."""
37
- if self._world:
38
- return self._world.frame
39
-
40
- async def evaluate(self, pageFunction: str, *args: JSFunctionArg) -> JSFunctionArg:
41
- """Execute ``pageFunction`` on this context.
42
-
43
- Details see :meth:`pyppeteer.page.Page.evaluate`.
44
- """
45
- return await self._evaluateInternal(True, pageFunction, *args)
46
-
47
- async def evaluateHandle(self, pageFunction: str, *args: JSFunctionArg) -> Union['JSHandle', 'ElementHandle']:
48
- """Execute ``pageFunction`` on this context.
49
- Details see :meth:`pyppeteer.page.Page.evaluateHandle`.
50
- """
51
- return await self._evaluateInternal(False, pageFunction, *args)
52
-
53
- async def _evaluateInternal(
54
- self, returnByValue: bool, pageFunction: str, *args: JSFunctionArg
55
- ) -> Union['JSHandle', 'ElementHandle', JSFunctionArg]:
56
- suffix = f'//# sourceURL={EVALUATION_SCRIPT_URL}'
57
-
58
- if not helpers.is_js_func(pageFunction):
59
- try:
60
- if SOURCE_URL_REGEX.match(pageFunction):
61
- expressionWithSourceUrl = pageFunction
62
- else:
63
- expressionWithSourceUrl = f'{pageFunction}\n{suffix}'
64
- remoteObject = await self._client.send(
65
- 'Runtime.evaluate',
66
- {
67
- 'expression': expressionWithSourceUrl,
68
- 'contextId': self._contextId,
69
- 'returnByValue': returnByValue,
70
- 'awaitPromise': True,
71
- 'userGesture': True,
72
- },
73
- )
74
- except Exception as e:
75
- exceptionDetails = rewriteError(e)
76
- raise type(e)(f'Evaluation failed: {helpers.getExceptionMessage(exceptionDetails)}')
77
- else:
78
- try:
79
- remoteObject = await self._client.send(
80
- 'Runtime.callFunctionOn',
81
- {
82
- 'functionDeclaration': f'{pageFunction}\n{suffix}\n',
83
- 'executionContextId': self._contextId,
84
- 'arguments': [self._convertArgument(arg) for arg in args],
85
- 'returnByValue': returnByValue,
86
- 'awaitPromise': True,
87
- 'userGesture': True,
88
- },
89
- )
90
- except Exception as e:
91
- exceptionDetails = rewriteError(e)
92
- raise type(e)(f'Evaluation failed: {helpers.getExceptionMessage(exceptionDetails)}')
93
-
94
- exceptionDetails = remoteObject.get('exceptionDetails')
95
- if exceptionDetails:
96
- raise ElementHandleError('Evaluation failed: {}'.format(helpers.getExceptionMessage(exceptionDetails)))
97
-
98
- remoteObject = remoteObject['result']
99
- if returnByValue:
100
- return helpers.valueFromRemoteObject(remoteObject)
101
- else:
102
- return createJSHandle(self, remoteObject)
103
-
104
- def _convertArgument(self, arg: Any) -> Dict: # noqa: C901
105
- if arg == math.inf:
106
- return {'unserializableValue': 'Infinity'}
107
- if arg == -math.inf:
108
- return {'unserializableValue': '-Infinity'}
109
- objectHandle = arg if isinstance(arg, JSHandle) else None
110
- if objectHandle:
111
- if objectHandle._context != self:
112
- raise ElementHandleError('JSHandles can be evaluated only in the context they were created!')
113
- if objectHandle._disposed:
114
- raise ElementHandleError('JSHandle is disposed!')
115
- if objectHandle._remoteObject.get('unserializableValue'):
116
- return {'unserializableValue': objectHandle._remoteObject.get('unserializableValue')}
117
- if not objectHandle._remoteObject.get('objectId'):
118
- return {'value': objectHandle._remoteObject.get('value')}
119
- return {'objectId': objectHandle._remoteObject.get('objectId')}
120
- return {'value': arg}
121
-
122
- async def queryObjects(self, prototypeHandle: 'JSHandle'):
123
- if prototypeHandle._disposed:
124
- raise ElementHandleError('Prototype JSHandle is disposed')
125
- if not prototypeHandle._remoteObject.get('objectId'):
126
- raise ElementHandleError('Prototype JSHandle must not be referencing primitive value')
127
- response = await self._client.send(
128
- 'Runtime.queryObjects', {'prototypeObjectId': prototypeHandle._remoteObject['objectId']}
129
- )
130
- return createJSHandle(context=self, remoteObject=response.get('objects'))
131
-
132
- async def _adoptBackendNodeId(self, backendNodeId: int):
133
- obj = await self._client.send(
134
- 'DOM.resolveNode', {'backendNodeId': backendNodeId, 'executionContextId': self._contextId}
135
- )
136
- obj = obj['object']
137
- return createJSHandle(context=self, remoteObject=obj)
138
-
139
- async def _adoptElementHandle(self, elementHandle: ElementHandle):
140
- if elementHandle.executionContext == self:
141
- raise ElementHandleError('Cannot adopt handle that already belongs to this execution context')
142
- if not self._world:
143
- raise ElementHandleError('Cannot adopt handle without DOMWorld')
144
- nodeInfo = await self._client.send('DOM.describeNode', {'objectId': elementHandle._remoteObject['objectId']})
145
- return await self._adoptBackendNodeId(nodeInfo['node']['backendNodeId'])
146
-
147
-
148
- def rewriteError(error: Exception) -> Union[None, Dict[str, Dict[str, str]]]:
149
- msg = error.args[0]
150
- if 'Object reference chain is too long' in msg:
151
- return {'result': {'type': 'undefined'}}
152
- if "Object couldn't be returned by value" in msg:
153
- return {'result': {'type': 'undefined'}}
154
- if msg.endswith('Cannot find context with specified id'):
155
- raise type(error)('Execution context was destroyed, most likely because of a navigation.')
156
- raise error
@@ -1,299 +0,0 @@
1
- import asyncio
2
- from pathlib import Path
3
- from typing import TYPE_CHECKING, Any, Awaitable, List, Optional, Set, Union
4
-
5
- from ordered_set import OrderedSet
6
- from biolib.pyppeteer.pyppeteer import helpers
7
- from biolib.pyppeteer.pyppeteer.connection import CDPSession
8
- from biolib.pyppeteer.pyppeteer.domworld import DOMWorld, WaitTask
9
- from biolib.pyppeteer.pyppeteer.errors import BrowserError, PageError
10
- from biolib.pyppeteer.pyppeteer.jshandle import ElementHandle, JSHandle
11
- from biolib.pyppeteer.pyppeteer.models import JSFunctionArg, WaitTargets
12
- from biolib.pyppeteer.pyppeteer.network_manager import Response
13
-
14
- if TYPE_CHECKING:
15
- from pyppeteer.execution_context import ExecutionContext
16
-
17
-
18
- class Frame:
19
- """Frame class.
20
-
21
- Frame objects can be obtained via :attr:`pyppeteer.page.Page.mainFrame`.
22
- """
23
-
24
- def __init__(
25
- self, frameManager: 'FrameManager', client: CDPSession, parentFrame: Optional['Frame'], frameId: str
26
- ) -> None:
27
- self._frameManager = frameManager
28
- self._client = client
29
- self._parentFrame = parentFrame
30
- self._url = ''
31
- self._id = frameId
32
- self._detached = False
33
-
34
- self._loaderId = ''
35
- self._lifecycleEvents: Set[str] = set()
36
- self._mainWorld = DOMWorld(frameManager, self, frameManager._timeoutSettings)
37
- self._secondaryWorld = DOMWorld(frameManager, self, frameManager._timeoutSettings)
38
- self._childFrames: OrderedSet[Frame] = OrderedSet()
39
- if self._parentFrame:
40
- self._parentFrame._childFrames.add(self)
41
-
42
- self._waitTasks: Set[WaitTask] = set()
43
- if self._parentFrame:
44
- self._parentFrame._childFrames.add(self)
45
-
46
- self.addScriptTag = self.mainWorld.addScriptTag
47
- self.addStyleTag = self.mainWorld.addStyleTag
48
- self.evaluate = self.mainWorld.evaluate
49
- self.evaluateHandle = self.mainWorld.evaluateHandle
50
- self.querySelector = self.J = self.mainWorld.querySelector
51
- self.querySelectorAll = self.JJ = self.mainWorld.querySelectorAll
52
- self.querySelectorAllEval = self.JJeval = self.mainWorld.querySelectorAllEval
53
- self.querySelectorEval = self.Jeval = self.mainWorld.querySelectorEval
54
- self.type = self.mainWorld.type
55
- self.waitForFunction = self.mainWorld.waitForFunction
56
- self.xpath = self.Jx = self.mainWorld.xpath
57
-
58
- self.click = self.secondaryWorld.click
59
- self.focus = self.secondaryWorld.focus
60
- self.hover = self.secondaryWorld.hover
61
- self.select = self.secondaryWorld.select
62
- self.setContent = self.secondaryWorld.setContent
63
- self.tap = self.secondaryWorld.tap
64
-
65
- @property
66
- async def executionContext(self) -> Optional['ExecutionContext']:
67
- return await self.mainWorld.executionContext
68
-
69
- @property
70
- async def content(self) -> str:
71
- return await self.secondaryWorld.content
72
-
73
- @property
74
- async def title(self) -> str:
75
- return await self.secondaryWorld.title
76
-
77
- async def goto(
78
- self, url: str, referer: str = None, timeout: float = None, waitUntil: WaitTargets = None
79
- ) -> Optional[Response]:
80
- return await self._frameManager.navigateFrame(
81
- self, url=url, referer=referer, timeout=timeout, waitUntil=waitUntil
82
- )
83
-
84
- async def waitForNavigation(
85
- self, timeout: Optional[float] = None, waitUntil: Optional[WaitTargets] = None
86
- ) -> Optional[Response]:
87
- return await self._frameManager.waitForFrameNavigation(self, waitUntil=waitUntil, timeout=timeout)
88
-
89
- @property
90
- def mainWorld(self) -> 'DOMWorld': # ensure mainWorld not settable
91
- return self._mainWorld
92
-
93
- @property
94
- def secondaryWorld(self) -> 'DOMWorld': # ensure secondaryWorld is not settable
95
- return self._secondaryWorld
96
-
97
- @property
98
- def name(self) -> str:
99
- """Get frame name."""
100
- return getattr(self, '_name', '')
101
-
102
- @property
103
- def url(self) -> str:
104
- """Get url of the frame."""
105
- return self._url
106
-
107
- @property
108
- def parentFrame(self) -> Optional['Frame']:
109
- """Get parent frame.
110
-
111
- If this frame is main frame or detached frame, return ``None``.
112
- """
113
- return self._parentFrame
114
-
115
- @property
116
- def childFrames(self) -> List['Frame']:
117
- """Get child frames."""
118
- return list(self._childFrames)
119
-
120
- @property
121
- def isDetached(self) -> bool:
122
- """Return ``True`` if this frame is detached.
123
-
124
- Otherwise return ``False``.
125
- """
126
- return self._detached
127
-
128
- async def addScriptTag(
129
- self,
130
- url: Optional[str] = None,
131
- path: Optional[Union[str, Path]] = None,
132
- content: Optional[str] = None,
133
- type_: str = '',
134
- ) -> ElementHandle:
135
- """Add script tag to this frame.
136
-
137
- Details see :meth:`pyppeteer.page.Page.addScriptTag`.
138
- """
139
- return await self._mainWorld.addScriptTag(url=url, path=path, content=content, type_=type_)
140
-
141
- async def addStyleTag(
142
- self, url: Optional[str] = None, path: Optional[Union[str, Path]] = None, content: Optional[str] = None
143
- ) -> Optional['ElementHandle']:
144
- return await self._mainWorld.addStyleTag(url=url, path=path, content=content)
145
-
146
- async def focus(self, selector: str) -> None:
147
- """Focus element which matches ``selector``.
148
-
149
- Details see :meth:`pyppeteer.page.Page.focus`.
150
- """
151
- handle = await self.J(selector)
152
- if not handle:
153
- raise PageError('No node found for selector: ' + selector)
154
- await self.evaluate('element => element.focus()', handle)
155
- await handle.dispose()
156
-
157
- async def hover(self, selector: str) -> None:
158
- """Mouse hover the element which matches ``selector``.
159
-
160
- Details see :meth:`pyppeteer.page.Page.hover`.
161
- """
162
- handle = await self.J(selector)
163
- if not handle:
164
- raise PageError('No node found for selector: ' + selector)
165
- await handle.hover()
166
- await handle.dispose()
167
-
168
- async def select(self, selector: str, *values: str) -> List[str]:
169
- """Select options and return selected values.
170
-
171
- Details see :meth:`pyppeteer.page.Page.select`.
172
- """
173
- for index, value in values:
174
- if not isinstance(value, str):
175
- raise TypeError(f'Values must be string. Found {value} of type {type(value)} at index {index}')
176
- return await self.querySelectorEval( # type: ignore
177
- selector,
178
- '''
179
- (element, values) => {
180
- if (element.nodeName.toLowerCase() !== 'select')
181
- throw new Error('Element is not a <select> element.');
182
-
183
- const options = Array.from(element.options);
184
- element.value = undefined;
185
- for (const option of options) {
186
- option.selected = values.includes(option.value);
187
- if (option.selected && !element.multiple)
188
- break;
189
- }
190
-
191
- element.dispatchEvent(new Event('input', { 'bubbles': true }));
192
- element.dispatchEvent(new Event('change', { 'bubbles': true }));
193
- return options.filter(option => option.selected).map(options => options.value)
194
- }
195
- ''',
196
- *values,
197
- )
198
-
199
- async def tap(self, selector: str) -> None:
200
- """Tap the element which matches the ``selector``.
201
-
202
- Details see :meth:`pyppeteer.page.Page.tap`.
203
- """
204
- handle = await self.J(selector)
205
- if not handle:
206
- raise PageError('No node found for selector: ' + selector)
207
- await handle.tap()
208
- await handle.dispose()
209
-
210
- async def type(self, selector: str, text: str, delay: float = 0) -> None:
211
- """Type ``text`` on the element which matches ``selector``.
212
-
213
- Details see :meth:`pyppeteer.page.Page.type`.
214
- """
215
- handle = await self.querySelector(selector)
216
- if handle is None:
217
- raise PageError(f'Cannot find {selector} on this page')
218
- await handle.type(text, delay)
219
- await handle.dispose()
220
-
221
- def waitFor(
222
- self, selectorOrFunctionOrTimeout: Union[str, int, float], *args: JSFunctionArg, **kwargs: Any
223
- ) -> Awaitable[Optional[JSHandle]]:
224
- """Wait until `selectorOrFunctionOrTimeout`.
225
-
226
- Details see :meth:`pyppeteer.page.Page.waitFor`.
227
- """
228
- xPathPattern = '//'
229
- if helpers.is_js_func(selectorOrFunctionOrTimeout):
230
- return self.waitForFunction(selectorOrFunctionOrTimeout, *args, **kwargs)
231
- if isinstance(selectorOrFunctionOrTimeout, str):
232
- string = selectorOrFunctionOrTimeout
233
- if string.startswith(xPathPattern):
234
- return self.waitForXPath(string, **kwargs)
235
- return self.waitForSelector(string, **kwargs)
236
- if isinstance(selectorOrFunctionOrTimeout, (int, float)):
237
- return self._client.loop.create_task(asyncio.sleep(selectorOrFunctionOrTimeout / 1000))
238
- f = self._client.loop.create_future()
239
- f.set_exception(BrowserError(f'Unsupported target type: {type(selectorOrFunctionOrTimeout)}'))
240
- return f
241
-
242
- async def waitForSelector(
243
- self, selector: str, visible: bool = False, hidden: bool = False, timeout: float = None
244
- ) -> Optional['ElementHandle']:
245
- """Wait until element which matches ``selector`` appears on page.
246
-
247
- Details see :meth:`pyppeteer.page.Page.waitForSelector`.
248
- """
249
- handle = await self._secondaryWorld.waitForSelector(selector, visible=visible, hidden=hidden, timeout=timeout)
250
- if handle:
251
- mainExecutionContext = await self._mainWorld.executionContext
252
- result = await mainExecutionContext._adoptElementHandle(handle)
253
- await handle.dispose()
254
- return result
255
-
256
- async def waitForXPath(
257
- self, xpath: str, visible: bool = False, hidden: bool = False, timeout: int = None
258
- ) -> Optional['ElementHandle']:
259
- """Wait until element which matches ``xpath`` appears on page.
260
-
261
- Details see :meth:`pyppeteer.page.Page.waitForXPath`.
262
- """
263
- handle = await self._secondaryWorld.waitForXpath(xpath, visible=visible, hidden=hidden, timeout=timeout)
264
- if not handle:
265
- return None
266
- mainExecutionContext = await self._mainWorld.executionContext
267
- result = await mainExecutionContext._adoptElementHandle(handle)
268
- await handle.dispose()
269
- return result
270
-
271
- def _navigated(self, framePayload: dict) -> None:
272
- self._name = framePayload.get('name', '')
273
- self._navigationURL = framePayload.get('url', '')
274
- self._url = framePayload.get('url', '')
275
-
276
- def _navigatedWithinDocument(self, url: str) -> None:
277
- self._url = url
278
-
279
- def _onLifecycleEvent(self, loaderId: str, name: str) -> None:
280
- if name == 'init':
281
- self._loaderId = loaderId
282
- self._lifecycleEvents.clear()
283
- else:
284
- self._lifecycleEvents.add(name)
285
-
286
- def _onLoadingStopped(self) -> None:
287
- self._lifecycleEvents.add('DOMContentLoaded')
288
- self._lifecycleEvents.add('load')
289
-
290
- def _detach(self) -> None:
291
- self._detached = True
292
- self.mainWorld._detach()
293
- self.secondaryWorld._detach()
294
- if self._parentFrame:
295
- self._parentFrame._childFrames.remove(self)
296
- self._parentFrame = None
297
-
298
-
299
- from biolib.pyppeteer.pyppeteer.frame.frame_manager import FrameManager # isort:skip