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.
- flywheel/__init__.py +784 -0
- flywheel/api/__init__.py +46 -0
- flywheel/api/acquisitions_api.py +5014 -0
- flywheel/api/analyses_api.py +3848 -0
- flywheel/api/audit_trail_api.py +568 -0
- flywheel/api/auth_api.py +121 -0
- flywheel/api/batch_api.py +630 -0
- flywheel/api/bulk_api.py +140 -0
- flywheel/api/change_log_api.py +254 -0
- flywheel/api/collections_api.py +3913 -0
- flywheel/api/config_api.py +299 -0
- flywheel/api/container_tasks_api.py +137 -0
- flywheel/api/container_type_api.py +137 -0
- flywheel/api/containers_api.py +4784 -0
- flywheel/api/custom_filters_api.py +466 -0
- flywheel/api/data_view_executions_api.py +549 -0
- flywheel/api/dataexplorer_api.py +1192 -0
- flywheel/api/devices_api.py +1071 -0
- flywheel/api/dimse_api.py +814 -0
- flywheel/api/download_api.py +261 -0
- flywheel/api/files_api.py +1868 -0
- flywheel/api/form_responses_api.py +703 -0
- flywheel/api/gears_api.py +1875 -0
- flywheel/api/groups_api.py +2829 -0
- flywheel/api/jobs_api.py +2320 -0
- flywheel/api/jupyterlab_servers_api.py +245 -0
- flywheel/api/modalities_api.py +562 -0
- flywheel/api/packfiles_api.py +121 -0
- flywheel/api/projects_api.py +7820 -0
- flywheel/api/protocols_api.py +757 -0
- flywheel/api/reports_api.py +1057 -0
- flywheel/api/resolve_api.py +276 -0
- flywheel/api/roles_api.py +563 -0
- flywheel/api/sessions_api.py +5296 -0
- flywheel/api/site_api.py +1552 -0
- flywheel/api/staffing_pools_api.py +677 -0
- flywheel/api/subjects_api.py +5349 -0
- flywheel/api/tasks_api.py +897 -0
- flywheel/api/tree_api.py +266 -0
- flywheel/api/uids_api.py +140 -0
- flywheel/api/upload_api.py +842 -0
- flywheel/api/users_api.py +2142 -0
- flywheel/api/views_api.py +1089 -0
- flywheel/api_client.py +748 -0
- flywheel/client.py +291 -0
- flywheel/configuration.py +308 -0
- flywheel/drone_login.py +65 -0
- flywheel/file_spec.py +67 -0
- flywheel/finder.py +168 -0
- flywheel/flywheel.py +9867 -0
- flywheel/gear_context.py +374 -0
- flywheel/models/__init__.py +726 -0
- flywheel/models/access_level.py +30 -0
- flywheel/models/access_permission.py +197 -0
- flywheel/models/access_permission_output.py +192 -0
- flywheel/models/access_permission_update.py +166 -0
- flywheel/models/access_type.py +54 -0
- flywheel/models/accumulator.py +33 -0
- flywheel/models/acquisition.py +25 -0
- flywheel/models/acquisition_container_output.py +34 -0
- flywheel/models/acquisition_copy_input.py +223 -0
- flywheel/models/acquisition_input.py +297 -0
- flywheel/models/acquisition_list_output.py +767 -0
- flywheel/models/acquisition_modify_input.py +299 -0
- flywheel/models/acquisition_node.py +35 -0
- flywheel/models/acquisition_output.py +767 -0
- flywheel/models/acquisition_parents.py +241 -0
- flywheel/models/acquisition_template_options.py +275 -0
- flywheel/models/acquisition_upsert_input.py +383 -0
- flywheel/models/acquisition_upsert_output.py +243 -0
- flywheel/models/action.py +91 -0
- flywheel/models/adhoc_analysis_input.py +247 -0
- flywheel/models/analysis.py +25 -0
- flywheel/models/analysis_container_output.py +34 -0
- flywheel/models/analysis_files_create_ticket_output.py +241 -0
- flywheel/models/analysis_input.py +310 -0
- flywheel/models/analysis_input_legacy.py +25 -0
- flywheel/models/analysis_list_output.py +680 -0
- flywheel/models/analysis_list_output_inflated_job.py +650 -0
- flywheel/models/analysis_modify_input.py +191 -0
- flywheel/models/analysis_node.py +35 -0
- flywheel/models/analysis_output.py +683 -0
- flywheel/models/analysis_output_inflated_job.py +674 -0
- flywheel/models/analysis_parents.py +270 -0
- flywheel/models/analysis_update.py +25 -0
- flywheel/models/api_key_input_with_optional_label.py +191 -0
- flywheel/models/api_key_output.py +297 -0
- flywheel/models/as_storage.py +298 -0
- flywheel/models/assignee.py +192 -0
- flywheel/models/assignee_type.py +29 -0
- flywheel/models/audit_trail_report.py +486 -0
- flywheel/models/audit_trail_report_status.py +32 -0
- flywheel/models/auth0_auth_out.py +323 -0
- flywheel/models/auth0_options_out.py +319 -0
- flywheel/models/auth_out.py +357 -0
- flywheel/models/auth_session_output.py +272 -0
- flywheel/models/avatars.py +218 -0
- flywheel/models/aws_creds.py +191 -0
- flywheel/models/aws_storage.py +354 -0
- flywheel/models/azure_creds.py +190 -0
- flywheel/models/base_aet.py +245 -0
- flywheel/models/base_compute.py +426 -0
- flywheel/models/batch.py +360 -0
- flywheel/models/batch_cancel_output.py +36 -0
- flywheel/models/batch_create_filters.py +220 -0
- flywheel/models/batch_job_analysis_input.py +281 -0
- flywheel/models/batch_jobs_proposal_input.py +36 -0
- flywheel/models/batch_proposal.py +25 -0
- flywheel/models/batch_proposal_detail.py +36 -0
- flywheel/models/batch_proposal_input.py +25 -0
- flywheel/models/body.py +36 -0
- flywheel/models/body_regenerate_key_api_devices_device_id_key_post.py +25 -0
- flywheel/models/body_region.py +46 -0
- flywheel/models/bookmark.py +189 -0
- flywheel/models/bulk_move_input.py +272 -0
- flywheel/models/bulk_move_sessions.py +25 -0
- flywheel/models/callbacks_virus_scan_input.py +36 -0
- flywheel/models/cancelled_batch_output.py +163 -0
- flywheel/models/catalog_list_output.py +407 -0
- flywheel/models/central_out.py +299 -0
- flywheel/models/change.py +379 -0
- flywheel/models/change_log_container_type.py +38 -0
- flywheel/models/change_log_document.py +245 -0
- flywheel/models/change_method.py +33 -0
- flywheel/models/classic_batch_job_output.py +352 -0
- flywheel/models/classic_batch_job_output_inflated_jobs.py +379 -0
- flywheel/models/classic_batch_proposal_input.py +388 -0
- flywheel/models/classic_batch_proposal_output.py +471 -0
- flywheel/models/classification_add_delete.py +36 -0
- flywheel/models/classification_replace.py +36 -0
- flywheel/models/classification_update_input.py +36 -0
- flywheel/models/cohort.py +29 -0
- flywheel/models/collection.py +25 -0
- flywheel/models/collection_container_output.py +32 -0
- flywheel/models/collection_input.py +217 -0
- flywheel/models/collection_input_with_contents.py +248 -0
- flywheel/models/collection_node.py +192 -0
- flywheel/models/collection_node_level.py +31 -0
- flywheel/models/collection_operation.py +193 -0
- flywheel/models/collection_operation_type.py +29 -0
- flywheel/models/collection_output.py +639 -0
- flywheel/models/collection_with_stats.py +637 -0
- flywheel/models/column.py +286 -0
- flywheel/models/column_type.py +32 -0
- flywheel/models/common_classification.py +135 -0
- flywheel/models/common_deleted_count.py +25 -0
- flywheel/models/common_editions.py +25 -0
- flywheel/models/common_info.py +135 -0
- flywheel/models/common_join_origins.py +25 -0
- flywheel/models/common_key.py +36 -0
- flywheel/models/common_modified_count.py +25 -0
- flywheel/models/common_object_created.py +36 -0
- flywheel/models/common_project_settings.py +25 -0
- flywheel/models/common_settings.py +36 -0
- flywheel/models/complete_multipart_upload_output.py +189 -0
- flywheel/models/complete_s3_multipart_upload_input.py +241 -0
- flywheel/models/config_feature_map.py +36 -0
- flywheel/models/config_out.py +381 -0
- flywheel/models/config_output.py +36 -0
- flywheel/models/config_site_config_output.py +36 -0
- flywheel/models/config_site_settings.py +36 -0
- flywheel/models/config_site_settings_input.py +36 -0
- flywheel/models/conflict_types.py +30 -0
- flywheel/models/container_delete_reason.py +39 -0
- flywheel/models/container_filter.py +193 -0
- flywheel/models/container_id_view_input.py +521 -0
- flywheel/models/container_id_view_input_execute_and_save.py +308 -0
- flywheel/models/container_modify.py +536 -0
- flywheel/models/container_new_output.py +25 -0
- flywheel/models/container_node_min.py +350 -0
- flywheel/models/container_output.py +36 -0
- flywheel/models/container_output_with_files.py +283 -0
- flywheel/models/container_parents.py +311 -0
- flywheel/models/container_pipeline_input.py +536 -0
- flywheel/models/container_project_parents.py +25 -0
- flywheel/models/container_reference.py +193 -0
- flywheel/models/container_reference_with_label.py +219 -0
- flywheel/models/container_session_parents.py +25 -0
- flywheel/models/container_subject_parents.py +25 -0
- flywheel/models/container_type.py +39 -0
- flywheel/models/container_uidcheck.py +253 -0
- flywheel/models/container_update.py +135 -0
- flywheel/models/context_input.py +217 -0
- flywheel/models/copy_filter.py +299 -0
- flywheel/models/copy_status.py +32 -0
- flywheel/models/core_models_api_key_api_key_input.py +190 -0
- flywheel/models/core_models_audit_trail_create_report_input.py +273 -0
- flywheel/models/core_models_audit_trail_modify_report_input.py +167 -0
- flywheel/models/core_models_common_source.py +189 -0
- flywheel/models/core_models_jobs_api_key_input.py +191 -0
- flywheel/models/core_models_search_parent_type.py +33 -0
- flywheel/models/core_workflows_form_responses_models_form_parents.py +163 -0
- flywheel/models/core_workflows_form_responses_models_form_response_output.py +440 -0
- flywheel/models/core_workflows_reader_models_reader_task_parents.py +295 -0
- flywheel/models/creds.py +135 -0
- flywheel/models/curator.py +221 -0
- flywheel/models/current_user_output.py +707 -0
- flywheel/models/custom_field.py +437 -0
- flywheel/models/custom_form.py +244 -0
- flywheel/models/cvat_info.py +275 -0
- flywheel/models/cvat_settings.py +272 -0
- flywheel/models/cvat_settings_input.py +272 -0
- flywheel/models/cvat_sync_state.py +30 -0
- flywheel/models/daily_report_usage.py +565 -0
- flywheel/models/data_strategy.py +29 -0
- flywheel/models/data_view.py +25 -0
- flywheel/models/data_view_analysis_file_spec.py +221 -0
- flywheel/models/data_view_analysis_filter_spec.py +221 -0
- flywheel/models/data_view_column_alias.py +337 -0
- flywheel/models/data_view_column_spec.py +286 -0
- flywheel/models/data_view_execution.py +505 -0
- flywheel/models/data_view_execution_state.py +31 -0
- flywheel/models/data_view_file_spec.py +392 -0
- flywheel/models/data_view_group_by.py +166 -0
- flywheel/models/data_view_group_by_column.py +194 -0
- flywheel/models/data_view_name_filter_spec.py +194 -0
- flywheel/models/data_view_output.py +25 -0
- flywheel/models/data_view_save_data_view_input.py +25 -0
- flywheel/models/data_view_zip_filter_spec.py +223 -0
- flywheel/models/default_flywheel_role.py +30 -0
- flywheel/models/deid_log_skip_reason.py +29 -0
- flywheel/models/delete_by_search_query.py +253 -0
- flywheel/models/deleted_file.py +514 -0
- flywheel/models/deleted_result.py +194 -0
- flywheel/models/deprecated_action.py +29 -0
- flywheel/models/destination_container_type.py +30 -0
- flywheel/models/device.py +437 -0
- flywheel/models/device_admin_update.py +194 -0
- flywheel/models/device_create.py +219 -0
- flywheel/models/device_self_update.py +272 -0
- flywheel/models/device_status.py +36 -0
- flywheel/models/device_status_entry.py +221 -0
- flywheel/models/device_storage_strategy_update.py +193 -0
- flywheel/models/dimse_project_input.py +36 -0
- flywheel/models/dimse_project_output.py +36 -0
- flywheel/models/dimse_service_input.py +36 -0
- flywheel/models/dimse_service_output.py +36 -0
- flywheel/models/download.py +249 -0
- flywheel/models/download_container_filter.py +167 -0
- flywheel/models/download_container_filter_definition.py +222 -0
- flywheel/models/download_filter.py +221 -0
- flywheel/models/download_filter_definition.py +195 -0
- flywheel/models/download_format.py +29 -0
- flywheel/models/download_input.py +25 -0
- flywheel/models/download_node.py +189 -0
- flywheel/models/download_strategy.py +31 -0
- flywheel/models/download_ticket.py +36 -0
- flywheel/models/download_ticket_stub.py +249 -0
- flywheel/models/download_ticket_with_summary.py +36 -0
- flywheel/models/e_signature.py +242 -0
- flywheel/models/edition.py +169 -0
- flywheel/models/egress_device.py +597 -0
- flywheel/models/egress_device_page.py +219 -0
- flywheel/models/egress_provider.py +408 -0
- flywheel/models/egress_provider_id.py +164 -0
- flywheel/models/exchange_storage.py +243 -0
- flywheel/models/executor_info.py +353 -0
- flywheel/models/export_templates.py +195 -0
- flywheel/models/features.py +1838 -0
- flywheel/models/field_change.py +271 -0
- flywheel/models/field_change_log_document.py +245 -0
- flywheel/models/field_type.py +37 -0
- flywheel/models/file.py +1139 -0
- flywheel/models/file_classification_delta.py +245 -0
- flywheel/models/file_container_type.py +34 -0
- flywheel/models/file_entry.py +740 -0
- flywheel/models/file_export_templates.py +272 -0
- flywheel/models/file_format.py +33 -0
- flywheel/models/file_gear_info.py +215 -0
- flywheel/models/file_group.py +29 -0
- flywheel/models/file_list_output.py +1115 -0
- flywheel/models/file_modify_input.py +191 -0
- flywheel/models/file_move_input.py +221 -0
- flywheel/models/file_node.py +1138 -0
- flywheel/models/file_node_min.py +321 -0
- flywheel/models/file_origin.py +283 -0
- flywheel/models/file_output.py +1135 -0
- flywheel/models/file_parents.py +297 -0
- flywheel/models/file_reference.py +221 -0
- flywheel/models/file_suggestion.py +241 -0
- flywheel/models/file_template_options.py +299 -0
- flywheel/models/file_upsert_input.py +612 -0
- flywheel/models/file_upsert_origin.py +36 -0
- flywheel/models/file_upsert_output.py +1154 -0
- flywheel/models/file_version.py +190 -0
- flywheel/models/file_version_copy_of.py +273 -0
- flywheel/models/file_version_output.py +325 -0
- flywheel/models/file_via.py +245 -0
- flywheel/models/file_zip_entry.py +25 -0
- flywheel/models/file_zip_info.py +25 -0
- flywheel/models/filter.py +350 -0
- flywheel/models/filter_input.py +218 -0
- flywheel/models/filter_values.py +195 -0
- flywheel/models/filter_view.py +28 -0
- flywheel/models/fixed_file_version_input.py +216 -0
- flywheel/models/fixed_input.py +299 -0
- flywheel/models/form_definition.py +163 -0
- flywheel/models/form_response_base.py +311 -0
- flywheel/models/form_response_create.py +193 -0
- flywheel/models/gcp_creds.py +397 -0
- flywheel/models/gcp_storage.py +298 -0
- flywheel/models/gear.py +619 -0
- flywheel/models/gear_category.py +32 -0
- flywheel/models/gear_config.py +138 -0
- flywheel/models/gear_context_input.py +164 -0
- flywheel/models/gear_context_lookup.py +25 -0
- flywheel/models/gear_context_lookup_item.py +36 -0
- flywheel/models/gear_context_value_output.py +272 -0
- flywheel/models/gear_context_value_output_unfound.py +164 -0
- flywheel/models/gear_custom.py +135 -0
- flywheel/models/gear_directive.py +135 -0
- flywheel/models/gear_doc.py +25 -0
- flywheel/models/gear_document.py +332 -0
- flywheel/models/gear_document_input.py +303 -0
- flywheel/models/gear_document_legacy_input.py +302 -0
- flywheel/models/gear_environment.py +135 -0
- flywheel/models/gear_exchange.py +221 -0
- flywheel/models/gear_file_input.py +192 -0
- flywheel/models/gear_id_output.py +170 -0
- flywheel/models/gear_info.py +251 -0
- flywheel/models/gear_input_item.py +231 -0
- flywheel/models/gear_inputs.py +140 -0
- flywheel/models/gear_invocation.py +138 -0
- flywheel/models/gear_key_input.py +191 -0
- flywheel/models/gear_manifest.py +624 -0
- flywheel/models/gear_mixin.py +218 -0
- flywheel/models/gear_node.py +355 -0
- flywheel/models/gear_output_configuration.py +164 -0
- flywheel/models/gear_permissions.py +191 -0
- flywheel/models/gear_permissions_input.py +163 -0
- flywheel/models/gear_permissions_type.py +29 -0
- flywheel/models/gear_return_ticket.py +25 -0
- flywheel/models/gear_rule.py +653 -0
- flywheel/models/gear_rule_condition.py +219 -0
- flywheel/models/gear_rule_condition_type.py +37 -0
- flywheel/models/gear_rule_input.py +517 -0
- flywheel/models/gear_rule_modify_input.py +492 -0
- flywheel/models/gear_rule_output.py +652 -0
- flywheel/models/gear_save_submission.py +221 -0
- flywheel/models/gear_series.py +298 -0
- flywheel/models/gear_series_update.py +163 -0
- flywheel/models/gear_suggestion_output.py +301 -0
- flywheel/models/gear_ticket.py +245 -0
- flywheel/models/gear_ticket_output.py +163 -0
- flywheel/models/google_auth_out.py +299 -0
- flywheel/models/graph_filter.py +329 -0
- flywheel/models/group.py +25 -0
- flywheel/models/group_by.py +163 -0
- flywheel/models/group_by_column.py +36 -0
- flywheel/models/group_container_output.py +33 -0
- flywheel/models/group_input.py +248 -0
- flywheel/models/group_metadata_input.py +36 -0
- flywheel/models/group_node.py +34 -0
- flywheel/models/group_output.py +471 -0
- flywheel/models/group_report.py +218 -0
- flywheel/models/group_role.py +163 -0
- flywheel/models/group_settings_output.py +249 -0
- flywheel/models/group_update.py +249 -0
- flywheel/models/header_feature.py +37 -0
- flywheel/models/hierarchy_export_templates.py +272 -0
- flywheel/models/http_validation_error.py +167 -0
- flywheel/models/info.py +218 -0
- flywheel/models/info_add_remove.py +36 -0
- flywheel/models/info_container_type.py +35 -0
- flywheel/models/info_replace.py +36 -0
- flywheel/models/info_update_input.py +36 -0
- flywheel/models/ingress_provider.py +299 -0
- flywheel/models/ingress_providers.py +272 -0
- flywheel/models/ingress_site_settings.py +305 -0
- flywheel/models/ingress_update_provider.py +218 -0
- flywheel/models/inline_response200.py +163 -0
- flywheel/models/inline_response2001.py +171 -0
- flywheel/models/inline_response2002.py +163 -0
- flywheel/models/inline_response2003.py +36 -0
- flywheel/models/inline_response2005.py +25 -0
- flywheel/models/input_filter.py +221 -0
- flywheel/models/input_job.py +521 -0
- flywheel/models/input_job_profile.py +275 -0
- flywheel/models/inserted_id.py +163 -0
- flywheel/models/job.py +841 -0
- flywheel/models/job_analysis_input.py +273 -0
- flywheel/models/job_ask.py +301 -0
- flywheel/models/job_ask_response.py +195 -0
- flywheel/models/job_ask_response_job.py +978 -0
- flywheel/models/job_ask_return.py +25 -0
- flywheel/models/job_ask_return_criteria.py +245 -0
- flywheel/models/job_ask_state.py +25 -0
- flywheel/models/job_ask_state_response.py +163 -0
- flywheel/models/job_complete.py +220 -0
- flywheel/models/job_completion_input.py +25 -0
- flywheel/models/job_completion_ticket.py +25 -0
- flywheel/models/job_config.py +135 -0
- flywheel/models/job_config_input.py +272 -0
- flywheel/models/job_config_inputs.py +25 -0
- flywheel/models/job_config_output.py +25 -0
- flywheel/models/job_container_detail.py +25 -0
- flywheel/models/job_destination.py +189 -0
- flywheel/models/job_detail.py +925 -0
- flywheel/models/job_detail_container.py +190 -0
- flywheel/models/job_detail_file_entry.py +194 -0
- flywheel/models/job_detail_group.py +190 -0
- flywheel/models/job_detail_parent_info.py +303 -0
- flywheel/models/job_executor_info.py +369 -0
- flywheel/models/job_file_input.py +247 -0
- flywheel/models/job_file_input_list_output.py +247 -0
- flywheel/models/job_file_object.py +435 -0
- flywheel/models/job_file_object_list_output.py +407 -0
- flywheel/models/job_gear_match.py +25 -0
- flywheel/models/job_inputs_array_item.py +305 -0
- flywheel/models/job_inputs_item.py +242 -0
- flywheel/models/job_inputs_object.py +138 -0
- flywheel/models/job_list_entry.py +25 -0
- flywheel/models/job_list_output.py +979 -0
- flywheel/models/job_list_output_config.py +220 -0
- flywheel/models/job_log.py +189 -0
- flywheel/models/job_log_column.py +40 -0
- flywheel/models/job_log_record.py +192 -0
- flywheel/models/job_modify.py +193 -0
- flywheel/models/job_origin.py +190 -0
- flywheel/models/job_output.py +1005 -0
- flywheel/models/job_output_config.py +247 -0
- flywheel/models/job_parents.py +297 -0
- flywheel/models/job_priority.py +31 -0
- flywheel/models/job_priority_update.py +192 -0
- flywheel/models/job_profile.py +427 -0
- flywheel/models/job_profile_input.py +25 -0
- flywheel/models/job_request.py +221 -0
- flywheel/models/job_request_item.py +246 -0
- flywheel/models/job_request_item_type.py +31 -0
- flywheel/models/job_request_target.py +270 -0
- flywheel/models/job_state.py +32 -0
- flywheel/models/job_state_counts.py +25 -0
- flywheel/models/job_stats_by_state.py +25 -0
- flywheel/models/job_ticket_output.py +165 -0
- flywheel/models/job_transition_times.py +253 -0
- flywheel/models/job_version_info.py +135 -0
- flywheel/models/jobs_by_state.py +272 -0
- flywheel/models/jobs_list.py +166 -0
- flywheel/models/join_origin_device.py +164 -0
- flywheel/models/join_origin_job.py +219 -0
- flywheel/models/join_origin_user.py +189 -0
- flywheel/models/join_origins.py +223 -0
- flywheel/models/join_type.py +28 -0
- flywheel/models/jupyterhub_workspace.py +163 -0
- flywheel/models/jupyterlab_server_modify.py +275 -0
- flywheel/models/jupyterlab_server_origin.py +25 -0
- flywheel/models/jupyterlab_server_output.py +25 -0
- flywheel/models/jupyterlab_server_response.py +415 -0
- flywheel/models/jupyterlab_server_update.py +25 -0
- flywheel/models/ldap_sync.py +36 -0
- flywheel/models/ldap_sync_config.py +163 -0
- flywheel/models/ldap_sync_input.py +36 -0
- flywheel/models/ldap_sync_status.py +250 -0
- flywheel/models/legacy_api_key_output.py +271 -0
- flywheel/models/legacy_input.py +244 -0
- flywheel/models/legacy_usage_report.py +309 -0
- flywheel/models/legacys_usage_project_entry.py +194 -0
- flywheel/models/libs_workflows_models_parent_type.py +33 -0
- flywheel/models/libs_workflows_models_task_status.py +32 -0
- flywheel/models/local_storage.py +217 -0
- flywheel/models/location.py +189 -0
- flywheel/models/locked.py +219 -0
- flywheel/models/master_subject_code_dob_input.py +279 -0
- flywheel/models/master_subject_code_input.py +281 -0
- flywheel/models/master_subject_code_output.py +166 -0
- flywheel/models/matched_acquisition_output.py +518 -0
- flywheel/models/mfa_channel.py +30 -0
- flywheel/models/mfa_settings.py +167 -0
- flywheel/models/mixins.py +794 -0
- flywheel/models/ml_set_filter.py +194 -0
- flywheel/models/ml_type.py +30 -0
- flywheel/models/modality.py +250 -0
- flywheel/models/modality_input.py +244 -0
- flywheel/models/modality_modify.py +218 -0
- flywheel/models/modality_output.py +271 -0
- flywheel/models/modified_result.py +190 -0
- flywheel/models/modify_user_input.py +466 -0
- flywheel/models/move_conflict.py +300 -0
- flywheel/models/note.py +391 -0
- flywheel/models/note_input.py +165 -0
- flywheel/models/optional_input_policy.py +30 -0
- flywheel/models/order.py +29 -0
- flywheel/models/organ_system.py +64 -0
- flywheel/models/origin.py +193 -0
- flywheel/models/origin_type.py +35 -0
- flywheel/models/orphaned_count.py +163 -0
- flywheel/models/output_user_page.py +219 -0
- flywheel/models/packfile_cleanup_output.py +166 -0
- flywheel/models/packfile_removed_output.py +189 -0
- flywheel/models/page.py +216 -0
- flywheel/models/page_generic_file_output.py +219 -0
- flywheel/models/page_generic_filter.py +219 -0
- flywheel/models/page_generic_form_response_output.py +219 -0
- flywheel/models/page_generic_protocol.py +244 -0
- flywheel/models/page_generic_reader_task_output.py +244 -0
- flywheel/models/page_generic_staffing_pool.py +244 -0
- flywheel/models/parsed_query_response.py +194 -0
- flywheel/models/permission_access_permission.py +25 -0
- flywheel/models/premade_jobs_batch_job_output.py +298 -0
- flywheel/models/premade_jobs_batch_job_output_inflated_jobs.py +299 -0
- flywheel/models/premade_jobs_batch_proposal.py +334 -0
- flywheel/models/premade_jobs_batch_proposal_detail.py +166 -0
- flywheel/models/premade_jobs_batch_proposal_input.py +166 -0
- flywheel/models/project.py +25 -0
- flywheel/models/project_acquisition_upsert_input.py +25 -0
- flywheel/models/project_acquisition_upsert_output.py +25 -0
- flywheel/models/project_aet.py +331 -0
- flywheel/models/project_aet_input.py +248 -0
- flywheel/models/project_catalog_list_output.py +25 -0
- flywheel/models/project_contact.py +194 -0
- flywheel/models/project_container_output.py +41 -0
- flywheel/models/project_copy_input.py +245 -0
- flywheel/models/project_copy_output.py +215 -0
- flywheel/models/project_counters.py +346 -0
- flywheel/models/project_hierarchy_input.py +278 -0
- flywheel/models/project_hierarchy_output.py +222 -0
- flywheel/models/project_hierarchy_upsert_input.py +25 -0
- flywheel/models/project_hierarchy_upsert_output.py +25 -0
- flywheel/models/project_input.py +384 -0
- flywheel/models/project_institution.py +194 -0
- flywheel/models/project_list_output.py +897 -0
- flywheel/models/project_locking_reason.py +32 -0
- flywheel/models/project_modify.py +413 -0
- flywheel/models/project_node.py +42 -0
- flywheel/models/project_output.py +899 -0
- flywheel/models/project_parents.py +168 -0
- flywheel/models/project_report.py +463 -0
- flywheel/models/project_report_list.py +167 -0
- flywheel/models/project_session_upsert_input.py +25 -0
- flywheel/models/project_session_upsert_output.py +25 -0
- flywheel/models/project_settings_input.py +333 -0
- flywheel/models/project_settings_output.py +333 -0
- flywheel/models/project_settings_sharing.py +327 -0
- flywheel/models/project_settings_sharing_input.py +334 -0
- flywheel/models/project_settings_workspaces.py +167 -0
- flywheel/models/project_settings_workspaces_input.py +167 -0
- flywheel/models/project_share_level.py +29 -0
- flywheel/models/project_sharing_settings_project_contact.py +25 -0
- flywheel/models/project_sharing_settings_project_counters.py +36 -0
- flywheel/models/project_sharing_settings_project_institution.py +25 -0
- flywheel/models/project_sharing_settings_project_settings_input.py +25 -0
- flywheel/models/project_sharing_settings_project_settings_output.py +25 -0
- flywheel/models/project_sharing_settings_project_settings_sharing.py +25 -0
- flywheel/models/project_sharing_settings_project_settings_sharing_input.py +25 -0
- flywheel/models/project_sharing_settings_project_stats.py +36 -0
- flywheel/models/project_stats.py +270 -0
- flywheel/models/project_subject_upsert_input.py +25 -0
- flywheel/models/project_subject_upsert_output.py +25 -0
- flywheel/models/project_template.py +195 -0
- flywheel/models/project_template_input.py +195 -0
- flywheel/models/project_template_list_input.py +166 -0
- flywheel/models/project_template_requirement.py +36 -0
- flywheel/models/project_template_session_template.py +36 -0
- flywheel/models/project_upsert_origin.py +36 -0
- flywheel/models/protocol.py +515 -0
- flywheel/models/protocol_e_signature_config.py +191 -0
- flywheel/models/protocol_input.py +354 -0
- flywheel/models/protocol_modify.py +277 -0
- flywheel/models/protocol_status.py +30 -0
- flywheel/models/provider.py +461 -0
- flywheel/models/provider_access_type.py +29 -0
- flywheel/models/provider_class.py +29 -0
- flywheel/models/provider_deletion_status.py +189 -0
- flywheel/models/provider_input.py +25 -0
- flywheel/models/provider_links.py +282 -0
- flywheel/models/provider_type.py +34 -0
- flywheel/models/providers.py +277 -0
- flywheel/models/reader_batch_create.py +463 -0
- flywheel/models/reader_task.py +725 -0
- flywheel/models/reader_task_config.py +189 -0
- flywheel/models/reader_task_create.py +543 -0
- flywheel/models/reader_task_modify.py +303 -0
- flywheel/models/reader_task_output.py +752 -0
- flywheel/models/reader_task_parent_details.py +322 -0
- flywheel/models/report_access_log_context.py +301 -0
- flywheel/models/report_access_log_context_entry.py +194 -0
- flywheel/models/report_access_log_context_file_entry.py +165 -0
- flywheel/models/report_access_log_entry.py +624 -0
- flywheel/models/report_access_log_origin.py +194 -0
- flywheel/models/report_availability_list.py +167 -0
- flywheel/models/report_daily_usage_entry.py +501 -0
- flywheel/models/report_demographics_grid.py +36 -0
- flywheel/models/report_ethnicity_grid.py +252 -0
- flywheel/models/report_gender_count.py +222 -0
- flywheel/models/report_group_report.py +217 -0
- flywheel/models/report_legacy_usage_entry.py +36 -0
- flywheel/models/report_legacy_usage_project_entry.py +36 -0
- flywheel/models/report_project.py +25 -0
- flywheel/models/report_site.py +192 -0
- flywheel/models/report_time_period.py +193 -0
- flywheel/models/report_usage.py +630 -0
- flywheel/models/report_usage_entry.py +25 -0
- flywheel/models/resolve_input.py +163 -0
- flywheel/models/resolve_output.py +194 -0
- flywheel/models/resolver_acquisition_node.py +36 -0
- flywheel/models/resolver_analysis_node.py +36 -0
- flywheel/models/resolver_file_node.py +36 -0
- flywheel/models/resolver_gear_node.py +36 -0
- flywheel/models/resolver_group_node.py +36 -0
- flywheel/models/resolver_input.py +25 -0
- flywheel/models/resolver_node.py +182 -0
- flywheel/models/resolver_output.py +25 -0
- flywheel/models/resolver_project_node.py +36 -0
- flywheel/models/resolver_session_node.py +36 -0
- flywheel/models/resolver_subject_node.py +36 -0
- flywheel/models/role_input.py +192 -0
- flywheel/models/role_output.py +273 -0
- flywheel/models/role_permission.py +194 -0
- flywheel/models/role_permission_output.py +189 -0
- flywheel/models/role_permission_update.py +163 -0
- flywheel/models/role_type.py +32 -0
- flywheel/models/role_update.py +194 -0
- flywheel/models/roles_backwards_compatible_role_assignment.py +36 -0
- flywheel/models/roles_group_role_pool_input.py +36 -0
- flywheel/models/roles_role.py +36 -0
- flywheel/models/roles_role_assignment.py +195 -0
- flywheel/models/roles_role_input.py +36 -0
- flywheel/models/rule.py +467 -0
- flywheel/models/rule_any.py +216 -0
- flywheel/models/s3_addressing_style.py +29 -0
- flywheel/models/s3_compat_storage.py +381 -0
- flywheel/models/save_search.py +298 -0
- flywheel/models/save_search_input.py +219 -0
- flywheel/models/save_search_output.py +301 -0
- flywheel/models/save_search_page.py +219 -0
- flywheel/models/save_search_parent.py +192 -0
- flywheel/models/save_search_update.py +194 -0
- flywheel/models/search_acquisition_response.py +252 -0
- flywheel/models/search_analysis_response.py +254 -0
- flywheel/models/search_collection_response.py +254 -0
- flywheel/models/search_file_response.py +312 -0
- flywheel/models/search_group_response.py +196 -0
- flywheel/models/search_parent_acquisition.py +47 -0
- flywheel/models/search_parent_analysis.py +47 -0
- flywheel/models/search_parent_collection.py +46 -0
- flywheel/models/search_parent_project.py +54 -0
- flywheel/models/search_parent_response.py +213 -0
- flywheel/models/search_parent_session.py +48 -0
- flywheel/models/search_parent_subject.py +48 -0
- flywheel/models/search_parse_error.py +252 -0
- flywheel/models/search_parse_search_query_result.py +36 -0
- flywheel/models/search_project_response.py +196 -0
- flywheel/models/search_query.py +337 -0
- flywheel/models/search_query_suggestions.py +36 -0
- flywheel/models/search_response.py +448 -0
- flywheel/models/search_return_type.py +33 -0
- flywheel/models/search_save_search.py +36 -0
- flywheel/models/search_save_search_input.py +36 -0
- flywheel/models/search_save_search_parent.py +36 -0
- flywheel/models/search_save_search_update.py +36 -0
- flywheel/models/search_session_response.py +252 -0
- flywheel/models/search_status.py +166 -0
- flywheel/models/search_structured_search_query.py +25 -0
- flywheel/models/search_subject_response.py +225 -0
- flywheel/models/search_suggestion.py +36 -0
- flywheel/models/select_item.py +190 -0
- flywheel/models/server_state.py +303 -0
- flywheel/models/service_aet.py +301 -0
- flywheel/models/service_aet_input.py +276 -0
- flywheel/models/session.py +25 -0
- flywheel/models/session_container_output.py +35 -0
- flywheel/models/session_copy_input.py +253 -0
- flywheel/models/session_embedded_subject.py +299 -0
- flywheel/models/session_input.py +431 -0
- flywheel/models/session_list_output.py +897 -0
- flywheel/models/session_metadata_input.py +36 -0
- flywheel/models/session_modify.py +464 -0
- flywheel/models/session_node.py +36 -0
- flywheel/models/session_output.py +897 -0
- flywheel/models/session_parents.py +220 -0
- flywheel/models/session_template_options.py +221 -0
- flywheel/models/session_template_recalc_output.py +165 -0
- flywheel/models/session_upsert_input.py +464 -0
- flywheel/models/session_upsert_output.py +243 -0
- flywheel/models/sharing_filter_options.py +345 -0
- flywheel/models/signed_fs_upload_output.py +189 -0
- flywheel/models/signed_url_cleanup_input.py +189 -0
- flywheel/models/signed_url_upload_input.py +190 -0
- flywheel/models/signed_url_upload_output.py +349 -0
- flywheel/models/site.py +623 -0
- flywheel/models/site_report.py +194 -0
- flywheel/models/site_settings.py +385 -0
- flywheel/models/sort.py +192 -0
- flywheel/models/stable_api_key_input.py +25 -0
- flywheel/models/staffing_pool.py +324 -0
- flywheel/models/staffing_pool_create.py +216 -0
- flywheel/models/staffing_pool_list.py +164 -0
- flywheel/models/staffing_pool_modify.py +218 -0
- flywheel/models/state.py +32 -0
- flywheel/models/static_compute.py +218 -0
- flywheel/models/status_transitions.py +245 -0
- flywheel/models/status_type.py +31 -0
- flywheel/models/status_value.py +31 -0
- flywheel/models/storage_strategy.py +30 -0
- flywheel/models/storage_strategy_config.py +194 -0
- flywheel/models/structured_query.py +165 -0
- flywheel/models/structured_query_suggestions.py +196 -0
- flywheel/models/structured_query_value_suggestion.py +247 -0
- flywheel/models/subject.py +34 -0
- flywheel/models/subject_container_output.py +36 -0
- flywheel/models/subject_copy_input.py +223 -0
- flywheel/models/subject_input.py +627 -0
- flywheel/models/subject_modify.py +684 -0
- flywheel/models/subject_node.py +37 -0
- flywheel/models/subject_output.py +1008 -0
- flywheel/models/subject_output_for_list.py +1005 -0
- flywheel/models/subject_parents.py +194 -0
- flywheel/models/subject_role_permission.py +194 -0
- flywheel/models/subject_state.py +30 -0
- flywheel/models/subject_template_options.py +191 -0
- flywheel/models/subject_upsert_input.py +573 -0
- flywheel/models/subject_upsert_output.py +216 -0
- flywheel/models/sync_user_input.py +322 -0
- flywheel/models/tag.py +165 -0
- flywheel/models/task_assign.py +194 -0
- flywheel/models/task_facet.py +29 -0
- flywheel/models/task_parent_ref.py +245 -0
- flywheel/models/task_parent_ref_input.py +219 -0
- flywheel/models/task_priority.py +31 -0
- flywheel/models/task_submission.py +189 -0
- flywheel/models/therapeutic_area.py +60 -0
- flywheel/models/transitions.py +272 -0
- flywheel/models/tree_container_request_spec.py +281 -0
- flywheel/models/tree_graph.py +142 -0
- flywheel/models/tree_graph_connection.py +244 -0
- flywheel/models/tree_graph_connections.py +142 -0
- flywheel/models/tree_graph_node.py +166 -0
- flywheel/models/tree_request.py +25 -0
- flywheel/models/tree_response_item.py +142 -0
- flywheel/models/type_str.py +31 -0
- flywheel/models/uid_check_input_acquisitions.py +244 -0
- flywheel/models/uid_check_input_sessions.py +244 -0
- flywheel/models/uid_check_output.py +191 -0
- flywheel/models/upload_complete_s3_multipart_input.py +25 -0
- flywheel/models/upload_complete_s3_multipart_output.py +25 -0
- flywheel/models/upload_signed_fs_file_upload_output.py +36 -0
- flywheel/models/upload_signed_upload_url_input.py +36 -0
- flywheel/models/upload_signed_upload_url_output.py +36 -0
- flywheel/models/upload_ticket_output.py +215 -0
- flywheel/models/upload_token_output.py +163 -0
- flywheel/models/upsert_result.py +31 -0
- flywheel/models/user.py +760 -0
- flywheel/models/user_api_key.py +220 -0
- flywheel/models/user_input.py +461 -0
- flywheel/models/user_jobs.py +219 -0
- flywheel/models/user_jobs_output.py +25 -0
- flywheel/models/user_output.py +36 -0
- flywheel/models/user_output_id.py +163 -0
- flywheel/models/user_preferences.py +135 -0
- flywheel/models/user_wechat.py +135 -0
- flywheel/models/validation_error.py +215 -0
- flywheel/models/validation_rule.py +190 -0
- flywheel/models/version.py +363 -0
- flywheel/models/version_output.py +25 -0
- flywheel/models/view_id_output.py +164 -0
- flywheel/models/view_output.py +440 -0
- flywheel/models/viewer_app.py +381 -0
- flywheel/models/viewer_app_input.py +382 -0
- flywheel/models/viewer_app_type.py +29 -0
- flywheel/models/virus_scan.py +166 -0
- flywheel/models/virus_scan_state.py +30 -0
- flywheel/models/work_in_progress_features.py +135 -0
- flywheel/models/zipfile_info.py +192 -0
- flywheel/models/zipfile_member_info.py +241 -0
- flywheel/partial_reader.py +50 -0
- flywheel/rest.py +352 -0
- flywheel/util.py +95 -0
- flywheel/view_builder.py +449 -0
- flywheel_sdk-21.2.0.dist-info/METADATA +42 -0
- flywheel_sdk-21.2.0.dist-info/RECORD +772 -0
- flywheel_sdk-21.2.0.dist-info/WHEEL +4 -0
- 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)
|