aipscan 0.9.0.dev4__tar.gz → 0.9.0.dev10__tar.gz
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.
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/.gitignore +1 -0
- aipscan-0.9.0.dev10/AIPscan/Aggregator/celery_helpers.py +46 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/database_helpers.py +2 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/mets_parse_helpers.py +18 -10
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/task_helpers.py +0 -12
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tasks.py +13 -8
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/templates/storage_service.html +2 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/test_database_helpers.py +3 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/test_task_helpers.py +0 -15
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/test_tasks.py +50 -33
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/views.py +6 -6
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/__init__.py +3 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/report_data.py +2 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_largest_aips.py +2 -1
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_largest_files.py +3 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/aips.html +3 -3
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_ingest_log_gantt.html +1 -1
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_ingest_log_tabular.html +6 -6
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/reports.html +4 -4
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/views.py +13 -12
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/__init__.py +12 -1
- aipscan-0.9.0.dev10/AIPscan/cli.py +168 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/decorators.py +3 -1
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/helpers.py +41 -5
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/models.py +1 -1
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/js/aggregator/storage_service.js +22 -1
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/templates/report_base.html +3 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/test_helpers.py +7 -0
- aipscan-0.9.0.dev10/AIPscan/tests/test_cli.py +133 -0
- aipscan-0.9.0.dev10/AIPscan/tests/test_helpers.py +65 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/tests/test_models.py +3 -2
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/PKG-INFO +15 -15
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/README.md +13 -14
- aipscan-0.9.0.dev10/build_config/entry/report_base.entry.js +5 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/plot_formats_count.config.js +4 -1
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/package-lock.json +15 -15
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/package.json +3 -3
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/pyproject.toml +4 -2
- aipscan-0.9.0.dev4/AIPscan/Aggregator/celery_helpers.py +0 -12
- aipscan-0.9.0.dev4/AIPscan/tests/test_helpers.py +0 -29
- aipscan-0.9.0.dev4/build_config/entry/report_base.entry.js +0 -3
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/API/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/API/fields.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/API/namespace_data.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/API/namespace_infos.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/API/namespace_report_data.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/API/views.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/forms.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/templates/confirm.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/templates/edit_storage_service.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/templates/result_message.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/templates/storage_services.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/fixtures/features_mets/features-mets-added-agents.xml +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/fixtures/features_mets/features-mets.xml +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/fixtures/images_mets/images.xml +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/fixtures/iso_mets/iso_mets.xml +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/fixtures/original_name_mets/dataverse_example.xml +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/fixtures/original_name_mets/document-empty-dirs.xml +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/fixtures/package_json/packages.json +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/test_mets.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/test_types.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/test_views.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/types.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/data.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/fields.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/report_data_typesense.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_agents_transfers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_aip_contents.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_aips_by_format.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_aips_by_puid.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_format_versions_count.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_formats_count.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_preservation_derivatives.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Data/tests/test_storage_locations.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Home/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Home/views.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/database_helpers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/helpers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_aip_contents.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_aips_by_format.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_aips_by_puid.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_format_versions_count.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_formats_count.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_ingest_log.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_largest_aips.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_largest_files.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_preservation_derivatives.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/report_storage_locations.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/request_params.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/aip.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/chart_formats_count.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/file.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/plot_formats_count.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_aip_contents.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_aips_by_format.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_aips_by_puid.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_buttons.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_buttons_print_only.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_format_versions_count.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_formats_count.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_largest_aips.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_largest_files.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_preservation_derivatives.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_storage_locations.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/templates/report_storage_locations_usage_over_time.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/fixtures/storage_location_usage_cumulative_aips.csv +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/fixtures/storage_location_usage_cumulative_files.csv +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/fixtures/storage_location_usage_cumulative_size.csv +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/fixtures/storage_location_usage_differential_aips.csv +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/fixtures/storage_location_usage_differential_files.csv +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/fixtures/storage_location_usage_differential_size.csv +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_aip_contents.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_aips_by_file_format.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_aips_by_puid.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_format_versions_count.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_formats_count.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_helpers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_ingest_log.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_largest_aips.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_largest_files.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_preservation_derivatives.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_storage_locations.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_update_dates.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Reporter/tests/test_views.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/User/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/User/forms.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/User/views.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/celery.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/config.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/conftest.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/navbar.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/run.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/css/custom.css +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/css/style_ingest_log.css +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/favicon.ico +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/js/report.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/js/reporter/aips.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/js/reporter/chart_formats_count.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/js/reporter/plot_formats_count.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/static/js/reporter/reports.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/templates/base.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/templates/error/404.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/templates/partials/navbar.html +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/tests/__init__.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/tests/test_typesense_helpers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/tests/test_typsense_test_helpers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/typesense_helpers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/typesense_test_helpers.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/worker.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/LICENSE +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build.py +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/base.config.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/chart_formats_count.config.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/entry/base.entry.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/entry/chart_formats_count.entry.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/entry/plot_formats_count.entry.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/entry/shared/base_shared.js +0 -0
- {aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/build_config/report_base.config.js +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from functools import wraps
|
|
3
|
+
|
|
4
|
+
from AIPscan import db
|
|
5
|
+
from AIPscan.models import package_tasks
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def write_celery_update(package_lists_task, workflow_coordinator):
|
|
11
|
+
# Write status update to celery model.
|
|
12
|
+
package_task = package_tasks(
|
|
13
|
+
package_task_id=package_lists_task.id,
|
|
14
|
+
workflow_coordinator_id=workflow_coordinator.request.id,
|
|
15
|
+
)
|
|
16
|
+
db.session.add(package_task)
|
|
17
|
+
db.session.commit()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def with_db_session(func):
|
|
21
|
+
"""Ensure the scoped session is cleaned up around each call."""
|
|
22
|
+
|
|
23
|
+
@wraps(func)
|
|
24
|
+
def wrapper(*args, **kwargs):
|
|
25
|
+
func_name = func.__name__
|
|
26
|
+
try:
|
|
27
|
+
return func(*args, **kwargs)
|
|
28
|
+
except Exception:
|
|
29
|
+
logger.exception("Unhandled exception in %s", func_name)
|
|
30
|
+
try:
|
|
31
|
+
db.session.rollback()
|
|
32
|
+
logger.debug("Rolled back session after error in %s", func_name)
|
|
33
|
+
except Exception:
|
|
34
|
+
logger.exception(
|
|
35
|
+
"Failed to rollback session after error in %s", func_name
|
|
36
|
+
)
|
|
37
|
+
raise
|
|
38
|
+
finally:
|
|
39
|
+
try:
|
|
40
|
+
db.session.remove()
|
|
41
|
+
except Exception:
|
|
42
|
+
logger.exception(
|
|
43
|
+
"Failed to dispose session after call to %s", func_name
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return wrapper
|
|
@@ -300,7 +300,7 @@ def _add_normalization_date(file_id):
|
|
|
300
300
|
|
|
301
301
|
:param file_id: File ID
|
|
302
302
|
"""
|
|
303
|
-
file_ =
|
|
303
|
+
file_ = db.session.get(File, file_id)
|
|
304
304
|
creation_event = Event.query.filter_by(file_id=file_.id, type="creation").first()
|
|
305
305
|
if creation_event is not None:
|
|
306
306
|
file_.date_created = creation_event.date
|
|
@@ -309,7 +309,7 @@ def _add_normalization_date(file_id):
|
|
|
309
309
|
|
|
310
310
|
def _add_premis_object_xml(fs_entry, file_id):
|
|
311
311
|
"""Add string representation of PREMIS Object to File object."""
|
|
312
|
-
file_ =
|
|
312
|
+
file_ = db.session.get(File, file_id)
|
|
313
313
|
|
|
314
314
|
if hasattr(fs_entry, "amdsecs"):
|
|
315
315
|
for ss in fs_entry.amdsecs[0].subsections:
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
information from an AIP METS file.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import os
|
|
6
|
+
|
|
5
7
|
import lxml
|
|
6
8
|
import metsrw
|
|
7
9
|
import requests
|
|
8
10
|
|
|
9
11
|
from AIPscan.Aggregator.task_helpers import create_numbered_subdirs
|
|
10
12
|
from AIPscan.Aggregator.task_helpers import get_mets_url
|
|
11
|
-
from AIPscan.
|
|
13
|
+
from AIPscan.helpers import stream_write_and_hash
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class METSError(Exception):
|
|
@@ -83,17 +85,23 @@ def get_aip_original_name(mets):
|
|
|
83
85
|
def download_mets(
|
|
84
86
|
storage_service, package_uuid, relative_path_to_mets, timestamp, package_list_no
|
|
85
87
|
):
|
|
86
|
-
"""Download METS from the storage service.
|
|
88
|
+
"""Download METS from the storage service.
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
)
|
|
90
|
+
The METS document is streamed directly to disk while its SHA256 digest is
|
|
91
|
+
computed so that the caller can avoid re-reading the file.
|
|
92
|
+
"""
|
|
92
93
|
|
|
93
|
-
# Create a directory to download the METS to.
|
|
94
94
|
numbered_subdir = create_numbered_subdirs(timestamp, package_list_no)
|
|
95
|
+
download_file = os.path.join(numbered_subdir, f"METS.{package_uuid}.xml")
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
mets_response = requests.get(
|
|
98
|
+
get_mets_url(storage_service, package_uuid, relative_path_to_mets),
|
|
99
|
+
stream=True,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
try:
|
|
103
|
+
mets_hash = stream_write_and_hash(mets_response, download_file)
|
|
104
|
+
finally:
|
|
105
|
+
mets_response.close()
|
|
98
106
|
|
|
99
|
-
return download_file
|
|
107
|
+
return download_file, mets_hash
|
|
@@ -142,17 +142,5 @@ def create_numbered_subdirs(timestamp, package_list_number):
|
|
|
142
142
|
return numbered_subdir
|
|
143
143
|
|
|
144
144
|
|
|
145
|
-
def write_mets(http_response, package_uuid, subdir):
|
|
146
|
-
"""Given a http response containing our METS data, create the path
|
|
147
|
-
we want to store our METS at, and then stream the response into a
|
|
148
|
-
file.
|
|
149
|
-
"""
|
|
150
|
-
mets_file = f"METS.{package_uuid}.xml"
|
|
151
|
-
download_file = os.path.join(subdir, mets_file)
|
|
152
|
-
with open(download_file, "wb") as file:
|
|
153
|
-
file.write(http_response.content)
|
|
154
|
-
return download_file
|
|
155
|
-
|
|
156
|
-
|
|
157
145
|
def summarize_fetch_job_results(fetch_job):
|
|
158
146
|
return f"aips: '{fetch_job.total_aips}'; sips: '{fetch_job.total_sips}'; dips: '{fetch_job.total_dips}'; deleted: '{fetch_job.total_deleted_aips}'; replicated: '{fetch_job.total_replicas}'"
|
|
@@ -9,6 +9,7 @@ from celery.utils.log import get_task_logger
|
|
|
9
9
|
from AIPscan import db
|
|
10
10
|
from AIPscan import typesense_helpers
|
|
11
11
|
from AIPscan.Aggregator import database_helpers
|
|
12
|
+
from AIPscan.Aggregator.celery_helpers import with_db_session
|
|
12
13
|
from AIPscan.Aggregator.celery_helpers import write_celery_update
|
|
13
14
|
from AIPscan.Aggregator.mets_parse_helpers import METSError
|
|
14
15
|
from AIPscan.Aggregator.mets_parse_helpers import download_mets
|
|
@@ -19,7 +20,6 @@ from AIPscan.Aggregator.task_helpers import parse_package_list_file
|
|
|
19
20
|
from AIPscan.Aggregator.task_helpers import process_package_object
|
|
20
21
|
from AIPscan.Aggregator.task_helpers import summarize_fetch_job_results
|
|
21
22
|
from AIPscan.celery import celery
|
|
22
|
-
from AIPscan.helpers import file_sha256_hash
|
|
23
23
|
from AIPscan.models import AIP
|
|
24
24
|
from AIPscan.models import Agent
|
|
25
25
|
from AIPscan.models import FetchJob
|
|
@@ -63,7 +63,7 @@ def start_mets_task(
|
|
|
63
63
|
"""Initiate a get_mets task worker and record the event in the
|
|
64
64
|
celery database.
|
|
65
65
|
"""
|
|
66
|
-
storage_service =
|
|
66
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
67
67
|
storage_location = database_helpers.create_or_update_storage_location(
|
|
68
68
|
current_location, storage_service
|
|
69
69
|
)
|
|
@@ -111,6 +111,7 @@ def delete_aip(uuid):
|
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
@celery.task(bind=True)
|
|
114
|
+
@with_db_session
|
|
114
115
|
def workflow_coordinator(
|
|
115
116
|
self, timestamp, storage_service_id, fetch_job_id, packages_directory
|
|
116
117
|
):
|
|
@@ -179,6 +180,7 @@ def make_request(request_url, request_url_without_api_key):
|
|
|
179
180
|
|
|
180
181
|
|
|
181
182
|
@celery.task(bind=True)
|
|
183
|
+
@with_db_session
|
|
182
184
|
def package_lists_request(self, storage_service_id, timestamp, packages_directory):
|
|
183
185
|
"""Request package lists from the storage service. Package lists
|
|
184
186
|
will contain details of the AIPs that we want to download.
|
|
@@ -188,7 +190,7 @@ def package_lists_request(self, storage_service_id, timestamp, packages_director
|
|
|
188
190
|
COUNT = "total_count"
|
|
189
191
|
IN_PROGRESS = "IN PROGRESS"
|
|
190
192
|
|
|
191
|
-
storage_service =
|
|
193
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
192
194
|
|
|
193
195
|
(
|
|
194
196
|
base_url,
|
|
@@ -245,6 +247,7 @@ def start_index_task(fetch_job_id):
|
|
|
245
247
|
|
|
246
248
|
|
|
247
249
|
@celery.task()
|
|
250
|
+
@with_db_session
|
|
248
251
|
def index_task(fetch_job_id):
|
|
249
252
|
# Update Typesense index
|
|
250
253
|
typesense_helpers.initialize_index()
|
|
@@ -268,6 +271,7 @@ def index_task(fetch_job_id):
|
|
|
268
271
|
|
|
269
272
|
|
|
270
273
|
@celery.task()
|
|
274
|
+
@with_db_session
|
|
271
275
|
def get_mets(
|
|
272
276
|
package_uuid,
|
|
273
277
|
aip_size,
|
|
@@ -300,8 +304,8 @@ def get_mets(
|
|
|
300
304
|
tasklogger = customlogger
|
|
301
305
|
|
|
302
306
|
# Download METS file
|
|
303
|
-
storage_service =
|
|
304
|
-
download_file = download_mets(
|
|
307
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
308
|
+
download_file, mets_hash = download_mets(
|
|
305
309
|
storage_service,
|
|
306
310
|
package_uuid,
|
|
307
311
|
relative_path_to_mets,
|
|
@@ -309,7 +313,6 @@ def get_mets(
|
|
|
309
313
|
package_list_no,
|
|
310
314
|
)
|
|
311
315
|
mets_name = os.path.basename(download_file)
|
|
312
|
-
mets_hash = file_sha256_hash(download_file)
|
|
313
316
|
|
|
314
317
|
# If METS file's hash matches an existing value, this is a duplicate of an
|
|
315
318
|
# existing AIP and we can safely ignore it.
|
|
@@ -370,8 +373,9 @@ def get_mets(
|
|
|
370
373
|
|
|
371
374
|
|
|
372
375
|
@celery.task()
|
|
376
|
+
@with_db_session
|
|
373
377
|
def delete_fetch_job(fetch_job_id):
|
|
374
|
-
fetch_job =
|
|
378
|
+
fetch_job = db.session.get(FetchJob, fetch_job_id)
|
|
375
379
|
if os.path.exists(fetch_job.download_directory):
|
|
376
380
|
shutil.rmtree(fetch_job.download_directory)
|
|
377
381
|
db.session.delete(fetch_job)
|
|
@@ -379,8 +383,9 @@ def delete_fetch_job(fetch_job_id):
|
|
|
379
383
|
|
|
380
384
|
|
|
381
385
|
@celery.task()
|
|
386
|
+
@with_db_session
|
|
382
387
|
def delete_storage_service(storage_service_id):
|
|
383
|
-
storage_service =
|
|
388
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
384
389
|
mets_fetch_jobs = FetchJob.query.filter_by(
|
|
385
390
|
storage_service_id=storage_service_id
|
|
386
391
|
).all()
|
{aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/templates/storage_service.html
RENAMED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
</td>
|
|
22
22
|
<td>
|
|
23
23
|
<span id="apikey">•••••••••••••••• </span>
|
|
24
|
-
<i id="apikeyBtn" class="fa fa-eye" aria-hidden="true"></i>
|
|
24
|
+
<i id="apikeyBtn" class="fa-solid fa-eye" aria-hidden="true"></i>
|
|
25
25
|
</td>
|
|
26
26
|
</tr>
|
|
27
27
|
<tr><td width=20%><strong>Download limit</strong></td><td>{{ storage_service.download_limit}}</td></tr>
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
<td>{{ mets_fetch_job.download_start }}</td>
|
|
63
63
|
<td>{% if mets_fetch_job.download_end %} {{ mets_fetch_job.download_end - mets_fetch_job.download_start }} {% endif %}</td>
|
|
64
64
|
<td>{{ mets_fetch_job.total_packages }} packages
|
|
65
|
-
<i class="fa fa-info
|
|
65
|
+
<i class="fa-solid fa-circle-info fa-lg" id="{{ mets_fetch_job.id }}" style="margin-left: 5px;"></i><br/>
|
|
66
66
|
<div class="stats" id="stats-{{ mets_fetch_job.id }}">
|
|
67
67
|
<span class="text-muted">
|
|
68
68
|
<small>
|
{aipscan-0.9.0.dev4 → aipscan-0.9.0.dev10}/AIPscan/Aggregator/tests/test_database_helpers.py
RENAMED
|
@@ -5,6 +5,7 @@ from datetime import datetime
|
|
|
5
5
|
import metsrw
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
|
+
from AIPscan import db
|
|
8
9
|
from AIPscan.Aggregator import database_helpers
|
|
9
10
|
from AIPscan.Aggregator import types
|
|
10
11
|
from AIPscan.conftest import ORIGIN_PIPELINE
|
|
@@ -294,7 +295,7 @@ def test_create_or_update_storage_location(
|
|
|
294
295
|
"AIPscan.Aggregator.database_helpers.create_storage_location_object"
|
|
295
296
|
)
|
|
296
297
|
|
|
297
|
-
storage_service =
|
|
298
|
+
storage_service = db.session.get(StorageService, 1)
|
|
298
299
|
|
|
299
300
|
storage_location = database_helpers.create_or_update_storage_location(
|
|
300
301
|
current_location=current_location, storage_service=storage_service
|
|
@@ -331,7 +332,7 @@ def test_create_or_update_pipeline(
|
|
|
331
332
|
)
|
|
332
333
|
get_storage_service_api_url.return_value = (None, None)
|
|
333
334
|
|
|
334
|
-
storage_service =
|
|
335
|
+
storage_service = db.session.get(StorageService, 1)
|
|
335
336
|
|
|
336
337
|
pipeline = database_helpers.create_or_update_pipeline(
|
|
337
338
|
origin_pipeline=origin_pipeline, storage_service=storage_service
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
-
import uuid
|
|
4
3
|
from datetime import datetime
|
|
5
4
|
|
|
6
5
|
import pytest
|
|
@@ -175,20 +174,6 @@ def test_create_numbered_subdirs(timestamp, package_list_number, result, mocker)
|
|
|
175
174
|
assert subdir_string == result
|
|
176
175
|
|
|
177
176
|
|
|
178
|
-
def test_write_mets(mocker, tmpdir):
|
|
179
|
-
"""Ensure that METS is written to expected location."""
|
|
180
|
-
CONTENT = b"test content"
|
|
181
|
-
http_response = mocker.MagicMock()
|
|
182
|
-
http_response.content = CONTENT
|
|
183
|
-
package_uuid = str(uuid.uuid4())
|
|
184
|
-
expected_path = os.path.join(tmpdir, f"METS.{package_uuid}.xml")
|
|
185
|
-
|
|
186
|
-
actual_path = task_helpers.write_mets(http_response, package_uuid, tmpdir)
|
|
187
|
-
assert expected_path == actual_path
|
|
188
|
-
with open(actual_path, "rb") as mets_file:
|
|
189
|
-
assert mets_file.read() == CONTENT
|
|
190
|
-
|
|
191
|
-
|
|
192
177
|
@pytest.fixture()
|
|
193
178
|
def packages():
|
|
194
179
|
fixtures_path = os.path.join("package_json", "packages.json")
|
|
@@ -7,6 +7,7 @@ from datetime import datetime
|
|
|
7
7
|
import celery
|
|
8
8
|
import pytest
|
|
9
9
|
|
|
10
|
+
from AIPscan import db
|
|
10
11
|
from AIPscan import test_helpers
|
|
11
12
|
from AIPscan.Aggregator.tasks import TaskError
|
|
12
13
|
from AIPscan.Aggregator.tasks import delete_aip
|
|
@@ -67,16 +68,21 @@ def test_get_mets_task(app_instance, tmpdir, mocker, fixture_path, package_uuid)
|
|
|
67
68
|
timestamp_str,
|
|
68
69
|
package_list_no,
|
|
69
70
|
):
|
|
70
|
-
return mets_file
|
|
71
|
+
return mets_file, test_helpers.file_sha256_hash(mets_file)
|
|
71
72
|
|
|
72
73
|
mocker.patch("AIPscan.Aggregator.tasks.download_mets", mock_download_mets)
|
|
73
74
|
delete_mets_file = mocker.patch("AIPscan.Aggregator.tasks.os.remove")
|
|
74
75
|
|
|
75
76
|
storage_service = test_helpers.create_test_storage_service()
|
|
77
|
+
storage_service_id = storage_service.id
|
|
78
|
+
|
|
76
79
|
storage_location = test_helpers.create_test_storage_location(
|
|
77
|
-
storage_service_id=
|
|
80
|
+
storage_service_id=storage_service_id
|
|
78
81
|
)
|
|
79
|
-
|
|
82
|
+
storage_location_id = storage_location.id
|
|
83
|
+
|
|
84
|
+
pipeline = test_helpers.create_test_pipeline(storage_service_id=storage_service_id)
|
|
85
|
+
pipeline_id = pipeline.id
|
|
80
86
|
|
|
81
87
|
get_storage_location = mocker.patch(
|
|
82
88
|
"AIPscan.Aggregator.database_helpers.create_or_update_storage_location"
|
|
@@ -84,7 +90,7 @@ def test_get_mets_task(app_instance, tmpdir, mocker, fixture_path, package_uuid)
|
|
|
84
90
|
get_storage_location.return_value = storage_location
|
|
85
91
|
|
|
86
92
|
# No AIPs should exist at this point.
|
|
87
|
-
aips = _get_aips(
|
|
93
|
+
aips = _get_aips(storage_service_id)
|
|
88
94
|
assert not aips
|
|
89
95
|
|
|
90
96
|
# Set up custom logger and add handler to capture output
|
|
@@ -93,8 +99,9 @@ def test_get_mets_task(app_instance, tmpdir, mocker, fixture_path, package_uuid)
|
|
|
93
99
|
|
|
94
100
|
# Create AIP and verify record.
|
|
95
101
|
fetch_job1 = test_helpers.create_test_fetch_job(
|
|
96
|
-
storage_service_id=
|
|
102
|
+
storage_service_id=storage_service_id
|
|
97
103
|
)
|
|
104
|
+
fetch_job1_id = fetch_job1.id
|
|
98
105
|
get_mets(
|
|
99
106
|
package_uuid=package_uuid,
|
|
100
107
|
aip_size=1000,
|
|
@@ -103,22 +110,24 @@ def test_get_mets_task(app_instance, tmpdir, mocker, fixture_path, package_uuid)
|
|
|
103
110
|
.replace(microsecond=0)
|
|
104
111
|
.strftime("%Y-%m-%d-%H-%M-%S"),
|
|
105
112
|
package_list_no=1,
|
|
106
|
-
storage_service_id=
|
|
107
|
-
storage_location_id=
|
|
108
|
-
fetch_job_id=
|
|
109
|
-
origin_pipeline_id=
|
|
113
|
+
storage_service_id=storage_service_id,
|
|
114
|
+
storage_location_id=storage_location_id,
|
|
115
|
+
fetch_job_id=fetch_job1_id,
|
|
116
|
+
origin_pipeline_id=pipeline_id,
|
|
110
117
|
customlogger=customlogger,
|
|
111
118
|
)
|
|
112
|
-
aips = _get_aips(
|
|
119
|
+
aips = _get_aips(storage_service_id)
|
|
113
120
|
assert len(aips) == 1
|
|
114
|
-
|
|
121
|
+
fetch_job1_refreshed = db.session.get(FetchJob, fetch_job1_id)
|
|
122
|
+
assert len(fetch_job1_refreshed.aips) == 1
|
|
115
123
|
|
|
116
124
|
original_mets_sha256 = aips[0].mets_sha256
|
|
117
125
|
|
|
118
126
|
# Try to create AIP again and verify no duplicate is created.
|
|
119
127
|
fetch_job2 = test_helpers.create_test_fetch_job(
|
|
120
|
-
storage_service_id=
|
|
128
|
+
storage_service_id=storage_service_id
|
|
121
129
|
)
|
|
130
|
+
fetch_job2_id = fetch_job2.id
|
|
122
131
|
get_mets(
|
|
123
132
|
package_uuid=package_uuid,
|
|
124
133
|
aip_size=1000,
|
|
@@ -127,23 +136,26 @@ def test_get_mets_task(app_instance, tmpdir, mocker, fixture_path, package_uuid)
|
|
|
127
136
|
.replace(microsecond=0)
|
|
128
137
|
.strftime("%Y-%m-%d-%H-%M-%S"),
|
|
129
138
|
package_list_no=1,
|
|
130
|
-
storage_service_id=
|
|
131
|
-
storage_location_id=
|
|
132
|
-
fetch_job_id=
|
|
133
|
-
origin_pipeline_id=
|
|
139
|
+
storage_service_id=storage_service_id,
|
|
140
|
+
storage_location_id=storage_location_id,
|
|
141
|
+
fetch_job_id=fetch_job2_id,
|
|
142
|
+
origin_pipeline_id=pipeline_id,
|
|
134
143
|
)
|
|
135
|
-
aips = _get_aips(
|
|
144
|
+
aips = _get_aips(storage_service_id)
|
|
136
145
|
assert len(aips) == 1
|
|
137
146
|
assert aips[0].mets_sha256 == original_mets_sha256
|
|
138
|
-
|
|
139
|
-
|
|
147
|
+
fetch_job1_refreshed = db.session.get(FetchJob, fetch_job1_id)
|
|
148
|
+
fetch_job2_refreshed = db.session.get(FetchJob, fetch_job2_id)
|
|
149
|
+
assert len(fetch_job1_refreshed.aips) == 1
|
|
150
|
+
assert len(fetch_job2_refreshed.aips) == 0
|
|
140
151
|
|
|
141
152
|
# Replace METS with a new METS file and run again. The old AIP record
|
|
142
153
|
# should be deleted and replaced with one from the new METS.
|
|
143
154
|
mets_file = os.path.join(FIXTURES_DIR, "iso_mets", "iso_mets.xml")
|
|
144
155
|
fetch_job3 = test_helpers.create_test_fetch_job(
|
|
145
|
-
storage_service_id=
|
|
156
|
+
storage_service_id=storage_service_id
|
|
146
157
|
)
|
|
158
|
+
fetch_job3_id = fetch_job3.id
|
|
147
159
|
get_mets(
|
|
148
160
|
package_uuid=package_uuid,
|
|
149
161
|
aip_size=1000,
|
|
@@ -152,17 +164,20 @@ def test_get_mets_task(app_instance, tmpdir, mocker, fixture_path, package_uuid)
|
|
|
152
164
|
.replace(microsecond=0)
|
|
153
165
|
.strftime("%Y-%m-%d-%H-%M-%S"),
|
|
154
166
|
package_list_no=1,
|
|
155
|
-
storage_service_id=
|
|
156
|
-
storage_location_id=
|
|
157
|
-
fetch_job_id=
|
|
158
|
-
origin_pipeline_id=
|
|
167
|
+
storage_service_id=storage_service_id,
|
|
168
|
+
storage_location_id=storage_location_id,
|
|
169
|
+
fetch_job_id=fetch_job3_id,
|
|
170
|
+
origin_pipeline_id=pipeline_id,
|
|
159
171
|
)
|
|
160
|
-
aips = _get_aips(
|
|
172
|
+
aips = _get_aips(storage_service_id)
|
|
161
173
|
assert len(aips) == 1
|
|
162
174
|
assert aips[0].mets_sha256 != original_mets_sha256
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
175
|
+
fetch_job1_refreshed = db.session.get(FetchJob, fetch_job1_id)
|
|
176
|
+
fetch_job2_refreshed = db.session.get(FetchJob, fetch_job2_id)
|
|
177
|
+
fetch_job3_refreshed = db.session.get(FetchJob, fetch_job3_id)
|
|
178
|
+
assert len(fetch_job1_refreshed.aips) == 0
|
|
179
|
+
assert len(fetch_job2_refreshed.aips) == 0
|
|
180
|
+
assert len(fetch_job3_refreshed.aips) == 1
|
|
166
181
|
|
|
167
182
|
delete_calls = [
|
|
168
183
|
mocker.call(os.path.join(FIXTURES_DIR, fixture_path)),
|
|
@@ -369,22 +384,24 @@ def test_start_index_task(app_instance, mocker):
|
|
|
369
384
|
|
|
370
385
|
# Create test fetch job
|
|
371
386
|
storage_service = test_helpers.create_test_storage_service()
|
|
387
|
+
storage_service_id = storage_service.id
|
|
372
388
|
|
|
373
389
|
fetch_job = test_helpers.create_test_fetch_job(
|
|
374
|
-
storage_service_id=
|
|
390
|
+
storage_service_id=storage_service_id
|
|
375
391
|
)
|
|
392
|
+
fetch_job_id = fetch_job.id
|
|
376
393
|
|
|
377
394
|
# At this point no index_tasks should exist for the fetch job
|
|
378
|
-
index_task_obj = index_tasks.query.filter_by(fetch_job_id=
|
|
395
|
+
index_task_obj = index_tasks.query.filter_by(fetch_job_id=fetch_job_id).first()
|
|
379
396
|
assert index_task_obj is None
|
|
380
397
|
|
|
381
398
|
# Start mock index task, making sure it got started with the right value
|
|
382
|
-
start_index_task(
|
|
399
|
+
start_index_task(fetch_job_id)
|
|
383
400
|
|
|
384
|
-
mock_index_task.assert_called_with(
|
|
401
|
+
mock_index_task.assert_called_with(fetch_job_id)
|
|
385
402
|
|
|
386
403
|
# At this point an index_tasks should exist for the fetch job
|
|
387
|
-
index_task_obj = index_tasks.query.filter_by(fetch_job_id=
|
|
404
|
+
index_task_obj = index_tasks.query.filter_by(fetch_job_id=fetch_job_id).first()
|
|
388
405
|
assert type(index_task_obj) is index_tasks
|
|
389
406
|
|
|
390
407
|
|
|
@@ -87,7 +87,7 @@ def ss_default():
|
|
|
87
87
|
|
|
88
88
|
@aggregator.route("/storage_service/<storage_service_id>", methods=["GET"])
|
|
89
89
|
def storage_service(storage_service_id):
|
|
90
|
-
storage_service =
|
|
90
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
91
91
|
|
|
92
92
|
if storage_service is None:
|
|
93
93
|
abort(404)
|
|
@@ -111,7 +111,7 @@ def storage_services():
|
|
|
111
111
|
@aggregator.route("/edit_storage_service/<storage_service_id>", methods=["GET", "POST"])
|
|
112
112
|
def edit_storage_service(storage_service_id):
|
|
113
113
|
form = StorageServiceForm()
|
|
114
|
-
storage_service =
|
|
114
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
115
115
|
|
|
116
116
|
if storage_service is None:
|
|
117
117
|
abort(404)
|
|
@@ -175,7 +175,7 @@ def new_storage_service():
|
|
|
175
175
|
"aggregator.ss_default",
|
|
176
176
|
)
|
|
177
177
|
def delete_storage_service(storage_service_id):
|
|
178
|
-
storage_service =
|
|
178
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
179
179
|
|
|
180
180
|
if storage_service is None:
|
|
181
181
|
abort(404)
|
|
@@ -192,7 +192,7 @@ def delete_storage_service(storage_service_id):
|
|
|
192
192
|
@aggregator.route("/new_fetch_job/<fetch_job_id>", methods=["POST"])
|
|
193
193
|
def new_fetch_job(fetch_job_id):
|
|
194
194
|
"""Fetch and process AIP METS files from Storage Service."""
|
|
195
|
-
storage_service =
|
|
195
|
+
storage_service = db.session.get(StorageService, fetch_job_id)
|
|
196
196
|
|
|
197
197
|
# Check Storage Service credentials and return 400 if invalid prior to
|
|
198
198
|
# creating the Fetch Job and kicking off the Celery task.
|
|
@@ -251,12 +251,12 @@ def new_fetch_job(fetch_job_id):
|
|
|
251
251
|
"aggregator.ss_default",
|
|
252
252
|
)
|
|
253
253
|
def delete_fetch_job(fetch_job_id):
|
|
254
|
-
fetch_job =
|
|
254
|
+
fetch_job = db.session.get(FetchJob, fetch_job_id)
|
|
255
255
|
|
|
256
256
|
if fetch_job is None:
|
|
257
257
|
abort(404)
|
|
258
258
|
|
|
259
|
-
storage_service =
|
|
259
|
+
storage_service = db.session.get(StorageService, fetch_job.storage_service_id)
|
|
260
260
|
tasks.delete_fetch_job.delay(fetch_job_id)
|
|
261
261
|
|
|
262
262
|
flash(f"Fetch job {fetch_job.download_start} is being deleted")
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from AIPscan import db
|
|
1
2
|
from AIPscan.Data import fields
|
|
2
3
|
from AIPscan.models import StorageLocation
|
|
3
4
|
from AIPscan.models import StorageService
|
|
@@ -14,7 +15,7 @@ def _get_storage_service(storage_service_id):
|
|
|
14
15
|
|
|
15
16
|
:returns: StorageService object or None
|
|
16
17
|
"""
|
|
17
|
-
return
|
|
18
|
+
return db.session.get(StorageService, storage_service_id)
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
def get_storage_service_name(storage_service_id):
|
|
@@ -29,7 +30,7 @@ def get_storage_service_name(storage_service_id):
|
|
|
29
30
|
|
|
30
31
|
def _get_storage_location(storage_location_id):
|
|
31
32
|
"""Return Storage Location with ID or None."""
|
|
32
|
-
return
|
|
33
|
+
return db.session.get(StorageLocation, storage_location_id)
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
def get_storage_location_description(storage_location_id):
|
|
@@ -270,7 +270,7 @@ def largest_files(
|
|
|
270
270
|
except AttributeError:
|
|
271
271
|
pass
|
|
272
272
|
|
|
273
|
-
matching_aip =
|
|
273
|
+
matching_aip = db.session.get(AIP, file_.aip_id)
|
|
274
274
|
if matching_aip is not None:
|
|
275
275
|
file_info[fields.FIELD_AIP_NAME] = matching_aip.transfer_name
|
|
276
276
|
file_info[fields.FIELD_AIP_UUID] = matching_aip.uuid
|
|
@@ -684,7 +684,7 @@ def _get_days_covered_by_date_range(storage_service_id, start_date, end_date):
|
|
|
684
684
|
:returns: List of strings like "YYYY-MM-DD"
|
|
685
685
|
"""
|
|
686
686
|
if start_date == datetime.min:
|
|
687
|
-
storage_service =
|
|
687
|
+
storage_service = db.session.get(StorageService, storage_service_id)
|
|
688
688
|
start_date = storage_service.earliest_aip_created
|
|
689
689
|
if end_date >= datetime.now():
|
|
690
690
|
end_date = datetime.now()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
+
from AIPscan import db
|
|
3
4
|
from AIPscan import typesense_helpers
|
|
4
5
|
from AIPscan import typesense_test_helpers
|
|
5
6
|
from AIPscan.Data import fields
|
|
@@ -48,7 +49,7 @@ def test_largest_aips(
|
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
def test_largest_aips_typesense(app_with_populated_files, enable_typesense, mocker):
|
|
51
|
-
doc = typesense_helpers.model_instance_to_document(AIP,
|
|
52
|
+
doc = typesense_helpers.model_instance_to_document(AIP, db.session.get(AIP, 1))
|
|
52
53
|
fake_results = {"hits": [{"document": doc}]}
|
|
53
54
|
|
|
54
55
|
typesense_test_helpers.fake_collection(mocker, fake_results)
|
|
@@ -3,6 +3,7 @@ import uuid
|
|
|
3
3
|
|
|
4
4
|
import pytest
|
|
5
5
|
|
|
6
|
+
from AIPscan import db
|
|
6
7
|
from AIPscan import typesense_helpers
|
|
7
8
|
from AIPscan import typesense_test_helpers
|
|
8
9
|
from AIPscan.Data import fields
|
|
@@ -116,7 +117,7 @@ def test_largest_files_elements(
|
|
|
116
117
|
mock_get_ss_name = mocker.patch("AIPscan.Data._get_storage_service")
|
|
117
118
|
mock_get_ss_name.return_value = MOCK_STORAGE_SERVICE
|
|
118
119
|
|
|
119
|
-
mock_get_aip = mocker.patch("
|
|
120
|
+
mock_get_aip = mocker.patch("AIPscan.Data.report_data.db.session.get")
|
|
120
121
|
mock_get_aip.return_value = MOCK_AIP
|
|
121
122
|
|
|
122
123
|
report = report_data.largest_files(
|
|
@@ -147,7 +148,7 @@ def test_largest_files_elements(
|
|
|
147
148
|
|
|
148
149
|
|
|
149
150
|
def test_largest_files_typesense(app_with_populated_files, enable_typesense, mocker):
|
|
150
|
-
doc = typesense_helpers.model_instance_to_document(File,
|
|
151
|
+
doc = typesense_helpers.model_instance_to_document(File, db.session.get(File, 1))
|
|
151
152
|
doc["transfer_name"] = "Test AIP"
|
|
152
153
|
doc["aip_uuid"] = "111111111111-1111-1111-11111111"
|
|
153
154
|
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
|
|
13
13
|
<div class="float-end">
|
|
14
14
|
<form action="{{ url_for('reporter.view_aips') }}" method="GET" class="pr-3" id="queryform">
|
|
15
|
-
<i class="
|
|
15
|
+
<i class="fa-solid fa-magnifying-glass"></i> Search <input name="query" id="query"/><input type="submit" hidden/>
|
|
16
16
|
</form>
|
|
17
17
|
</div>
|
|
18
18
|
|
|
19
19
|
<div class="report-opts" style="margin-bottom: 0.2em;">
|
|
20
20
|
<div>
|
|
21
21
|
<span class="fixed-width-menu-span-left">
|
|
22
|
-
<i class="fa fa-database" aria-hidden="true"></i>
|
|
22
|
+
<i class="fa-solid fa-database" aria-hidden="true"></i>
|
|
23
23
|
Storage Service
|
|
24
24
|
</span>
|
|
25
25
|
<select id="ss" method="GET" action="/">
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<div class="report-opts" style="margin-bottom: 1em;">
|
|
37
37
|
<div>
|
|
38
38
|
<span class="fixed-width-menu-span-left">
|
|
39
|
-
<i class="fa fa-archive" aria-hidden="true"></i>
|
|
39
|
+
<i class="fa-solid fa-box-archive" aria-hidden="true"></i>
|
|
40
40
|
Location
|
|
41
41
|
</span>
|
|
42
42
|
<select id="sl" method="GET" action="/">
|