flywheel-sdk 21.2.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.
Files changed (772) hide show
  1. flywheel/__init__.py +784 -0
  2. flywheel/api/__init__.py +46 -0
  3. flywheel/api/acquisitions_api.py +5014 -0
  4. flywheel/api/analyses_api.py +3848 -0
  5. flywheel/api/audit_trail_api.py +568 -0
  6. flywheel/api/auth_api.py +121 -0
  7. flywheel/api/batch_api.py +630 -0
  8. flywheel/api/bulk_api.py +140 -0
  9. flywheel/api/change_log_api.py +254 -0
  10. flywheel/api/collections_api.py +3913 -0
  11. flywheel/api/config_api.py +299 -0
  12. flywheel/api/container_tasks_api.py +137 -0
  13. flywheel/api/container_type_api.py +137 -0
  14. flywheel/api/containers_api.py +4784 -0
  15. flywheel/api/custom_filters_api.py +466 -0
  16. flywheel/api/data_view_executions_api.py +549 -0
  17. flywheel/api/dataexplorer_api.py +1192 -0
  18. flywheel/api/devices_api.py +1071 -0
  19. flywheel/api/dimse_api.py +814 -0
  20. flywheel/api/download_api.py +261 -0
  21. flywheel/api/files_api.py +1868 -0
  22. flywheel/api/form_responses_api.py +703 -0
  23. flywheel/api/gears_api.py +1875 -0
  24. flywheel/api/groups_api.py +2829 -0
  25. flywheel/api/jobs_api.py +2320 -0
  26. flywheel/api/jupyterlab_servers_api.py +245 -0
  27. flywheel/api/modalities_api.py +562 -0
  28. flywheel/api/packfiles_api.py +121 -0
  29. flywheel/api/projects_api.py +7820 -0
  30. flywheel/api/protocols_api.py +757 -0
  31. flywheel/api/reports_api.py +1057 -0
  32. flywheel/api/resolve_api.py +276 -0
  33. flywheel/api/roles_api.py +563 -0
  34. flywheel/api/sessions_api.py +5296 -0
  35. flywheel/api/site_api.py +1552 -0
  36. flywheel/api/staffing_pools_api.py +677 -0
  37. flywheel/api/subjects_api.py +5349 -0
  38. flywheel/api/tasks_api.py +897 -0
  39. flywheel/api/tree_api.py +266 -0
  40. flywheel/api/uids_api.py +140 -0
  41. flywheel/api/upload_api.py +842 -0
  42. flywheel/api/users_api.py +2142 -0
  43. flywheel/api/views_api.py +1089 -0
  44. flywheel/api_client.py +748 -0
  45. flywheel/client.py +291 -0
  46. flywheel/configuration.py +308 -0
  47. flywheel/drone_login.py +65 -0
  48. flywheel/file_spec.py +67 -0
  49. flywheel/finder.py +168 -0
  50. flywheel/flywheel.py +9867 -0
  51. flywheel/gear_context.py +374 -0
  52. flywheel/models/__init__.py +726 -0
  53. flywheel/models/access_level.py +30 -0
  54. flywheel/models/access_permission.py +197 -0
  55. flywheel/models/access_permission_output.py +192 -0
  56. flywheel/models/access_permission_update.py +166 -0
  57. flywheel/models/access_type.py +54 -0
  58. flywheel/models/accumulator.py +33 -0
  59. flywheel/models/acquisition.py +25 -0
  60. flywheel/models/acquisition_container_output.py +34 -0
  61. flywheel/models/acquisition_copy_input.py +223 -0
  62. flywheel/models/acquisition_input.py +297 -0
  63. flywheel/models/acquisition_list_output.py +767 -0
  64. flywheel/models/acquisition_modify_input.py +299 -0
  65. flywheel/models/acquisition_node.py +35 -0
  66. flywheel/models/acquisition_output.py +767 -0
  67. flywheel/models/acquisition_parents.py +241 -0
  68. flywheel/models/acquisition_template_options.py +275 -0
  69. flywheel/models/acquisition_upsert_input.py +383 -0
  70. flywheel/models/acquisition_upsert_output.py +243 -0
  71. flywheel/models/action.py +91 -0
  72. flywheel/models/adhoc_analysis_input.py +247 -0
  73. flywheel/models/analysis.py +25 -0
  74. flywheel/models/analysis_container_output.py +34 -0
  75. flywheel/models/analysis_files_create_ticket_output.py +241 -0
  76. flywheel/models/analysis_input.py +310 -0
  77. flywheel/models/analysis_input_legacy.py +25 -0
  78. flywheel/models/analysis_list_output.py +680 -0
  79. flywheel/models/analysis_list_output_inflated_job.py +650 -0
  80. flywheel/models/analysis_modify_input.py +191 -0
  81. flywheel/models/analysis_node.py +35 -0
  82. flywheel/models/analysis_output.py +683 -0
  83. flywheel/models/analysis_output_inflated_job.py +674 -0
  84. flywheel/models/analysis_parents.py +270 -0
  85. flywheel/models/analysis_update.py +25 -0
  86. flywheel/models/api_key_input_with_optional_label.py +191 -0
  87. flywheel/models/api_key_output.py +297 -0
  88. flywheel/models/as_storage.py +298 -0
  89. flywheel/models/assignee.py +192 -0
  90. flywheel/models/assignee_type.py +29 -0
  91. flywheel/models/audit_trail_report.py +486 -0
  92. flywheel/models/audit_trail_report_status.py +32 -0
  93. flywheel/models/auth0_auth_out.py +323 -0
  94. flywheel/models/auth0_options_out.py +319 -0
  95. flywheel/models/auth_out.py +357 -0
  96. flywheel/models/auth_session_output.py +272 -0
  97. flywheel/models/avatars.py +218 -0
  98. flywheel/models/aws_creds.py +191 -0
  99. flywheel/models/aws_storage.py +354 -0
  100. flywheel/models/azure_creds.py +190 -0
  101. flywheel/models/base_aet.py +245 -0
  102. flywheel/models/base_compute.py +426 -0
  103. flywheel/models/batch.py +360 -0
  104. flywheel/models/batch_cancel_output.py +36 -0
  105. flywheel/models/batch_create_filters.py +220 -0
  106. flywheel/models/batch_job_analysis_input.py +281 -0
  107. flywheel/models/batch_jobs_proposal_input.py +36 -0
  108. flywheel/models/batch_proposal.py +25 -0
  109. flywheel/models/batch_proposal_detail.py +36 -0
  110. flywheel/models/batch_proposal_input.py +25 -0
  111. flywheel/models/body.py +36 -0
  112. flywheel/models/body_regenerate_key_api_devices_device_id_key_post.py +25 -0
  113. flywheel/models/body_region.py +46 -0
  114. flywheel/models/bookmark.py +189 -0
  115. flywheel/models/bulk_move_input.py +272 -0
  116. flywheel/models/bulk_move_sessions.py +25 -0
  117. flywheel/models/callbacks_virus_scan_input.py +36 -0
  118. flywheel/models/cancelled_batch_output.py +163 -0
  119. flywheel/models/catalog_list_output.py +407 -0
  120. flywheel/models/central_out.py +299 -0
  121. flywheel/models/change.py +379 -0
  122. flywheel/models/change_log_container_type.py +38 -0
  123. flywheel/models/change_log_document.py +245 -0
  124. flywheel/models/change_method.py +33 -0
  125. flywheel/models/classic_batch_job_output.py +352 -0
  126. flywheel/models/classic_batch_job_output_inflated_jobs.py +379 -0
  127. flywheel/models/classic_batch_proposal_input.py +388 -0
  128. flywheel/models/classic_batch_proposal_output.py +471 -0
  129. flywheel/models/classification_add_delete.py +36 -0
  130. flywheel/models/classification_replace.py +36 -0
  131. flywheel/models/classification_update_input.py +36 -0
  132. flywheel/models/cohort.py +29 -0
  133. flywheel/models/collection.py +25 -0
  134. flywheel/models/collection_container_output.py +32 -0
  135. flywheel/models/collection_input.py +217 -0
  136. flywheel/models/collection_input_with_contents.py +248 -0
  137. flywheel/models/collection_node.py +192 -0
  138. flywheel/models/collection_node_level.py +31 -0
  139. flywheel/models/collection_operation.py +193 -0
  140. flywheel/models/collection_operation_type.py +29 -0
  141. flywheel/models/collection_output.py +639 -0
  142. flywheel/models/collection_with_stats.py +637 -0
  143. flywheel/models/column.py +286 -0
  144. flywheel/models/column_type.py +32 -0
  145. flywheel/models/common_classification.py +135 -0
  146. flywheel/models/common_deleted_count.py +25 -0
  147. flywheel/models/common_editions.py +25 -0
  148. flywheel/models/common_info.py +135 -0
  149. flywheel/models/common_join_origins.py +25 -0
  150. flywheel/models/common_key.py +36 -0
  151. flywheel/models/common_modified_count.py +25 -0
  152. flywheel/models/common_object_created.py +36 -0
  153. flywheel/models/common_project_settings.py +25 -0
  154. flywheel/models/common_settings.py +36 -0
  155. flywheel/models/complete_multipart_upload_output.py +189 -0
  156. flywheel/models/complete_s3_multipart_upload_input.py +241 -0
  157. flywheel/models/config_feature_map.py +36 -0
  158. flywheel/models/config_out.py +381 -0
  159. flywheel/models/config_output.py +36 -0
  160. flywheel/models/config_site_config_output.py +36 -0
  161. flywheel/models/config_site_settings.py +36 -0
  162. flywheel/models/config_site_settings_input.py +36 -0
  163. flywheel/models/conflict_types.py +30 -0
  164. flywheel/models/container_delete_reason.py +39 -0
  165. flywheel/models/container_filter.py +193 -0
  166. flywheel/models/container_id_view_input.py +521 -0
  167. flywheel/models/container_id_view_input_execute_and_save.py +308 -0
  168. flywheel/models/container_modify.py +536 -0
  169. flywheel/models/container_new_output.py +25 -0
  170. flywheel/models/container_node_min.py +350 -0
  171. flywheel/models/container_output.py +36 -0
  172. flywheel/models/container_output_with_files.py +283 -0
  173. flywheel/models/container_parents.py +311 -0
  174. flywheel/models/container_pipeline_input.py +536 -0
  175. flywheel/models/container_project_parents.py +25 -0
  176. flywheel/models/container_reference.py +193 -0
  177. flywheel/models/container_reference_with_label.py +219 -0
  178. flywheel/models/container_session_parents.py +25 -0
  179. flywheel/models/container_subject_parents.py +25 -0
  180. flywheel/models/container_type.py +39 -0
  181. flywheel/models/container_uidcheck.py +253 -0
  182. flywheel/models/container_update.py +135 -0
  183. flywheel/models/context_input.py +217 -0
  184. flywheel/models/copy_filter.py +299 -0
  185. flywheel/models/copy_status.py +32 -0
  186. flywheel/models/core_models_api_key_api_key_input.py +190 -0
  187. flywheel/models/core_models_audit_trail_create_report_input.py +273 -0
  188. flywheel/models/core_models_audit_trail_modify_report_input.py +167 -0
  189. flywheel/models/core_models_common_source.py +189 -0
  190. flywheel/models/core_models_jobs_api_key_input.py +191 -0
  191. flywheel/models/core_models_search_parent_type.py +33 -0
  192. flywheel/models/core_workflows_form_responses_models_form_parents.py +163 -0
  193. flywheel/models/core_workflows_form_responses_models_form_response_output.py +440 -0
  194. flywheel/models/core_workflows_reader_models_reader_task_parents.py +295 -0
  195. flywheel/models/creds.py +135 -0
  196. flywheel/models/curator.py +221 -0
  197. flywheel/models/current_user_output.py +707 -0
  198. flywheel/models/custom_field.py +437 -0
  199. flywheel/models/custom_form.py +244 -0
  200. flywheel/models/cvat_info.py +275 -0
  201. flywheel/models/cvat_settings.py +272 -0
  202. flywheel/models/cvat_settings_input.py +272 -0
  203. flywheel/models/cvat_sync_state.py +30 -0
  204. flywheel/models/daily_report_usage.py +565 -0
  205. flywheel/models/data_strategy.py +29 -0
  206. flywheel/models/data_view.py +25 -0
  207. flywheel/models/data_view_analysis_file_spec.py +221 -0
  208. flywheel/models/data_view_analysis_filter_spec.py +221 -0
  209. flywheel/models/data_view_column_alias.py +337 -0
  210. flywheel/models/data_view_column_spec.py +286 -0
  211. flywheel/models/data_view_execution.py +505 -0
  212. flywheel/models/data_view_execution_state.py +31 -0
  213. flywheel/models/data_view_file_spec.py +392 -0
  214. flywheel/models/data_view_group_by.py +166 -0
  215. flywheel/models/data_view_group_by_column.py +194 -0
  216. flywheel/models/data_view_name_filter_spec.py +194 -0
  217. flywheel/models/data_view_output.py +25 -0
  218. flywheel/models/data_view_save_data_view_input.py +25 -0
  219. flywheel/models/data_view_zip_filter_spec.py +223 -0
  220. flywheel/models/default_flywheel_role.py +30 -0
  221. flywheel/models/deid_log_skip_reason.py +29 -0
  222. flywheel/models/delete_by_search_query.py +253 -0
  223. flywheel/models/deleted_file.py +514 -0
  224. flywheel/models/deleted_result.py +194 -0
  225. flywheel/models/deprecated_action.py +29 -0
  226. flywheel/models/destination_container_type.py +30 -0
  227. flywheel/models/device.py +437 -0
  228. flywheel/models/device_admin_update.py +194 -0
  229. flywheel/models/device_create.py +219 -0
  230. flywheel/models/device_self_update.py +272 -0
  231. flywheel/models/device_status.py +36 -0
  232. flywheel/models/device_status_entry.py +221 -0
  233. flywheel/models/device_storage_strategy_update.py +193 -0
  234. flywheel/models/dimse_project_input.py +36 -0
  235. flywheel/models/dimse_project_output.py +36 -0
  236. flywheel/models/dimse_service_input.py +36 -0
  237. flywheel/models/dimse_service_output.py +36 -0
  238. flywheel/models/download.py +249 -0
  239. flywheel/models/download_container_filter.py +167 -0
  240. flywheel/models/download_container_filter_definition.py +222 -0
  241. flywheel/models/download_filter.py +221 -0
  242. flywheel/models/download_filter_definition.py +195 -0
  243. flywheel/models/download_format.py +29 -0
  244. flywheel/models/download_input.py +25 -0
  245. flywheel/models/download_node.py +189 -0
  246. flywheel/models/download_strategy.py +31 -0
  247. flywheel/models/download_ticket.py +36 -0
  248. flywheel/models/download_ticket_stub.py +249 -0
  249. flywheel/models/download_ticket_with_summary.py +36 -0
  250. flywheel/models/e_signature.py +242 -0
  251. flywheel/models/edition.py +169 -0
  252. flywheel/models/egress_device.py +597 -0
  253. flywheel/models/egress_device_page.py +219 -0
  254. flywheel/models/egress_provider.py +408 -0
  255. flywheel/models/egress_provider_id.py +164 -0
  256. flywheel/models/exchange_storage.py +243 -0
  257. flywheel/models/executor_info.py +353 -0
  258. flywheel/models/export_templates.py +195 -0
  259. flywheel/models/features.py +1838 -0
  260. flywheel/models/field_change.py +271 -0
  261. flywheel/models/field_change_log_document.py +245 -0
  262. flywheel/models/field_type.py +37 -0
  263. flywheel/models/file.py +1139 -0
  264. flywheel/models/file_classification_delta.py +245 -0
  265. flywheel/models/file_container_type.py +34 -0
  266. flywheel/models/file_entry.py +740 -0
  267. flywheel/models/file_export_templates.py +272 -0
  268. flywheel/models/file_format.py +33 -0
  269. flywheel/models/file_gear_info.py +215 -0
  270. flywheel/models/file_group.py +29 -0
  271. flywheel/models/file_list_output.py +1115 -0
  272. flywheel/models/file_modify_input.py +191 -0
  273. flywheel/models/file_move_input.py +221 -0
  274. flywheel/models/file_node.py +1138 -0
  275. flywheel/models/file_node_min.py +321 -0
  276. flywheel/models/file_origin.py +283 -0
  277. flywheel/models/file_output.py +1135 -0
  278. flywheel/models/file_parents.py +297 -0
  279. flywheel/models/file_reference.py +221 -0
  280. flywheel/models/file_suggestion.py +241 -0
  281. flywheel/models/file_template_options.py +299 -0
  282. flywheel/models/file_upsert_input.py +612 -0
  283. flywheel/models/file_upsert_origin.py +36 -0
  284. flywheel/models/file_upsert_output.py +1154 -0
  285. flywheel/models/file_version.py +190 -0
  286. flywheel/models/file_version_copy_of.py +273 -0
  287. flywheel/models/file_version_output.py +325 -0
  288. flywheel/models/file_via.py +245 -0
  289. flywheel/models/file_zip_entry.py +25 -0
  290. flywheel/models/file_zip_info.py +25 -0
  291. flywheel/models/filter.py +350 -0
  292. flywheel/models/filter_input.py +218 -0
  293. flywheel/models/filter_values.py +195 -0
  294. flywheel/models/filter_view.py +28 -0
  295. flywheel/models/fixed_file_version_input.py +216 -0
  296. flywheel/models/fixed_input.py +299 -0
  297. flywheel/models/form_definition.py +163 -0
  298. flywheel/models/form_response_base.py +311 -0
  299. flywheel/models/form_response_create.py +193 -0
  300. flywheel/models/gcp_creds.py +397 -0
  301. flywheel/models/gcp_storage.py +298 -0
  302. flywheel/models/gear.py +619 -0
  303. flywheel/models/gear_category.py +32 -0
  304. flywheel/models/gear_config.py +138 -0
  305. flywheel/models/gear_context_input.py +164 -0
  306. flywheel/models/gear_context_lookup.py +25 -0
  307. flywheel/models/gear_context_lookup_item.py +36 -0
  308. flywheel/models/gear_context_value_output.py +272 -0
  309. flywheel/models/gear_context_value_output_unfound.py +164 -0
  310. flywheel/models/gear_custom.py +135 -0
  311. flywheel/models/gear_directive.py +135 -0
  312. flywheel/models/gear_doc.py +25 -0
  313. flywheel/models/gear_document.py +332 -0
  314. flywheel/models/gear_document_input.py +303 -0
  315. flywheel/models/gear_document_legacy_input.py +302 -0
  316. flywheel/models/gear_environment.py +135 -0
  317. flywheel/models/gear_exchange.py +221 -0
  318. flywheel/models/gear_file_input.py +192 -0
  319. flywheel/models/gear_id_output.py +170 -0
  320. flywheel/models/gear_info.py +251 -0
  321. flywheel/models/gear_input_item.py +231 -0
  322. flywheel/models/gear_inputs.py +140 -0
  323. flywheel/models/gear_invocation.py +138 -0
  324. flywheel/models/gear_key_input.py +191 -0
  325. flywheel/models/gear_manifest.py +624 -0
  326. flywheel/models/gear_mixin.py +218 -0
  327. flywheel/models/gear_node.py +355 -0
  328. flywheel/models/gear_output_configuration.py +164 -0
  329. flywheel/models/gear_permissions.py +191 -0
  330. flywheel/models/gear_permissions_input.py +163 -0
  331. flywheel/models/gear_permissions_type.py +29 -0
  332. flywheel/models/gear_return_ticket.py +25 -0
  333. flywheel/models/gear_rule.py +653 -0
  334. flywheel/models/gear_rule_condition.py +219 -0
  335. flywheel/models/gear_rule_condition_type.py +37 -0
  336. flywheel/models/gear_rule_input.py +517 -0
  337. flywheel/models/gear_rule_modify_input.py +492 -0
  338. flywheel/models/gear_rule_output.py +652 -0
  339. flywheel/models/gear_save_submission.py +221 -0
  340. flywheel/models/gear_series.py +298 -0
  341. flywheel/models/gear_series_update.py +163 -0
  342. flywheel/models/gear_suggestion_output.py +301 -0
  343. flywheel/models/gear_ticket.py +245 -0
  344. flywheel/models/gear_ticket_output.py +163 -0
  345. flywheel/models/google_auth_out.py +299 -0
  346. flywheel/models/graph_filter.py +329 -0
  347. flywheel/models/group.py +25 -0
  348. flywheel/models/group_by.py +163 -0
  349. flywheel/models/group_by_column.py +36 -0
  350. flywheel/models/group_container_output.py +33 -0
  351. flywheel/models/group_input.py +248 -0
  352. flywheel/models/group_metadata_input.py +36 -0
  353. flywheel/models/group_node.py +34 -0
  354. flywheel/models/group_output.py +471 -0
  355. flywheel/models/group_report.py +218 -0
  356. flywheel/models/group_role.py +163 -0
  357. flywheel/models/group_settings_output.py +249 -0
  358. flywheel/models/group_update.py +249 -0
  359. flywheel/models/header_feature.py +37 -0
  360. flywheel/models/hierarchy_export_templates.py +272 -0
  361. flywheel/models/http_validation_error.py +167 -0
  362. flywheel/models/info.py +218 -0
  363. flywheel/models/info_add_remove.py +36 -0
  364. flywheel/models/info_container_type.py +35 -0
  365. flywheel/models/info_replace.py +36 -0
  366. flywheel/models/info_update_input.py +36 -0
  367. flywheel/models/ingress_provider.py +299 -0
  368. flywheel/models/ingress_providers.py +272 -0
  369. flywheel/models/ingress_site_settings.py +305 -0
  370. flywheel/models/ingress_update_provider.py +218 -0
  371. flywheel/models/inline_response200.py +163 -0
  372. flywheel/models/inline_response2001.py +171 -0
  373. flywheel/models/inline_response2002.py +163 -0
  374. flywheel/models/inline_response2003.py +36 -0
  375. flywheel/models/inline_response2005.py +25 -0
  376. flywheel/models/input_filter.py +221 -0
  377. flywheel/models/input_job.py +521 -0
  378. flywheel/models/input_job_profile.py +275 -0
  379. flywheel/models/inserted_id.py +163 -0
  380. flywheel/models/job.py +841 -0
  381. flywheel/models/job_analysis_input.py +273 -0
  382. flywheel/models/job_ask.py +301 -0
  383. flywheel/models/job_ask_response.py +195 -0
  384. flywheel/models/job_ask_response_job.py +978 -0
  385. flywheel/models/job_ask_return.py +25 -0
  386. flywheel/models/job_ask_return_criteria.py +245 -0
  387. flywheel/models/job_ask_state.py +25 -0
  388. flywheel/models/job_ask_state_response.py +163 -0
  389. flywheel/models/job_complete.py +220 -0
  390. flywheel/models/job_completion_input.py +25 -0
  391. flywheel/models/job_completion_ticket.py +25 -0
  392. flywheel/models/job_config.py +135 -0
  393. flywheel/models/job_config_input.py +272 -0
  394. flywheel/models/job_config_inputs.py +25 -0
  395. flywheel/models/job_config_output.py +25 -0
  396. flywheel/models/job_container_detail.py +25 -0
  397. flywheel/models/job_destination.py +189 -0
  398. flywheel/models/job_detail.py +925 -0
  399. flywheel/models/job_detail_container.py +190 -0
  400. flywheel/models/job_detail_file_entry.py +194 -0
  401. flywheel/models/job_detail_group.py +190 -0
  402. flywheel/models/job_detail_parent_info.py +303 -0
  403. flywheel/models/job_executor_info.py +369 -0
  404. flywheel/models/job_file_input.py +247 -0
  405. flywheel/models/job_file_input_list_output.py +247 -0
  406. flywheel/models/job_file_object.py +435 -0
  407. flywheel/models/job_file_object_list_output.py +407 -0
  408. flywheel/models/job_gear_match.py +25 -0
  409. flywheel/models/job_inputs_array_item.py +305 -0
  410. flywheel/models/job_inputs_item.py +242 -0
  411. flywheel/models/job_inputs_object.py +138 -0
  412. flywheel/models/job_list_entry.py +25 -0
  413. flywheel/models/job_list_output.py +979 -0
  414. flywheel/models/job_list_output_config.py +220 -0
  415. flywheel/models/job_log.py +189 -0
  416. flywheel/models/job_log_column.py +40 -0
  417. flywheel/models/job_log_record.py +192 -0
  418. flywheel/models/job_modify.py +193 -0
  419. flywheel/models/job_origin.py +190 -0
  420. flywheel/models/job_output.py +1005 -0
  421. flywheel/models/job_output_config.py +247 -0
  422. flywheel/models/job_parents.py +297 -0
  423. flywheel/models/job_priority.py +31 -0
  424. flywheel/models/job_priority_update.py +192 -0
  425. flywheel/models/job_profile.py +427 -0
  426. flywheel/models/job_profile_input.py +25 -0
  427. flywheel/models/job_request.py +221 -0
  428. flywheel/models/job_request_item.py +246 -0
  429. flywheel/models/job_request_item_type.py +31 -0
  430. flywheel/models/job_request_target.py +270 -0
  431. flywheel/models/job_state.py +32 -0
  432. flywheel/models/job_state_counts.py +25 -0
  433. flywheel/models/job_stats_by_state.py +25 -0
  434. flywheel/models/job_ticket_output.py +165 -0
  435. flywheel/models/job_transition_times.py +253 -0
  436. flywheel/models/job_version_info.py +135 -0
  437. flywheel/models/jobs_by_state.py +272 -0
  438. flywheel/models/jobs_list.py +166 -0
  439. flywheel/models/join_origin_device.py +164 -0
  440. flywheel/models/join_origin_job.py +219 -0
  441. flywheel/models/join_origin_user.py +189 -0
  442. flywheel/models/join_origins.py +223 -0
  443. flywheel/models/join_type.py +28 -0
  444. flywheel/models/jupyterhub_workspace.py +163 -0
  445. flywheel/models/jupyterlab_server_modify.py +275 -0
  446. flywheel/models/jupyterlab_server_origin.py +25 -0
  447. flywheel/models/jupyterlab_server_output.py +25 -0
  448. flywheel/models/jupyterlab_server_response.py +415 -0
  449. flywheel/models/jupyterlab_server_update.py +25 -0
  450. flywheel/models/ldap_sync.py +36 -0
  451. flywheel/models/ldap_sync_config.py +163 -0
  452. flywheel/models/ldap_sync_input.py +36 -0
  453. flywheel/models/ldap_sync_status.py +250 -0
  454. flywheel/models/legacy_api_key_output.py +271 -0
  455. flywheel/models/legacy_input.py +244 -0
  456. flywheel/models/legacy_usage_report.py +309 -0
  457. flywheel/models/legacys_usage_project_entry.py +194 -0
  458. flywheel/models/libs_workflows_models_parent_type.py +33 -0
  459. flywheel/models/libs_workflows_models_task_status.py +32 -0
  460. flywheel/models/local_storage.py +217 -0
  461. flywheel/models/location.py +189 -0
  462. flywheel/models/locked.py +219 -0
  463. flywheel/models/master_subject_code_dob_input.py +279 -0
  464. flywheel/models/master_subject_code_input.py +281 -0
  465. flywheel/models/master_subject_code_output.py +166 -0
  466. flywheel/models/matched_acquisition_output.py +518 -0
  467. flywheel/models/mfa_channel.py +30 -0
  468. flywheel/models/mfa_settings.py +167 -0
  469. flywheel/models/mixins.py +794 -0
  470. flywheel/models/ml_set_filter.py +194 -0
  471. flywheel/models/ml_type.py +30 -0
  472. flywheel/models/modality.py +250 -0
  473. flywheel/models/modality_input.py +244 -0
  474. flywheel/models/modality_modify.py +218 -0
  475. flywheel/models/modality_output.py +271 -0
  476. flywheel/models/modified_result.py +190 -0
  477. flywheel/models/modify_user_input.py +466 -0
  478. flywheel/models/move_conflict.py +300 -0
  479. flywheel/models/note.py +391 -0
  480. flywheel/models/note_input.py +165 -0
  481. flywheel/models/optional_input_policy.py +30 -0
  482. flywheel/models/order.py +29 -0
  483. flywheel/models/organ_system.py +64 -0
  484. flywheel/models/origin.py +193 -0
  485. flywheel/models/origin_type.py +35 -0
  486. flywheel/models/orphaned_count.py +163 -0
  487. flywheel/models/output_user_page.py +219 -0
  488. flywheel/models/packfile_cleanup_output.py +166 -0
  489. flywheel/models/packfile_removed_output.py +189 -0
  490. flywheel/models/page.py +216 -0
  491. flywheel/models/page_generic_file_output.py +219 -0
  492. flywheel/models/page_generic_filter.py +219 -0
  493. flywheel/models/page_generic_form_response_output.py +219 -0
  494. flywheel/models/page_generic_protocol.py +244 -0
  495. flywheel/models/page_generic_reader_task_output.py +244 -0
  496. flywheel/models/page_generic_staffing_pool.py +244 -0
  497. flywheel/models/parsed_query_response.py +194 -0
  498. flywheel/models/permission_access_permission.py +25 -0
  499. flywheel/models/premade_jobs_batch_job_output.py +298 -0
  500. flywheel/models/premade_jobs_batch_job_output_inflated_jobs.py +299 -0
  501. flywheel/models/premade_jobs_batch_proposal.py +334 -0
  502. flywheel/models/premade_jobs_batch_proposal_detail.py +166 -0
  503. flywheel/models/premade_jobs_batch_proposal_input.py +166 -0
  504. flywheel/models/project.py +25 -0
  505. flywheel/models/project_acquisition_upsert_input.py +25 -0
  506. flywheel/models/project_acquisition_upsert_output.py +25 -0
  507. flywheel/models/project_aet.py +331 -0
  508. flywheel/models/project_aet_input.py +248 -0
  509. flywheel/models/project_catalog_list_output.py +25 -0
  510. flywheel/models/project_contact.py +194 -0
  511. flywheel/models/project_container_output.py +41 -0
  512. flywheel/models/project_copy_input.py +245 -0
  513. flywheel/models/project_copy_output.py +215 -0
  514. flywheel/models/project_counters.py +346 -0
  515. flywheel/models/project_hierarchy_input.py +278 -0
  516. flywheel/models/project_hierarchy_output.py +222 -0
  517. flywheel/models/project_hierarchy_upsert_input.py +25 -0
  518. flywheel/models/project_hierarchy_upsert_output.py +25 -0
  519. flywheel/models/project_input.py +384 -0
  520. flywheel/models/project_institution.py +194 -0
  521. flywheel/models/project_list_output.py +897 -0
  522. flywheel/models/project_locking_reason.py +32 -0
  523. flywheel/models/project_modify.py +413 -0
  524. flywheel/models/project_node.py +42 -0
  525. flywheel/models/project_output.py +899 -0
  526. flywheel/models/project_parents.py +168 -0
  527. flywheel/models/project_report.py +463 -0
  528. flywheel/models/project_report_list.py +167 -0
  529. flywheel/models/project_session_upsert_input.py +25 -0
  530. flywheel/models/project_session_upsert_output.py +25 -0
  531. flywheel/models/project_settings_input.py +333 -0
  532. flywheel/models/project_settings_output.py +333 -0
  533. flywheel/models/project_settings_sharing.py +327 -0
  534. flywheel/models/project_settings_sharing_input.py +334 -0
  535. flywheel/models/project_settings_workspaces.py +167 -0
  536. flywheel/models/project_settings_workspaces_input.py +167 -0
  537. flywheel/models/project_share_level.py +29 -0
  538. flywheel/models/project_sharing_settings_project_contact.py +25 -0
  539. flywheel/models/project_sharing_settings_project_counters.py +36 -0
  540. flywheel/models/project_sharing_settings_project_institution.py +25 -0
  541. flywheel/models/project_sharing_settings_project_settings_input.py +25 -0
  542. flywheel/models/project_sharing_settings_project_settings_output.py +25 -0
  543. flywheel/models/project_sharing_settings_project_settings_sharing.py +25 -0
  544. flywheel/models/project_sharing_settings_project_settings_sharing_input.py +25 -0
  545. flywheel/models/project_sharing_settings_project_stats.py +36 -0
  546. flywheel/models/project_stats.py +270 -0
  547. flywheel/models/project_subject_upsert_input.py +25 -0
  548. flywheel/models/project_subject_upsert_output.py +25 -0
  549. flywheel/models/project_template.py +195 -0
  550. flywheel/models/project_template_input.py +195 -0
  551. flywheel/models/project_template_list_input.py +166 -0
  552. flywheel/models/project_template_requirement.py +36 -0
  553. flywheel/models/project_template_session_template.py +36 -0
  554. flywheel/models/project_upsert_origin.py +36 -0
  555. flywheel/models/protocol.py +515 -0
  556. flywheel/models/protocol_e_signature_config.py +191 -0
  557. flywheel/models/protocol_input.py +354 -0
  558. flywheel/models/protocol_modify.py +277 -0
  559. flywheel/models/protocol_status.py +30 -0
  560. flywheel/models/provider.py +461 -0
  561. flywheel/models/provider_access_type.py +29 -0
  562. flywheel/models/provider_class.py +29 -0
  563. flywheel/models/provider_deletion_status.py +189 -0
  564. flywheel/models/provider_input.py +25 -0
  565. flywheel/models/provider_links.py +282 -0
  566. flywheel/models/provider_type.py +34 -0
  567. flywheel/models/providers.py +277 -0
  568. flywheel/models/reader_batch_create.py +463 -0
  569. flywheel/models/reader_task.py +725 -0
  570. flywheel/models/reader_task_config.py +189 -0
  571. flywheel/models/reader_task_create.py +543 -0
  572. flywheel/models/reader_task_modify.py +303 -0
  573. flywheel/models/reader_task_output.py +752 -0
  574. flywheel/models/reader_task_parent_details.py +322 -0
  575. flywheel/models/report_access_log_context.py +301 -0
  576. flywheel/models/report_access_log_context_entry.py +194 -0
  577. flywheel/models/report_access_log_context_file_entry.py +165 -0
  578. flywheel/models/report_access_log_entry.py +624 -0
  579. flywheel/models/report_access_log_origin.py +194 -0
  580. flywheel/models/report_availability_list.py +167 -0
  581. flywheel/models/report_daily_usage_entry.py +501 -0
  582. flywheel/models/report_demographics_grid.py +36 -0
  583. flywheel/models/report_ethnicity_grid.py +252 -0
  584. flywheel/models/report_gender_count.py +222 -0
  585. flywheel/models/report_group_report.py +217 -0
  586. flywheel/models/report_legacy_usage_entry.py +36 -0
  587. flywheel/models/report_legacy_usage_project_entry.py +36 -0
  588. flywheel/models/report_project.py +25 -0
  589. flywheel/models/report_site.py +192 -0
  590. flywheel/models/report_time_period.py +193 -0
  591. flywheel/models/report_usage.py +630 -0
  592. flywheel/models/report_usage_entry.py +25 -0
  593. flywheel/models/resolve_input.py +163 -0
  594. flywheel/models/resolve_output.py +194 -0
  595. flywheel/models/resolver_acquisition_node.py +36 -0
  596. flywheel/models/resolver_analysis_node.py +36 -0
  597. flywheel/models/resolver_file_node.py +36 -0
  598. flywheel/models/resolver_gear_node.py +36 -0
  599. flywheel/models/resolver_group_node.py +36 -0
  600. flywheel/models/resolver_input.py +25 -0
  601. flywheel/models/resolver_node.py +182 -0
  602. flywheel/models/resolver_output.py +25 -0
  603. flywheel/models/resolver_project_node.py +36 -0
  604. flywheel/models/resolver_session_node.py +36 -0
  605. flywheel/models/resolver_subject_node.py +36 -0
  606. flywheel/models/role_input.py +192 -0
  607. flywheel/models/role_output.py +273 -0
  608. flywheel/models/role_permission.py +194 -0
  609. flywheel/models/role_permission_output.py +189 -0
  610. flywheel/models/role_permission_update.py +163 -0
  611. flywheel/models/role_type.py +32 -0
  612. flywheel/models/role_update.py +194 -0
  613. flywheel/models/roles_backwards_compatible_role_assignment.py +36 -0
  614. flywheel/models/roles_group_role_pool_input.py +36 -0
  615. flywheel/models/roles_role.py +36 -0
  616. flywheel/models/roles_role_assignment.py +195 -0
  617. flywheel/models/roles_role_input.py +36 -0
  618. flywheel/models/rule.py +467 -0
  619. flywheel/models/rule_any.py +216 -0
  620. flywheel/models/s3_addressing_style.py +29 -0
  621. flywheel/models/s3_compat_storage.py +381 -0
  622. flywheel/models/save_search.py +298 -0
  623. flywheel/models/save_search_input.py +219 -0
  624. flywheel/models/save_search_output.py +301 -0
  625. flywheel/models/save_search_page.py +219 -0
  626. flywheel/models/save_search_parent.py +192 -0
  627. flywheel/models/save_search_update.py +194 -0
  628. flywheel/models/search_acquisition_response.py +252 -0
  629. flywheel/models/search_analysis_response.py +254 -0
  630. flywheel/models/search_collection_response.py +254 -0
  631. flywheel/models/search_file_response.py +312 -0
  632. flywheel/models/search_group_response.py +196 -0
  633. flywheel/models/search_parent_acquisition.py +47 -0
  634. flywheel/models/search_parent_analysis.py +47 -0
  635. flywheel/models/search_parent_collection.py +46 -0
  636. flywheel/models/search_parent_project.py +54 -0
  637. flywheel/models/search_parent_response.py +213 -0
  638. flywheel/models/search_parent_session.py +48 -0
  639. flywheel/models/search_parent_subject.py +48 -0
  640. flywheel/models/search_parse_error.py +252 -0
  641. flywheel/models/search_parse_search_query_result.py +36 -0
  642. flywheel/models/search_project_response.py +196 -0
  643. flywheel/models/search_query.py +337 -0
  644. flywheel/models/search_query_suggestions.py +36 -0
  645. flywheel/models/search_response.py +448 -0
  646. flywheel/models/search_return_type.py +33 -0
  647. flywheel/models/search_save_search.py +36 -0
  648. flywheel/models/search_save_search_input.py +36 -0
  649. flywheel/models/search_save_search_parent.py +36 -0
  650. flywheel/models/search_save_search_update.py +36 -0
  651. flywheel/models/search_session_response.py +252 -0
  652. flywheel/models/search_status.py +166 -0
  653. flywheel/models/search_structured_search_query.py +25 -0
  654. flywheel/models/search_subject_response.py +225 -0
  655. flywheel/models/search_suggestion.py +36 -0
  656. flywheel/models/select_item.py +190 -0
  657. flywheel/models/server_state.py +303 -0
  658. flywheel/models/service_aet.py +301 -0
  659. flywheel/models/service_aet_input.py +276 -0
  660. flywheel/models/session.py +25 -0
  661. flywheel/models/session_container_output.py +35 -0
  662. flywheel/models/session_copy_input.py +253 -0
  663. flywheel/models/session_embedded_subject.py +299 -0
  664. flywheel/models/session_input.py +431 -0
  665. flywheel/models/session_list_output.py +897 -0
  666. flywheel/models/session_metadata_input.py +36 -0
  667. flywheel/models/session_modify.py +464 -0
  668. flywheel/models/session_node.py +36 -0
  669. flywheel/models/session_output.py +897 -0
  670. flywheel/models/session_parents.py +220 -0
  671. flywheel/models/session_template_options.py +221 -0
  672. flywheel/models/session_template_recalc_output.py +165 -0
  673. flywheel/models/session_upsert_input.py +464 -0
  674. flywheel/models/session_upsert_output.py +243 -0
  675. flywheel/models/sharing_filter_options.py +345 -0
  676. flywheel/models/signed_fs_upload_output.py +189 -0
  677. flywheel/models/signed_url_cleanup_input.py +189 -0
  678. flywheel/models/signed_url_upload_input.py +190 -0
  679. flywheel/models/signed_url_upload_output.py +349 -0
  680. flywheel/models/site.py +623 -0
  681. flywheel/models/site_report.py +194 -0
  682. flywheel/models/site_settings.py +385 -0
  683. flywheel/models/sort.py +192 -0
  684. flywheel/models/stable_api_key_input.py +25 -0
  685. flywheel/models/staffing_pool.py +324 -0
  686. flywheel/models/staffing_pool_create.py +216 -0
  687. flywheel/models/staffing_pool_list.py +164 -0
  688. flywheel/models/staffing_pool_modify.py +218 -0
  689. flywheel/models/state.py +32 -0
  690. flywheel/models/static_compute.py +218 -0
  691. flywheel/models/status_transitions.py +245 -0
  692. flywheel/models/status_type.py +31 -0
  693. flywheel/models/status_value.py +31 -0
  694. flywheel/models/storage_strategy.py +30 -0
  695. flywheel/models/storage_strategy_config.py +194 -0
  696. flywheel/models/structured_query.py +165 -0
  697. flywheel/models/structured_query_suggestions.py +196 -0
  698. flywheel/models/structured_query_value_suggestion.py +247 -0
  699. flywheel/models/subject.py +34 -0
  700. flywheel/models/subject_container_output.py +36 -0
  701. flywheel/models/subject_copy_input.py +223 -0
  702. flywheel/models/subject_input.py +627 -0
  703. flywheel/models/subject_modify.py +684 -0
  704. flywheel/models/subject_node.py +37 -0
  705. flywheel/models/subject_output.py +1008 -0
  706. flywheel/models/subject_output_for_list.py +1005 -0
  707. flywheel/models/subject_parents.py +194 -0
  708. flywheel/models/subject_role_permission.py +194 -0
  709. flywheel/models/subject_state.py +30 -0
  710. flywheel/models/subject_template_options.py +191 -0
  711. flywheel/models/subject_upsert_input.py +573 -0
  712. flywheel/models/subject_upsert_output.py +216 -0
  713. flywheel/models/sync_user_input.py +322 -0
  714. flywheel/models/tag.py +165 -0
  715. flywheel/models/task_assign.py +194 -0
  716. flywheel/models/task_facet.py +29 -0
  717. flywheel/models/task_parent_ref.py +245 -0
  718. flywheel/models/task_parent_ref_input.py +219 -0
  719. flywheel/models/task_priority.py +31 -0
  720. flywheel/models/task_submission.py +189 -0
  721. flywheel/models/therapeutic_area.py +60 -0
  722. flywheel/models/transitions.py +272 -0
  723. flywheel/models/tree_container_request_spec.py +281 -0
  724. flywheel/models/tree_graph.py +142 -0
  725. flywheel/models/tree_graph_connection.py +244 -0
  726. flywheel/models/tree_graph_connections.py +142 -0
  727. flywheel/models/tree_graph_node.py +166 -0
  728. flywheel/models/tree_request.py +25 -0
  729. flywheel/models/tree_response_item.py +142 -0
  730. flywheel/models/type_str.py +31 -0
  731. flywheel/models/uid_check_input_acquisitions.py +244 -0
  732. flywheel/models/uid_check_input_sessions.py +244 -0
  733. flywheel/models/uid_check_output.py +191 -0
  734. flywheel/models/upload_complete_s3_multipart_input.py +25 -0
  735. flywheel/models/upload_complete_s3_multipart_output.py +25 -0
  736. flywheel/models/upload_signed_fs_file_upload_output.py +36 -0
  737. flywheel/models/upload_signed_upload_url_input.py +36 -0
  738. flywheel/models/upload_signed_upload_url_output.py +36 -0
  739. flywheel/models/upload_ticket_output.py +215 -0
  740. flywheel/models/upload_token_output.py +163 -0
  741. flywheel/models/upsert_result.py +31 -0
  742. flywheel/models/user.py +760 -0
  743. flywheel/models/user_api_key.py +220 -0
  744. flywheel/models/user_input.py +461 -0
  745. flywheel/models/user_jobs.py +219 -0
  746. flywheel/models/user_jobs_output.py +25 -0
  747. flywheel/models/user_output.py +36 -0
  748. flywheel/models/user_output_id.py +163 -0
  749. flywheel/models/user_preferences.py +135 -0
  750. flywheel/models/user_wechat.py +135 -0
  751. flywheel/models/validation_error.py +215 -0
  752. flywheel/models/validation_rule.py +190 -0
  753. flywheel/models/version.py +363 -0
  754. flywheel/models/version_output.py +25 -0
  755. flywheel/models/view_id_output.py +164 -0
  756. flywheel/models/view_output.py +440 -0
  757. flywheel/models/viewer_app.py +381 -0
  758. flywheel/models/viewer_app_input.py +382 -0
  759. flywheel/models/viewer_app_type.py +29 -0
  760. flywheel/models/virus_scan.py +166 -0
  761. flywheel/models/virus_scan_state.py +30 -0
  762. flywheel/models/work_in_progress_features.py +135 -0
  763. flywheel/models/zipfile_info.py +192 -0
  764. flywheel/models/zipfile_member_info.py +241 -0
  765. flywheel/partial_reader.py +50 -0
  766. flywheel/rest.py +352 -0
  767. flywheel/util.py +95 -0
  768. flywheel/view_builder.py +449 -0
  769. flywheel_sdk-21.2.0.dist-info/METADATA +42 -0
  770. flywheel_sdk-21.2.0.dist-info/RECORD +772 -0
  771. flywheel_sdk-21.2.0.dist-info/WHEEL +4 -0
  772. flywheel_sdk-21.2.0.dist-info/licenses/LICENSE.txt +18 -0
@@ -0,0 +1,794 @@
1
+ import warnings
2
+
3
+ from .. import util
4
+ from ..finder import Finder
5
+ from .gear_mixin import GearMixin # noqa: F401
6
+
7
+
8
+ class ContextBase(object):
9
+ def __init__(self):
10
+ self._context = None
11
+
12
+ def _set_context(self, context):
13
+ """Set the context object (i.e. flywheel client instance)"""
14
+ self._context = context
15
+
16
+
17
+ class ContainerBase(object):
18
+ def __init__(self):
19
+ self.__context = None
20
+
21
+ def _set_context(self, context):
22
+ """Set the context object (i.e. flywheel client instance)"""
23
+ self.__context = context
24
+ self._update_files_parent(getattr(self, "_files", None))
25
+
26
+ def _update_files_parent(self, files):
27
+ # Set the parent for each file
28
+ if files:
29
+ for file_entry in files:
30
+ file_entry._parent = self
31
+
32
+ def _invoke_container_api(self, fmt, *args, **kwargs):
33
+ """Invoke container api, formatting the string first"""
34
+ if not self.__context:
35
+ raise ValueError(f"No context in {self}")
36
+ fname = fmt.format(self.container_type)
37
+ fn = getattr(self.__context, fname, None)
38
+ if not fn:
39
+ raise ValueError(f"Context {self.__context} doesn't have a function {fname}")
40
+ return fn(*args, **kwargs)
41
+
42
+ def _invoke_file_api(self, fmt, *args, **kwargs):
43
+ """Invoke container api, formatting the string first"""
44
+ if self.__context:
45
+ fname = fmt.format(self.container_type)
46
+ file_group = getattr(self, "_file_group", None)
47
+ if file_group is not None and not hasattr(self.__context, fname):
48
+ fname = fname.replace("file", file_group)
49
+ fn = getattr(self.__context, fname, None)
50
+ if fn:
51
+ return fn(*args, **kwargs)
52
+ else:
53
+ raise ValueError(f"Context {self.__context} doesn't have a function {fname}")
54
+ return None
55
+
56
+ def _add_child(self, child_type, args, kwargs):
57
+ """Add a child to this container, returns the child that was created"""
58
+ fname = "add_{}".format(child_type)
59
+
60
+ body = util.params_to_dict(fname, args, kwargs)
61
+ body[self.container_type] = self.id
62
+
63
+ child_id = self._invoke_container_api(fname, body)
64
+ if child_id:
65
+ get_fname = "get_{}".format(child_type)
66
+ return self._invoke_container_api(get_fname, child_id)
67
+
68
+ return None
69
+
70
+ def update(self, *args, **kwargs):
71
+ """Update container using dictionary or kwargs"""
72
+ # Could either pass a dictionary or kwargs values
73
+ body = util.params_to_dict("update", args, kwargs)
74
+
75
+ # Update the container
76
+ return self._invoke_container_api("modify_{}", self.id, body)
77
+
78
+ def reload(self):
79
+ """Reload the object from the server, and return the result"""
80
+ return self._invoke_container_api("get_{}", self.id)
81
+
82
+ def ref(self):
83
+ """Make a container reference"""
84
+ return {"type": self.container_type, "id": self.id}
85
+
86
+ def _localize_date(self, name):
87
+ """Localize the date attribute for name"""
88
+ value = getattr(self, name, None)
89
+ if not value:
90
+ return None
91
+ from dateutil.tz import tzlocal
92
+
93
+ return value.astimezone(tzlocal())
94
+
95
+ @property
96
+ def local_created(self):
97
+ """Get the creation time in the local timezone"""
98
+ return self._localize_date("created")
99
+
100
+ @property
101
+ def local_modified(self):
102
+ """Get the modification time in the local timezone"""
103
+ return self._localize_date("modified")
104
+
105
+ def _find_children(self, child_type, filters, find_first=False, find_one=False, **kwargs):
106
+ fname = "get_{}_{}".format(self.container_type, child_type)
107
+ return self.__context._find(
108
+ fname,
109
+ [self.id],
110
+ filters,
111
+ find_first=find_first,
112
+ find_one=find_one,
113
+ **kwargs,
114
+ )
115
+
116
+ def __getattr__(self, name):
117
+ # Return finders for children
118
+ if name in self.child_types and self.id is not None:
119
+ prop_name = "_{}".format(name)
120
+ result = getattr(self, prop_name, None)
121
+ if result is None:
122
+ # e.g. get_project_sessions
123
+ fname = "get_{}_{}".format(self.container_type, name)
124
+ result = Finder(self.__context, fname, self.id)
125
+ setattr(self, prop_name, result)
126
+ return result
127
+
128
+ return getattr(object, name)
129
+
130
+
131
+ class InfoMethods(object):
132
+ def _warn_if_keys_will_be_sanitized(self, key):
133
+ """Log warning message for offending characters"""
134
+ if "$" in key:
135
+ warnings.warn(f"Key {key} contains '$', which will be replaced with '-'.")
136
+ if "." in key:
137
+ warnings.warn(f"Key {key} contains '.', which will be replaced with '_'.")
138
+
139
+ def _check_list(self, values):
140
+ """Check list values"""
141
+ for val in values:
142
+ if isinstance(val, list):
143
+ self._check_list(val)
144
+ elif isinstance(val, dict):
145
+ self._validate_keys(val)
146
+
147
+ def _validate_keys(self, body):
148
+ """Recursively check for keys that contain offending characters"""
149
+ for key, values in body.items():
150
+ self._warn_if_keys_will_be_sanitized(key)
151
+ if isinstance(values, dict):
152
+ self._validate_keys(values)
153
+ elif isinstance(values, list):
154
+ self._check_list(values)
155
+
156
+ def replace_info(self, info):
157
+ """Fully replace this object's info with the provided value"""
158
+ self._validate_keys(info)
159
+ return self._invoke_container_api("replace_{}_info", self.id, info)
160
+
161
+ def update_info(self, *args, **kwargs):
162
+ """Update the info with the passed in arguments"""
163
+ # Could either pass a dictionary or kwargs values
164
+ body = util.params_to_dict("update_info", args, kwargs)
165
+ self._validate_keys(body)
166
+ return self._invoke_container_api("set_{}_info", self.id, body)
167
+
168
+ def delete_info(self, *args):
169
+ """Delete the info fields listed in args"""
170
+ body = util.params_to_list(args)
171
+ return self._invoke_container_api("delete_{}_info_fields", self.id, body)
172
+
173
+
174
+ class TagMethods(object):
175
+ def add_tag(self, tag, **kwargs):
176
+ """Add the given tag to the object"""
177
+ return self._invoke_container_api("add_{}_tag", self.id, tag, **kwargs)
178
+
179
+ def rename_tag(self, tag, new_tag, **kwargs):
180
+ """Rename tag on object"""
181
+ return self._invoke_container_api("rename_{}_tag", self.id, tag, new_tag, **kwargs)
182
+
183
+ def delete_tag(self, tag, **kwargs):
184
+ """Delete tag from object"""
185
+ return self._invoke_container_api("delete_{}_tag", self.id, tag, **kwargs)
186
+
187
+
188
+ class NoteMethods(object):
189
+ def add_note(self, message, **kwargs):
190
+ """Add the given note to the object"""
191
+ return self._invoke_container_api("add_{}_note", self.id, message, **kwargs)
192
+
193
+ def delete_note(self, note_id, **kwargs):
194
+ """Delete the given note on the object"""
195
+ return self._invoke_container_api("delete_{}_note", self.id, note_id, **kwargs)
196
+
197
+
198
+ class PermissionMethods(object):
199
+ def add_permission(self, permission, **kwargs):
200
+ """Add a permission to a container"""
201
+ return self._invoke_container_api("add_{}_permission", self.id, permission, **kwargs)
202
+
203
+ def get_permission(self, user_id, **kwargs):
204
+ """Get a user's permission from container"""
205
+ return self._invoke_container_api("get_{}_user_permission", self.id, user_id, **kwargs)
206
+
207
+ def update_permission(self, user_id, permission, **kwargs):
208
+ """Update a user's permission on container"""
209
+ return self._invoke_container_api("modify_{}_user_permission", self.id, user_id, permission, **kwargs)
210
+
211
+ def delete_permission(self, user_id, **kwargs):
212
+ """Delete a user's permission from container"""
213
+ return self._invoke_container_api("delete_{}_user_permission", self.id, user_id, **kwargs)
214
+
215
+
216
+ class DownloadMethods(object):
217
+ def download_tar(self, dest_file, include_types=None, exclude_types=None, **kwargs):
218
+ """Download the container as a tarball to dest_file.
219
+
220
+ :param str dest_file: (required) The destination file on disk
221
+ :param list include_types: The optional list of types to include in the download (e.g. ['nifti'])
222
+ :param list exclude_types: The optional list of types to exclude from the download (e.g. ['dicom'])
223
+ :return: A summary of the download
224
+ """
225
+ return self._invoke_container_api(
226
+ "download_tar", self, dest_file, include_types=include_types, exclude_types=exclude_types, **kwargs
227
+ )
228
+
229
+ def download_zip(self, dest_file, include_types=None, exclude_types=None, **kwargs):
230
+ """Download the container as a zip archive to dest_file.
231
+
232
+ :param str dest_file: (required) The destination file on disk
233
+ :param list include_types: The optional list of types to include in the download (e.g. ['nifti'])
234
+ :param list exclude_types: The optional list of types to exclude from the download (e.g. ['dicom'])
235
+ :return: A summary of the download
236
+ """
237
+ return self._invoke_container_api(
238
+ "download_zip", self, dest_file, include_types=include_types, exclude_types=exclude_types, **kwargs
239
+ )
240
+
241
+
242
+ class AnalysisMethods(object):
243
+ def add_analysis(self, *args, **kwargs):
244
+ """Add an analysis to this container"""
245
+ fname = "add_{}_analysis"
246
+
247
+ body = util.params_to_dict(fname, args, kwargs)
248
+ analysis_id = self._invoke_container_api(fname, self.id, body)
249
+
250
+ if analysis_id:
251
+ return self._invoke_container_api("get_analysis", analysis_id)
252
+
253
+ return None
254
+
255
+
256
+ class FileMethods(object):
257
+ def _warn_if_keys_will_be_sanitized(self, key):
258
+ """Log warning message for offending characters"""
259
+ if "$" in key:
260
+ warnings.warn(f"Key {key} contains '$', which will be replaced with '-'.")
261
+ if "." in key:
262
+ warnings.warn(f"Key {key} contains '.', which will be replaced with '_'.")
263
+
264
+ def _check_list(self, values):
265
+ """Check list values"""
266
+ for val in values:
267
+ if isinstance(val, list):
268
+ self._check_list(val)
269
+ elif isinstance(val, dict):
270
+ self._validate_keys(val)
271
+
272
+ def _validate_keys(self, body):
273
+ """Recursively check for keys that contain offending characters"""
274
+ for key, values in body.items():
275
+ self._warn_if_keys_will_be_sanitized(key)
276
+ if isinstance(values, dict):
277
+ self._validate_keys(values)
278
+ elif isinstance(values, list):
279
+ self._check_list(values)
280
+
281
+ def upload_file(self, file, **kwargs):
282
+ """Upload a file to a container"""
283
+ return self._invoke_file_api("upload_file_to_{}", self.id, file, **kwargs)
284
+
285
+ def download_file(self, file_name, dest_file, **kwargs):
286
+ """Download file to the given path"""
287
+ return self._invoke_file_api("download_file_from_{}", self.id, file_name, dest_file, **kwargs)
288
+
289
+ def get_file_download_url(self, file_name, **kwargs):
290
+ """Get a ticketed download url for the file"""
291
+ return self._invoke_file_api("get_{}_download_url", self.id, file_name, **kwargs)
292
+
293
+ def read_file(self, file_name, **kwargs):
294
+ """Read the contents of the file"""
295
+ return self._invoke_file_api("download_file_from_{}_as_data", self.id, file_name, **kwargs)
296
+
297
+ def update_file(self, file_name, *args, **kwargs):
298
+ """Update a file's type and/or modality"""
299
+ body = util.params_to_dict("update_file", args, kwargs)
300
+ return self._invoke_file_api("modify_{}_file", self.id, file_name, body)
301
+
302
+ def delete_file(self, file_name, **kwargs):
303
+ """Delete file from the container"""
304
+ result = self._invoke_file_api("delete_{}_file", self.id, file_name, **kwargs)
305
+ # Delete from cache
306
+ files = getattr(self, "_files", None)
307
+ if files is not None:
308
+ for i, entry in enumerate(files):
309
+ if entry.name == file_name:
310
+ del files[i]
311
+ break
312
+ return result
313
+
314
+ def replace_file_info(self, file_name, info, **kwargs):
315
+ """Fully replace this file's info with the provided value"""
316
+ self._validate_keys(info)
317
+ return self._invoke_file_api("replace_{}_file_info", self.id, file_name, info, **kwargs)
318
+
319
+ def update_file_info(self, file_name, *args, **kwargs):
320
+ """Update the file's info with the passed in arguments"""
321
+ # Could either pass a dictionary or kwargs values
322
+ body = util.params_to_dict("update_file_info", args, kwargs)
323
+ self._validate_keys(body)
324
+ return self._invoke_file_api("set_{}_file_info", self.id, file_name, body)
325
+
326
+ def delete_file_info(self, file_name, *args, **kwargs):
327
+ """Delete the file info fields listed in args"""
328
+ body = util.params_to_list(args)
329
+ return self._invoke_file_api("delete_{}_file_info_fields", self.id, file_name, body, **kwargs)
330
+
331
+ def replace_file_classification(self, file_name, classification, modality=None, **kwargs):
332
+ """Fully replace a file's modality and classification"""
333
+ body = {"replace": classification}
334
+ if modality is not None:
335
+ body["modality"] = modality
336
+ return self._invoke_file_api("modify_{}_file_classification", self.id, file_name, body, **kwargs)
337
+
338
+ def update_file_classification(self, file_name, classification, **kwargs):
339
+ """Update a file's classification"""
340
+ return self._invoke_file_api("set_{}_file_classification", self.id, file_name, classification, **kwargs)
341
+
342
+ def delete_file_classification(self, file_name, classification, **kwargs):
343
+ """Delete a file's classification fields"""
344
+ return self._invoke_file_api(
345
+ "delete_{}_file_classification_fields", self.id, file_name, classification, **kwargs
346
+ )
347
+
348
+ def get_files(self, **kwargs):
349
+ """Get the files collection, retrieving the container if necessary"""
350
+ result = getattr(self, "_files", None)
351
+
352
+ if result is None:
353
+ obj = self._invoke_container_api("get_{}", self.id, **kwargs)
354
+ result = getattr(obj, "_files", None)
355
+ self._update_files_parent(result)
356
+
357
+ return result
358
+
359
+ def get_file(self, name, **kwargs):
360
+ """Get the first file entry with the given name, retrieving the container if necessary"""
361
+ for entry in self.get_files(**kwargs):
362
+ if entry.name == name:
363
+ return entry
364
+ return None
365
+
366
+ def file_ref(self, name, **kwargs):
367
+ """Get a reference to the given file"""
368
+ entry = self.get_file(**kwargs)
369
+ return entry.ref() if entry else None
370
+
371
+ def get_file_zip_info(self, file_name, **kwargs):
372
+ """Get zip member information for this file"""
373
+ return self._invoke_file_api("get_{}_file_zip_info", self.id, file_name, **kwargs)
374
+
375
+ def download_file_zip_member(self, file_name, member_path, dest_file, **kwargs):
376
+ """Download file's zip member to the given path"""
377
+ return self._invoke_file_api(
378
+ "download_file_from_{}", self.id, file_name, dest_file, member=member_path, **kwargs
379
+ )
380
+
381
+ def read_file_zip_member(self, file_name, member_path, **kwargs):
382
+ """Read contents of file's zip member"""
383
+ return self._invoke_file_api("download_file_from_{}_as_data", self.id, file_name, member=member_path, **kwargs)
384
+
385
+
386
+ class TimestampMethods(object):
387
+ @property
388
+ def local_timestamp(self):
389
+ """Get the timestamp in the local timezone"""
390
+ return self._localize_date("timestamp")
391
+
392
+ @property
393
+ def original_timestamp(self):
394
+ """Get the timestamp in the original timezone"""
395
+ if not self.timestamp:
396
+ return None
397
+
398
+ if not self.timezone:
399
+ raise ValueError("No original timezone was specified!")
400
+
401
+ import pytz
402
+
403
+ tz = pytz.timezone(self.timezone)
404
+ return self.timestamp.astimezone(tz)
405
+
406
+
407
+ class GroupMixin(ContainerBase, TagMethods, PermissionMethods):
408
+ container_type = "group"
409
+ child_types = ["projects"]
410
+
411
+ def add_project(self, *args, **kwargs):
412
+ """Add a project to this group"""
413
+ return self._add_child("project", args, kwargs)
414
+
415
+ def add_permission_template(self, permission, **kwargs):
416
+ """Add a permission template for a group"""
417
+ return self._invoke_container_api("add_group_permission_template", self.id, permission, **kwargs)
418
+
419
+ def get_permission_template(self, user_id, **kwargs):
420
+ """Get a user's permission template for a group"""
421
+ return self._invoke_container_api("get_group_user_permission_template", self.id, user_id, **kwargs)
422
+
423
+ def update_permission_template(self, user_id, permission, **kwargs):
424
+ """Update a user's permission template for a group"""
425
+ return self._invoke_container_api(
426
+ "modify_group_user_permission_template",
427
+ self.id,
428
+ user_id,
429
+ permission,
430
+ **kwargs,
431
+ )
432
+
433
+ def delete_permission_template(self, user_id, **kwargs):
434
+ """Delete a user's permission template from a group"""
435
+ return self._invoke_container_api("delete_group_user_permission_template", self.id, user_id, **kwargs)
436
+
437
+
438
+ class ProjectMixin(
439
+ ContainerBase,
440
+ TagMethods,
441
+ NoteMethods,
442
+ PermissionMethods,
443
+ FileMethods,
444
+ InfoMethods,
445
+ DownloadMethods,
446
+ AnalysisMethods,
447
+ ):
448
+ container_type = "project"
449
+ child_types = ["subjects", "sessions", "analyses", "files"]
450
+
451
+ def add_subject(self, *args, **kwargs):
452
+ """Add a subject to this project"""
453
+ return self._add_child("subject", args, kwargs)
454
+
455
+ def add_session(self, *args, **kwargs):
456
+ """Add a session to this project"""
457
+ return self._add_child("session", args, kwargs)
458
+
459
+
460
+ class SubjectMixin(ContainerBase, TagMethods, NoteMethods, FileMethods, InfoMethods, AnalysisMethods):
461
+ container_type = "subject"
462
+ child_types = ["sessions", "analyses", "files"]
463
+
464
+ def add_session(self, *args, **kwargs):
465
+ """Add a session to this subject"""
466
+ fname = "add_session"
467
+
468
+ body = util.params_to_dict(fname, args, kwargs)
469
+
470
+ # Adding a session requires project and subject id
471
+ body["project"] = self.project
472
+ body.setdefault("subject", {})
473
+ body["subject"]["_id"] = self.id
474
+
475
+ session_id = self._invoke_container_api(fname, body)
476
+ if session_id:
477
+ return self._invoke_container_api("get_session", session_id)
478
+ return None
479
+
480
+
481
+ class SessionMixin(
482
+ ContainerBase,
483
+ TagMethods,
484
+ NoteMethods,
485
+ FileMethods,
486
+ InfoMethods,
487
+ TimestampMethods,
488
+ DownloadMethods,
489
+ AnalysisMethods,
490
+ ):
491
+ container_type = "session"
492
+ child_types = ["acquisitions", "analyses", "files"]
493
+
494
+ def add_acquisition(self, *args, **kwargs):
495
+ """Add a acquisition to this session"""
496
+ return self._add_child("acquisition", args, kwargs)
497
+
498
+ @property
499
+ def age_years(self):
500
+ if self.age:
501
+ return util.seconds_to_years(self.age)
502
+ return self.age
503
+
504
+ @property
505
+ def age_months(self):
506
+ if self.age:
507
+ return util.seconds_to_months(self.age)
508
+ return self.age
509
+
510
+ @property
511
+ def age_weeks(self):
512
+ if self.age:
513
+ return util.seconds_to_weeks(self.age)
514
+ return self.age
515
+
516
+ @property
517
+ def age_days(self):
518
+ if self.age:
519
+ return util.seconds_to_days(self.age)
520
+ return self.age
521
+
522
+
523
+ class AcquisitionMixin(
524
+ ContainerBase,
525
+ NoteMethods,
526
+ TagMethods,
527
+ FileMethods,
528
+ InfoMethods,
529
+ TimestampMethods,
530
+ DownloadMethods,
531
+ AnalysisMethods,
532
+ ):
533
+ container_type = "acquisition"
534
+ child_types = ["analyses", "files"]
535
+
536
+
537
+ class AnalysisMixin(ContainerBase, NoteMethods, TagMethods, FileMethods, InfoMethods, DownloadMethods):
538
+ container_type = "analysis"
539
+ child_types = ["files"]
540
+ _file_group = "output"
541
+
542
+ def download_file(self, file_name, dest_file, **kwargs):
543
+ """Download file to the given path"""
544
+ if self.inputs and file_name in {f.name for f in self.inputs}:
545
+ return self._invoke_file_api("download_input_from_analysis", self.id, file_name, dest_file, **kwargs)
546
+ return self._invoke_file_api("download_file_from_analysis", self.id, file_name, dest_file, **kwargs)
547
+
548
+ def upload_file(self, file, **kwargs):
549
+ """Upload an output file to analysis"""
550
+ return self._invoke_container_api("upload_output_to_analysis", self.id, file, **kwargs)
551
+
552
+ def upload_output(self, file, **kwargs):
553
+ """Upload an output file to analysis"""
554
+ return self._invoke_container_api("upload_output_to_analysis", self.id, file, **kwargs)
555
+
556
+ def update_file_info(self, file_name, *args, **kwargs):
557
+ """Update the file's info with the passed in arguments"""
558
+ body = util.params_to_dict("update_file_info", args, kwargs)
559
+ # don't have analysis file methods in SDK yet, so use generic container method
560
+ return self._invoke_container_api("set_container_file_info", self.id, file_name, body)
561
+
562
+
563
+ class CollectionMixin(ContainerBase, NoteMethods, TagMethods, FileMethods, InfoMethods):
564
+ container_type = "collection"
565
+ child_types = ["sessions", "acquisitions", "analyses", "files"]
566
+
567
+ def add_sessions(self, *args, **kwargs):
568
+ session_ids = []
569
+ for arg in args:
570
+ if isinstance(arg, str):
571
+ session_ids.append(arg)
572
+ else:
573
+ session_ids.append(arg.id)
574
+
575
+ return self._invoke_container_api("add_sessions_to_{}", self.id, session_ids, **kwargs)
576
+
577
+ def add_acquisitions(self, *args, **kwargs):
578
+ acquisition_ids = []
579
+ for arg in args:
580
+ if isinstance(arg, str):
581
+ acquisition_ids.append(arg)
582
+ else:
583
+ acquisition_ids.append(arg.id)
584
+
585
+ return self._invoke_container_api("add_acquisitions_to_{}", self.id, acquisition_ids, **kwargs)
586
+
587
+
588
+ class FileMixin(ContainerBase):
589
+ container_type = "file"
590
+ child_types = []
591
+
592
+ def __init__(self):
593
+ super(FileMixin, self).__init__()
594
+ self._parent = None
595
+
596
+ @property
597
+ def parent(self, **kwargs):
598
+ if self._parent is None:
599
+ self._parent = self._invoke_container_api(f"get_{self._parent_ref.type}", self.parent_ref.id, **kwargs)
600
+ return self._parent
601
+
602
+ @property
603
+ def local_replaced(self):
604
+ """Get the replaced timestamp in local time"""
605
+ return self._localize_date("replaced")
606
+
607
+ def url(self, **kwargs):
608
+ """Get a ticketed download url for the file"""
609
+ return self.parent.get_file_download_url(self.name, **kwargs)
610
+
611
+ def download(self, dest_file, **kwargs):
612
+ """Download file to the given path"""
613
+ return self.parent.download_file(self.name, dest_file, **kwargs)
614
+
615
+ def read(self, **kwargs):
616
+ """Read the contents of the file"""
617
+ return self.parent.read_file(self.name, **kwargs)
618
+
619
+ def replace_info(self, info, **kwargs):
620
+ """Fully replace this file's info with the provided value"""
621
+ return self.parent.replace_file_info(self.name, info, **kwargs)
622
+
623
+ def update_info(self, *args, **kwargs):
624
+ """Update the file's info with the passed in arguments"""
625
+ return self.parent.update_file_info(self.name, *args, **kwargs)
626
+
627
+ def delete_info(self, *args, **kwargs):
628
+ """Delete the file info fields listed in args"""
629
+ return self.parent.delete_file_info(self.name, *args, **kwargs)
630
+
631
+ def update(self, *args, **kwargs):
632
+ """Update a file's type and/or modality"""
633
+ return self.parent.update_file(self.name, *args, **kwargs)
634
+
635
+ def replace_classification(self, classification, modality=None, **kwargs):
636
+ """Fully replace a file's modality and classification"""
637
+ return self.parent.replace_file_classification(self.name, classification, modality=modality, **kwargs)
638
+
639
+ def update_classification(self, classification, **kwargs):
640
+ """Update a file's classification"""
641
+ return self.parent.update_file_classification(self.name, classification, **kwargs)
642
+
643
+ def delete_classification(self, classification, **kwargs):
644
+ """Delete a file's classification fields"""
645
+ return self.parent.delete_file_classification(self.name, classification, **kwargs)
646
+
647
+ def set_tags(self, tags, **kwargs):
648
+ """Set the tags list on the file"""
649
+ return self._invoke_container_api("set_{}_tags", self.file_id, tags, **kwargs)
650
+
651
+ def add_tags(self, tags, **kwargs):
652
+ """Add the tags to the tags list on the file"""
653
+ return self._invoke_container_api("add_{}_tags", self.file_id, tags, **kwargs)
654
+
655
+ def add_tag(self, tag, **kwargs):
656
+ """Add the given tag to the file"""
657
+ return self._invoke_container_api("add_{}_tags", self.file_id, [tag], **kwargs)
658
+
659
+ def rename_tag(self, tag, new_tag, **kwargs):
660
+ """Rename tag on file"""
661
+ tags = self._invoke_container_api("get_file", self.file_id, **kwargs).tags or []
662
+ tags = [t if t != tag else new_tag for t in tags]
663
+ return self._invoke_container_api("set_{}_tags", self.file_id, tags, **kwargs)
664
+
665
+ def delete_tag(self, tag, **kwargs):
666
+ """Delete tag from file"""
667
+ tags = self._invoke_container_api("get_file", self.file_id, **kwargs).tags or []
668
+ tags = [t for t in tags if t != tag]
669
+ return self._invoke_container_api("set_{}_tags", self.file_id, tags, **kwargs)
670
+
671
+ def ref(self):
672
+ """Make a file reference"""
673
+ # Handle files retrieved via lookup
674
+ if hasattr(self, "parent_ref") and not self.parent:
675
+ ref = self.parent_ref.to_dict()
676
+ else:
677
+ ref = self.parent.ref()
678
+ ref["name"] = self.name
679
+ return ref
680
+
681
+ def reload(self, **kwargs):
682
+ """Reload the file."""
683
+ return self._invoke_container_api("get_file", self.file_id, version=self.version, **kwargs)
684
+
685
+ def get_zip_info(self, **kwargs):
686
+ """Get zip member information for this file"""
687
+ return self._invoke_container_api("get_file_zip_info", self.file_id, **kwargs)
688
+
689
+ def download_zip_member(self, member_path, dest_file, **kwargs):
690
+ """Download file's zip member to the given path"""
691
+ return self.parent.download_file_zip_member(self.name, member_path, dest_file, **kwargs)
692
+
693
+ def read_zip_member(self, member_path, **kwargs):
694
+ """Read contents of file's zip member"""
695
+ return self.parent.read_file_zip_member(self.name, member_path, **kwargs)
696
+
697
+
698
+ class JobMixin(ContainerBase):
699
+ container_type = "job"
700
+ child_types = []
701
+
702
+ def change_state(self, new_state, **kwargs):
703
+ """Change the state of the job to new_state"""
704
+ return self._invoke_container_api("change_job_state", self.id, new_state, **kwargs)
705
+
706
+ def get_logs(self, **kwargs):
707
+ """Get the job log entries"""
708
+ response = self._invoke_container_api("get_job_logs", self.id, **kwargs)
709
+ return response.logs
710
+
711
+ def print_logs(self, file=None, **kwargs):
712
+ """Print logs to file (or stdout, if file is not specified)"""
713
+ if file is None:
714
+ import sys
715
+
716
+ file = sys.stdout
717
+
718
+ for item in self.get_logs(**kwargs):
719
+ file.write(item.msg)
720
+
721
+ file.flush()
722
+
723
+ def update_priority(self, priority, **kwargs):
724
+ """Update priority of jobs"""
725
+ body = {"job_ids": [self.id], "priority": priority}
726
+ return self._invoke_container_api("update_jobs_priority", body, **kwargs)
727
+
728
+
729
+ class ResolverOutputMixin(object):
730
+ def _set_context(self, context):
731
+ """Set context and parent for files"""
732
+ parent = None
733
+
734
+ if self.path:
735
+ for node in self.path:
736
+ if getattr(node, "container_type", None) == "file":
737
+ node._parent = parent
738
+
739
+ if hasattr(node, "_set_context"):
740
+ node._set_context(context)
741
+
742
+ parent = node
743
+
744
+ if self.children:
745
+ for node in self.children:
746
+ if hasattr(node, "_set_context"):
747
+ node._set_context(context)
748
+
749
+ if getattr(node, "container_type", None) == "file":
750
+ node._parent = parent
751
+
752
+
753
+ class SearchResponseMixin(object):
754
+ def _set_context(self, context):
755
+ if self.group is not None:
756
+ self.group._set_context(context)
757
+
758
+ if self.project is not None:
759
+ self.project._set_context(context)
760
+
761
+ if self.subject is not None:
762
+ self.subject._set_context(context)
763
+
764
+ if self.session is not None:
765
+ self.session._set_context(context)
766
+
767
+ if self.acquisition is not None:
768
+ self.acquisition._set_context(context)
769
+
770
+ if self.collection is not None:
771
+ self.collection._set_context(context)
772
+
773
+ if self.analysis is not None:
774
+ self.analysis._set_context(context)
775
+
776
+ if self.file is not None:
777
+ # Set parent object on file
778
+ self.file._parent = self.parent
779
+
780
+
781
+ class BatchProposalMixin(ContextBase):
782
+ """Batch mixin that provides run/cancel shorthand"""
783
+
784
+ def run(self, **kwargs):
785
+ """Execute the batch proposal"""
786
+ return self._context.start_batch(self.id, **kwargs)
787
+
788
+
789
+ class BatchMixin(ContextBase):
790
+ """Batch mixin that provides cancel shorthand"""
791
+
792
+ def cancel(self, **kwargs):
793
+ """Cancel the batch proposal and any associated jobs"""
794
+ return self._context.cancel_batch(self.id, **kwargs)