igs-slm 0.1.0b0__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.
- igs_slm-0.1.0b0.dist-info/LICENSE +21 -0
- igs_slm-0.1.0b0.dist-info/METADATA +151 -0
- igs_slm-0.1.0b0.dist-info/RECORD +447 -0
- igs_slm-0.1.0b0.dist-info/WHEEL +4 -0
- igs_slm-0.1.0b0.dist-info/entry_points.txt +3 -0
- igs_tools/__init__.py +0 -0
- igs_tools/connection.py +88 -0
- igs_tools/defines/__init__.py +8 -0
- igs_tools/defines/constellation.py +21 -0
- igs_tools/defines/data_center.py +75 -0
- igs_tools/defines/rinex.py +49 -0
- igs_tools/directory.py +247 -0
- igs_tools/utils.py +66 -0
- slm/__init__.py +21 -0
- slm/admin.py +674 -0
- slm/api/edit/__init__.py +0 -0
- slm/api/edit/serializers.py +316 -0
- slm/api/edit/views.py +1632 -0
- slm/api/fields.py +89 -0
- slm/api/filter.py +504 -0
- slm/api/pagination.py +55 -0
- slm/api/permissions.py +65 -0
- slm/api/public/__init__.py +0 -0
- slm/api/public/serializers.py +249 -0
- slm/api/public/views.py +606 -0
- slm/api/serializers.py +132 -0
- slm/api/views.py +148 -0
- slm/apps.py +323 -0
- slm/authentication.py +198 -0
- slm/bin/__init__.py +0 -0
- slm/bin/startproject.py +262 -0
- slm/bin/templates/{{ project_dir }}/pyproject.toml +35 -0
- slm/bin/templates/{{ project_dir }}/sites/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/base.py +15 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/__init__.py +56 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/local.py +4 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/wsgi.py +16 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/manage.py +34 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/__init__.py +61 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/wsgi.py +16 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/urls.py +7 -0
- slm/bin/templates/{{ project_dir }}/sites/{{ site }}/validation.py +11 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/admin.py +5 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/apps.py +14 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/import_archive.py +64 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/migrations/__init__.py +0 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/models.py +6 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/templates/slm/base.html +8 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/urls.py +10 -0
- slm/bin/templates/{{ project_dir }}/{{ extension_app }}/views.py +5 -0
- slm/defines/AlertLevel.py +24 -0
- slm/defines/AntennaCalibration.py +25 -0
- slm/defines/AntennaFeatures.py +27 -0
- slm/defines/AntennaReferencePoint.py +22 -0
- slm/defines/Aspiration.py +13 -0
- slm/defines/CardinalDirection.py +19 -0
- slm/defines/CollocationStatus.py +12 -0
- slm/defines/EquipmentState.py +22 -0
- slm/defines/FlagSeverity.py +14 -0
- slm/defines/FractureSpacing.py +15 -0
- slm/defines/FrequencyStandardType.py +15 -0
- slm/defines/GeodesyMLVersion.py +48 -0
- slm/defines/ISOCountry.py +1194 -0
- slm/defines/Instrumentation.py +19 -0
- slm/defines/LogEntryType.py +30 -0
- slm/defines/SLMFileType.py +18 -0
- slm/defines/SiteFileUploadStatus.py +61 -0
- slm/defines/SiteLogFormat.py +49 -0
- slm/defines/SiteLogStatus.py +78 -0
- slm/defines/TectonicPlates.py +28 -0
- slm/defines/__init__.py +46 -0
- slm/forms.py +1126 -0
- slm/jinja2/slm/sitelog/ascii_9char.log +346 -0
- slm/jinja2/slm/sitelog/legacy.log +346 -0
- slm/jinja2/slm/sitelog/xsd/0.4/collocationInformation.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/condition.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/contact.xml +52 -0
- slm/jinja2/slm/sitelog/xsd/0.4/formInformation.xml +5 -0
- slm/jinja2/slm/sitelog/xsd/0.4/frequencyStandard.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/gnssAntenna.xml +16 -0
- slm/jinja2/slm/sitelog/xsd/0.4/gnssReceiver.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.4/humiditySensor.xml +13 -0
- slm/jinja2/slm/sitelog/xsd/0.4/localEpisodicEffect.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/moreInformation.xml +22 -0
- slm/jinja2/slm/sitelog/xsd/0.4/multipathSource.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/otherInstrumentation.xml +5 -0
- slm/jinja2/slm/sitelog/xsd/0.4/pressureSensor.xml +12 -0
- slm/jinja2/slm/sitelog/xsd/0.4/radioInterference.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.4/sensor.xml +16 -0
- slm/jinja2/slm/sitelog/xsd/0.4/signalObstruction.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/0.4/siteIdentification.xml +22 -0
- slm/jinja2/slm/sitelog/xsd/0.4/siteLocation.xml +21 -0
- slm/jinja2/slm/sitelog/xsd/0.4/surveyedLocalTie.xml +20 -0
- slm/jinja2/slm/sitelog/xsd/0.4/temperatureSensor.xml +13 -0
- slm/jinja2/slm/sitelog/xsd/0.4/waterVaporSensor.xml +11 -0
- slm/jinja2/slm/sitelog/xsd/0.5/document.xml +10 -0
- slm/jinja2/slm/sitelog/xsd/geodesyml_0.4.xml +99 -0
- slm/jinja2/slm/sitelog/xsd/geodesyml_0.5.xml +112 -0
- slm/management/__init__.py +0 -0
- slm/management/commands/__init__.py +53 -0
- slm/management/commands/build_index.py +96 -0
- slm/management/commands/generate_sinex.py +675 -0
- slm/management/commands/head_from_index.py +541 -0
- slm/management/commands/import_archive.py +908 -0
- slm/management/commands/import_equipment.py +351 -0
- slm/management/commands/set_site.py +56 -0
- slm/management/commands/sitelog.py +144 -0
- slm/management/commands/synchronize.py +60 -0
- slm/management/commands/update_data_availability.py +167 -0
- slm/management/commands/validate_db.py +186 -0
- slm/management/commands/validate_gml.py +73 -0
- slm/map/__init__.py +1 -0
- slm/map/admin.py +5 -0
- slm/map/api/__init__.py +0 -0
- slm/map/api/edit/__init__.py +0 -0
- slm/map/api/edit/serializers.py +28 -0
- slm/map/api/edit/views.py +46 -0
- slm/map/api/public/__init__.py +0 -0
- slm/map/api/public/serializers.py +29 -0
- slm/map/api/public/views.py +64 -0
- slm/map/apps.py +7 -0
- slm/map/defines.py +53 -0
- slm/map/migrations/0001_initial.py +115 -0
- slm/map/migrations/__init__.py +0 -0
- slm/map/models.py +63 -0
- slm/map/static/slm/css/map.css +86 -0
- slm/map/static/slm/js/map.js +159 -0
- slm/map/templates/slm/map.html +374 -0
- slm/map/templates/slm/station/base.html +11 -0
- slm/map/templates/slm/station/edit.html +10 -0
- slm/map/templates/slm/top_nav.html +17 -0
- slm/map/templatetags/__init__.py +0 -0
- slm/map/templatetags/slm_map.py +18 -0
- slm/map/urls.py +25 -0
- slm/map/views.py +36 -0
- slm/middleware.py +29 -0
- slm/migrations/0001_alter_siteantenna_marker_enu_alter_sitelocation_llh_and_more.py +47 -0
- slm/migrations/0001_initial.py +4826 -0
- slm/migrations/0002_alter_dataavailability_site.py +22 -0
- slm/migrations/0003_remove_logentry_slm_logentr_site_lo_7a2af7_idx_and_more.py +80 -0
- slm/migrations/0004_alter_logentry_timestamp_and_more.py +25 -0
- slm/migrations/0005_alter_logentry_options_alter_logentry_section_and_more.py +46 -0
- slm/migrations/0006_alter_logentry_options_alter_logentry_index_together.py +24 -0
- slm/migrations/0007_alter_dataavailability_rate.py +23 -0
- slm/migrations/0008_alter_archiveindex_options_and_more.py +64 -0
- slm/migrations/0009_alter_archiveindex_end.py +21 -0
- slm/migrations/0010_alter_dataavailability_rinex_version_and_more.py +844 -0
- slm/migrations/0011_alter_siteidentification_fracture_spacing.py +33 -0
- slm/migrations/0012_alter_logentry_type.py +36 -0
- slm/migrations/0013_unpublishedfilesalert.py +48 -0
- slm/migrations/0014_sitelogpublished.py +48 -0
- slm/migrations/0015_alter_siteantenna_options_and_more.py +181 -0
- slm/migrations/0016_alter_antenna_description_alter_radome_description_and_more.py +42 -0
- slm/migrations/0017_alter_logentry_unique_together_and_more.py +54 -0
- slm/migrations/0018_afix_deleted.py +34 -0
- slm/migrations/0018_alter_siteantenna_options_and_more.py +244 -0
- slm/migrations/0019_remove_siteantenna_marker_enu_siteantenna_marker_une_and_more.py +101 -0
- slm/migrations/0020_alter_manufacturer_options.py +16 -0
- slm/migrations/0021_alter_siteform_report_type.py +23 -0
- slm/migrations/0022_rename_antcal_antenna_radome_slm_antcal_antenna_20827a_idx_and_more.py +297 -0
- slm/migrations/0023_archivedsitelog_gml_version_and_more.py +55 -0
- slm/migrations/0024_alter_agency_name_alter_agency_shortname.py +24 -0
- slm/migrations/0025_alter_archivedsitelog_log_format_and_more.py +61 -0
- slm/migrations/0026_alter_archivedsitelog_log_format_and_more.py +61 -0
- slm/migrations/0027_importalert_file_contents_importalert_findings_and_more.py +41 -0
- slm/migrations/0028_antenna_replaced_manufacturer_url_radome_replaced_and_more.py +46 -0
- slm/migrations/0029_manufacturer_full_name.py +17 -0
- slm/migrations/0030_alter_antenna_state_alter_radome_state_and_more.py +43 -0
- slm/migrations/__init__.py +0 -0
- slm/migrations/load_satellitesystems.py +27 -0
- slm/models/__init__.py +118 -0
- slm/models/about.py +14 -0
- slm/models/alerts.py +1204 -0
- slm/models/data.py +58 -0
- slm/models/equipment.py +229 -0
- slm/models/help.py +14 -0
- slm/models/index.py +428 -0
- slm/models/sitelog.py +4279 -0
- slm/models/system.py +723 -0
- slm/models/user.py +304 -0
- slm/parsing/__init__.py +786 -0
- slm/parsing/legacy/__init__.py +4 -0
- slm/parsing/legacy/binding.py +817 -0
- slm/parsing/legacy/parser.py +377 -0
- slm/parsing/xsd/__init__.py +34 -0
- slm/parsing/xsd/binding.py +86 -0
- slm/parsing/xsd/geodesyml/0.4/commonTypes.xsd +133 -0
- slm/parsing/xsd/geodesyml/0.4/contact.xsd +29 -0
- slm/parsing/xsd/geodesyml/0.4/dataStreams.xsd +129 -0
- slm/parsing/xsd/geodesyml/0.4/document.xsd +64 -0
- slm/parsing/xsd/geodesyml/0.4/equipment.xsd +427 -0
- slm/parsing/xsd/geodesyml/0.4/fieldMeasurement.xsd +170 -0
- slm/parsing/xsd/geodesyml/0.4/geodesyML.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.4/geodeticEquipment.xsd +343 -0
- slm/parsing/xsd/geodesyml/0.4/geodeticMonument.xsd +147 -0
- slm/parsing/xsd/geodesyml/0.4/lineage.xsd +614 -0
- slm/parsing/xsd/geodesyml/0.4/localInterferences.xsd +131 -0
- slm/parsing/xsd/geodesyml/0.4/measurement.xsd +473 -0
- slm/parsing/xsd/geodesyml/0.4/monumentInfo.xsd +251 -0
- slm/parsing/xsd/geodesyml/0.4/observationSystem.xsd +429 -0
- slm/parsing/xsd/geodesyml/0.4/project.xsd +38 -0
- slm/parsing/xsd/geodesyml/0.4/quality.xsd +176 -0
- slm/parsing/xsd/geodesyml/0.4/referenceFrame.xsd +194 -0
- slm/parsing/xsd/geodesyml/0.4/siteLog.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.5/commonTypes.xsd +133 -0
- slm/parsing/xsd/geodesyml/0.5/contact.xsd +29 -0
- slm/parsing/xsd/geodesyml/0.5/dataStreams.xsd +129 -0
- slm/parsing/xsd/geodesyml/0.5/document.xsd +64 -0
- slm/parsing/xsd/geodesyml/0.5/equipment.xsd +427 -0
- slm/parsing/xsd/geodesyml/0.5/fieldMeasurement.xsd +170 -0
- slm/parsing/xsd/geodesyml/0.5/geodesyML.xsd +71 -0
- slm/parsing/xsd/geodesyml/0.5/geodeticEquipment.xsd +343 -0
- slm/parsing/xsd/geodesyml/0.5/geodeticMonument.xsd +147 -0
- slm/parsing/xsd/geodesyml/0.5/lineage.xsd +614 -0
- slm/parsing/xsd/geodesyml/0.5/localInterferences.xsd +131 -0
- slm/parsing/xsd/geodesyml/0.5/measurement.xsd +473 -0
- slm/parsing/xsd/geodesyml/0.5/monumentInfo.xsd +306 -0
- slm/parsing/xsd/geodesyml/0.5/observationSystem.xsd +429 -0
- slm/parsing/xsd/geodesyml/0.5/project.xsd +38 -0
- slm/parsing/xsd/geodesyml/0.5/quality.xsd +176 -0
- slm/parsing/xsd/geodesyml/0.5/referenceFrame.xsd +194 -0
- slm/parsing/xsd/geodesyml/0.5/siteLog.xsd +73 -0
- slm/parsing/xsd/parser.py +116 -0
- slm/parsing/xsd/resolver.py +28 -0
- slm/receivers/__init__.py +11 -0
- slm/receivers/alerts.py +87 -0
- slm/receivers/cleanup.py +41 -0
- slm/receivers/event_loggers.py +175 -0
- slm/receivers/index.py +67 -0
- slm/settings/__init__.py +55 -0
- slm/settings/auth.py +15 -0
- slm/settings/ckeditor.py +14 -0
- slm/settings/debug.py +47 -0
- slm/settings/internationalization.py +12 -0
- slm/settings/logging.py +113 -0
- slm/settings/platform/__init__.py +0 -0
- slm/settings/platform/darwin.py +10 -0
- slm/settings/rest.py +21 -0
- slm/settings/root.py +152 -0
- slm/settings/routines.py +43 -0
- slm/settings/secrets.py +37 -0
- slm/settings/security.py +5 -0
- slm/settings/slm.py +188 -0
- slm/settings/static_templates.py +53 -0
- slm/settings/templates.py +29 -0
- slm/settings/uploads.py +8 -0
- slm/settings/urls.py +126 -0
- slm/settings/validation.py +196 -0
- slm/signals.py +250 -0
- slm/singleton.py +49 -0
- slm/static/rest_framework/css/bootstrap-tweaks.css +204 -0
- slm/static/rest_framework/css/bootstrap.min.css +7 -0
- slm/static/rest_framework/css/bootstrap.min.css.map +1 -0
- slm/static/rest_framework/css/default.css +82 -0
- slm/static/rest_framework/css/prettify.css +30 -0
- slm/static/rest_framework/docs/css/base.css +344 -0
- slm/static/rest_framework/docs/css/highlight.css +125 -0
- slm/static/rest_framework/docs/css/jquery.json-view.min.css +11 -0
- slm/static/rest_framework/docs/img/favicon.ico +0 -0
- slm/static/rest_framework/docs/img/grid.png +0 -0
- slm/static/rest_framework/docs/js/api.js +321 -0
- slm/static/rest_framework/docs/js/highlight.pack.js +2 -0
- slm/static/rest_framework/docs/js/jquery.json-view.min.js +7 -0
- slm/static/rest_framework/img/grid.png +0 -0
- slm/static/rest_framework/js/ajax-form.js +127 -0
- slm/static/rest_framework/js/bootstrap.bundle.min.js +7 -0
- slm/static/rest_framework/js/bootstrap.bundle.min.js.map +1 -0
- slm/static/rest_framework/js/bootstrap.min.js.map +1 -0
- slm/static/rest_framework/js/coreapi-0.1.1.js +2043 -0
- slm/static/rest_framework/js/csrf.js +52 -0
- slm/static/rest_framework/js/default.js +47 -0
- slm/static/rest_framework/js/jquery-3.5.1.min.js +2 -0
- slm/static/rest_framework/js/prettify-min.js +28 -0
- slm/static/slm/css/admin.css +3 -0
- slm/static/slm/css/defines.css +82 -0
- slm/static/slm/css/forms.css +1 -0
- slm/static/slm/css/style.css +1004 -0
- slm/static/slm/img/email-branding.png +0 -0
- slm/static/slm/img/favicon.ico +0 -0
- slm/static/slm/img/login-bg.jpg +0 -0
- slm/static/slm/img/slm-logo.svg +4 -0
- slm/static/slm/js/autocomplete.js +341 -0
- slm/static/slm/js/enums.js +322 -0
- slm/static/slm/js/fileIcons.js +30 -0
- slm/static/slm/js/form.js +404 -0
- slm/static/slm/js/formWidget.js +23 -0
- slm/static/slm/js/persistable.js +33 -0
- slm/static/slm/js/slm.js +1028 -0
- slm/static/slm/js/time24.js +212 -0
- slm/static_templates/slm/css/defines.css +26 -0
- slm/static_templates/slm/js/enums.js +28 -0
- slm/static_templates/slm/js/fileIcons.js +16 -0
- slm/static_templates/slm/js/urls.js +5 -0
- slm/templates/account/base.html +20 -0
- slm/templates/account/email/base.html +43 -0
- slm/templates/account/email/base_message.txt +7 -0
- slm/templates/account/email/email_confirmation_message.html +16 -0
- slm/templates/account/email/email_confirmation_message.txt +7 -0
- slm/templates/account/email/email_confirmation_signup_message.html +1 -0
- slm/templates/account/email/email_confirmation_signup_message.txt +1 -0
- slm/templates/account/email/email_confirmation_signup_subject.txt +1 -0
- slm/templates/account/email/email_confirmation_subject.txt +4 -0
- slm/templates/account/email/password_reset_key_message.html +28 -0
- slm/templates/account/email/password_reset_key_message.txt +9 -0
- slm/templates/account/email/password_reset_key_subject.txt +4 -0
- slm/templates/account/email/unknown_account_message.html +25 -0
- slm/templates/account/email/unknown_account_message.txt +12 -0
- slm/templates/account/email/unknown_account_subject.txt +4 -0
- slm/templates/account/login.html +67 -0
- slm/templates/account/logout.html +38 -0
- slm/templates/account/password_change.html +48 -0
- slm/templates/account/password_reset.html +51 -0
- slm/templates/account/password_reset_done.html +20 -0
- slm/templates/account/password_reset_from_key.html +52 -0
- slm/templates/account/password_reset_from_key_done.html +17 -0
- slm/templates/admin/base.html +7 -0
- slm/templates/messages.html +8 -0
- slm/templates/rest_framework/README +16 -0
- slm/templates/rest_framework/admin/detail.html +10 -0
- slm/templates/rest_framework/admin/dict_value.html +11 -0
- slm/templates/rest_framework/admin/list.html +32 -0
- slm/templates/rest_framework/admin/list_value.html +11 -0
- slm/templates/rest_framework/admin/simple_list_value.html +2 -0
- slm/templates/rest_framework/admin.html +282 -0
- slm/templates/rest_framework/api.html +3 -0
- slm/templates/rest_framework/base.html +334 -0
- slm/templates/rest_framework/docs/auth/basic.html +42 -0
- slm/templates/rest_framework/docs/auth/session.html +40 -0
- slm/templates/rest_framework/docs/auth/token.html +41 -0
- slm/templates/rest_framework/docs/document.html +37 -0
- slm/templates/rest_framework/docs/error.html +71 -0
- slm/templates/rest_framework/docs/index.html +55 -0
- slm/templates/rest_framework/docs/interact.html +57 -0
- slm/templates/rest_framework/docs/langs/javascript-intro.html +5 -0
- slm/templates/rest_framework/docs/langs/javascript.html +15 -0
- slm/templates/rest_framework/docs/langs/python-intro.html +3 -0
- slm/templates/rest_framework/docs/langs/python.html +13 -0
- slm/templates/rest_framework/docs/langs/shell-intro.html +3 -0
- slm/templates/rest_framework/docs/langs/shell.html +6 -0
- slm/templates/rest_framework/docs/link.html +113 -0
- slm/templates/rest_framework/docs/sidebar.html +78 -0
- slm/templates/rest_framework/filters/base.html +16 -0
- slm/templates/rest_framework/filters/ordering.html +17 -0
- slm/templates/rest_framework/filters/search.html +13 -0
- slm/templates/rest_framework/horizontal/checkbox.html +23 -0
- slm/templates/rest_framework/horizontal/checkbox_multiple.html +32 -0
- slm/templates/rest_framework/horizontal/dict_field.html +11 -0
- slm/templates/rest_framework/horizontal/fieldset.html +16 -0
- slm/templates/rest_framework/horizontal/form.html +6 -0
- slm/templates/rest_framework/horizontal/input.html +21 -0
- slm/templates/rest_framework/horizontal/list_field.html +11 -0
- slm/templates/rest_framework/horizontal/list_fieldset.html +13 -0
- slm/templates/rest_framework/horizontal/radio.html +42 -0
- slm/templates/rest_framework/horizontal/select.html +36 -0
- slm/templates/rest_framework/horizontal/select_multiple.html +38 -0
- slm/templates/rest_framework/horizontal/textarea.html +21 -0
- slm/templates/rest_framework/inline/checkbox.html +8 -0
- slm/templates/rest_framework/inline/checkbox_multiple.html +14 -0
- slm/templates/rest_framework/inline/dict_field.html +9 -0
- slm/templates/rest_framework/inline/fieldset.html +6 -0
- slm/templates/rest_framework/inline/form.html +8 -0
- slm/templates/rest_framework/inline/input.html +9 -0
- slm/templates/rest_framework/inline/list_field.html +9 -0
- slm/templates/rest_framework/inline/list_fieldset.html +3 -0
- slm/templates/rest_framework/inline/radio.html +25 -0
- slm/templates/rest_framework/inline/select.html +24 -0
- slm/templates/rest_framework/inline/select_multiple.html +25 -0
- slm/templates/rest_framework/inline/textarea.html +9 -0
- slm/templates/rest_framework/login.html +3 -0
- slm/templates/rest_framework/login_base.html +65 -0
- slm/templates/rest_framework/pagination/numbers.html +47 -0
- slm/templates/rest_framework/pagination/previous_and_next.html +21 -0
- slm/templates/rest_framework/raw_data_form.html +11 -0
- slm/templates/rest_framework/schema.js +3 -0
- slm/templates/rest_framework/vertical/checkbox.html +16 -0
- slm/templates/rest_framework/vertical/checkbox_multiple.html +30 -0
- slm/templates/rest_framework/vertical/dict_field.html +7 -0
- slm/templates/rest_framework/vertical/fieldset.html +13 -0
- slm/templates/rest_framework/vertical/form.html +6 -0
- slm/templates/rest_framework/vertical/input.html +17 -0
- slm/templates/rest_framework/vertical/list_field.html +7 -0
- slm/templates/rest_framework/vertical/list_fieldset.html +7 -0
- slm/templates/rest_framework/vertical/radio.html +40 -0
- slm/templates/rest_framework/vertical/select.html +34 -0
- slm/templates/rest_framework/vertical/select_multiple.html +31 -0
- slm/templates/rest_framework/vertical/textarea.html +17 -0
- slm/templates/slm/about.html +21 -0
- slm/templates/slm/alerts/alert.html +15 -0
- slm/templates/slm/alerts/geodesymlinvalid.html +8 -0
- slm/templates/slm/alerts/importalert.html +10 -0
- slm/templates/slm/alerts.html +18 -0
- slm/templates/slm/auth_menu.html +41 -0
- slm/templates/slm/base.html +195 -0
- slm/templates/slm/emails/alert_issued.html +31 -0
- slm/templates/slm/emails/alert_issued.txt +9 -0
- slm/templates/slm/emails/base.html +6 -0
- slm/templates/slm/emails/changes_rejected.txt +7 -0
- slm/templates/slm/emails/review_requested.txt +7 -0
- slm/templates/slm/forms/widgets/auto_complete.html +21 -0
- slm/templates/slm/forms/widgets/auto_complete_multiple.html +18 -0
- slm/templates/slm/forms/widgets/checkbox_multiple.html +6 -0
- slm/templates/slm/forms/widgets/inline_multi.html +1 -0
- slm/templates/slm/forms/widgets/splitdatetime.html +14 -0
- slm/templates/slm/forms/widgets/time24.html +37 -0
- slm/templates/slm/help.html +54 -0
- slm/templates/slm/messages.html +13 -0
- slm/templates/slm/new_site.html +88 -0
- slm/templates/slm/profile.html +57 -0
- slm/templates/slm/register.html +40 -0
- slm/templates/slm/reports/file_log.html +43 -0
- slm/templates/slm/reports/head_log.html +23 -0
- slm/templates/slm/reports/head_report.html +55 -0
- slm/templates/slm/reports/index_log.html +23 -0
- slm/templates/slm/reports/index_report.html +71 -0
- slm/templates/slm/station/alert.html +8 -0
- slm/templates/slm/station/alerts.html +19 -0
- slm/templates/slm/station/base.html +104 -0
- slm/templates/slm/station/download.html +87 -0
- slm/templates/slm/station/edit.html +283 -0
- slm/templates/slm/station/form.html +110 -0
- slm/templates/slm/station/log.html +18 -0
- slm/templates/slm/station/review.html +461 -0
- slm/templates/slm/station/upload.html +295 -0
- slm/templates/slm/station/uploads/attachment.html +20 -0
- slm/templates/slm/station/uploads/geodesyml.html +1 -0
- slm/templates/slm/station/uploads/image.html +27 -0
- slm/templates/slm/station/uploads/json.html +0 -0
- slm/templates/slm/station/uploads/legacy.html +77 -0
- slm/templates/slm/top_nav.html +14 -0
- slm/templates/slm/user_activity.html +16 -0
- slm/templates/slm/widgets/alert_scroll.html +135 -0
- slm/templates/slm/widgets/filelist.html +258 -0
- slm/templates/slm/widgets/legend.html +12 -0
- slm/templates/slm/widgets/log_scroll.html +88 -0
- slm/templates/slm/widgets/stationlist.html +233 -0
- slm/templatetags/__init__.py +0 -0
- slm/templatetags/jinja2.py +9 -0
- slm/templatetags/slm.py +459 -0
- slm/urls.py +148 -0
- slm/utils.py +299 -0
- slm/validators.py +297 -0
- slm/views.py +654 -0
- slm/widgets.py +134 -0
slm/api/serializers.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from django.template.loader import get_template
|
|
4
|
+
from django.utils.functional import cached_property
|
|
5
|
+
from lxml import etree
|
|
6
|
+
from rest_framework import serializers
|
|
7
|
+
|
|
8
|
+
from slm.defines import GeodesyMLVersion, SiteLogFormat, SiteLogStatus
|
|
9
|
+
from slm.models import Site
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class _Heading:
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_heading = _Heading()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SiteLogSerializer(serializers.BaseSerializer):
|
|
20
|
+
site = None
|
|
21
|
+
epoch = None
|
|
22
|
+
epoch_param = None
|
|
23
|
+
published_param = True
|
|
24
|
+
is_published = None
|
|
25
|
+
graphic = ""
|
|
26
|
+
|
|
27
|
+
text_tmpl = get_template("slm/sitelog/legacy.log")
|
|
28
|
+
text_9char_tmpl = get_template("slm/sitelog/ascii_9char.log")
|
|
29
|
+
|
|
30
|
+
xml_parser = etree.XMLParser(remove_blank_text=True)
|
|
31
|
+
|
|
32
|
+
def __init__(self, *args, instance, epoch=None, published=True, **kwargs):
|
|
33
|
+
self.site = instance
|
|
34
|
+
self.epoch_param = epoch
|
|
35
|
+
self.epoch = epoch
|
|
36
|
+
self.published_param = (bool(epoch) or published) or None
|
|
37
|
+
self.is_published = self.published_param or (
|
|
38
|
+
self.site.status not in SiteLogStatus.unpublished_states()
|
|
39
|
+
)
|
|
40
|
+
if self.epoch is None:
|
|
41
|
+
self.epoch = (
|
|
42
|
+
self.site.last_publish
|
|
43
|
+
if self.published_param
|
|
44
|
+
else self.site.last_update or self.site.created
|
|
45
|
+
)
|
|
46
|
+
super().__init__(*args, instance=instance, **kwargs)
|
|
47
|
+
|
|
48
|
+
def xml(self, version):
|
|
49
|
+
return etree.tostring(
|
|
50
|
+
etree.fromstring(
|
|
51
|
+
version.template.render(
|
|
52
|
+
{
|
|
53
|
+
**self.context,
|
|
54
|
+
"identifier": self.site.get_filename(
|
|
55
|
+
log_format=SiteLogFormat.GEODESY_ML, epoch=self.epoch_param
|
|
56
|
+
).split(".")[0],
|
|
57
|
+
"files": self.site.sitefileuploads.public().order_by(
|
|
58
|
+
"timestamp"
|
|
59
|
+
),
|
|
60
|
+
}
|
|
61
|
+
).encode(),
|
|
62
|
+
parser=self.xml_parser,
|
|
63
|
+
),
|
|
64
|
+
pretty_print=True,
|
|
65
|
+
).decode()
|
|
66
|
+
|
|
67
|
+
@cached_property
|
|
68
|
+
def json(self):
|
|
69
|
+
# todo
|
|
70
|
+
return json.dumps({})
|
|
71
|
+
|
|
72
|
+
def format(self, log_format, version=None):
|
|
73
|
+
if log_format == SiteLogFormat.LEGACY:
|
|
74
|
+
return self.text
|
|
75
|
+
elif log_format == SiteLogFormat.ASCII_9CHAR:
|
|
76
|
+
return self.text_9char
|
|
77
|
+
elif log_format == SiteLogFormat.GEODESY_ML:
|
|
78
|
+
return self.xml(version=(version or GeodesyMLVersion.latest()))
|
|
79
|
+
raise NotImplementedError(
|
|
80
|
+
f"Serialization for format {log_format} is not yet implemented."
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def section_name(self, name):
|
|
84
|
+
if name.startswith("site"):
|
|
85
|
+
return name[4:]
|
|
86
|
+
return name
|
|
87
|
+
|
|
88
|
+
@cached_property
|
|
89
|
+
def context(self):
|
|
90
|
+
def sort(subsections):
|
|
91
|
+
if subsections:
|
|
92
|
+
return subsections.sort()
|
|
93
|
+
return subsections
|
|
94
|
+
|
|
95
|
+
# todo put this logic on the site model?
|
|
96
|
+
graphic = ""
|
|
97
|
+
if self.published_param:
|
|
98
|
+
ant = self.site.siteantenna_set.published(epoch=self.epoch_param).last()
|
|
99
|
+
graphic = ant.graphic if ant else ""
|
|
100
|
+
else:
|
|
101
|
+
antennas = self.site.siteantenna_set.head(
|
|
102
|
+
epoch=self.epoch_param, include_deleted=False
|
|
103
|
+
).sort(reverse=True)
|
|
104
|
+
if antennas:
|
|
105
|
+
graphic = antennas[0].graphic
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
"site": self.site,
|
|
109
|
+
**{
|
|
110
|
+
self.section_name(section.field): (
|
|
111
|
+
getattr(self.site, section.accessor).published(
|
|
112
|
+
epoch=self.epoch_param
|
|
113
|
+
)
|
|
114
|
+
if self.published_param
|
|
115
|
+
else sort(
|
|
116
|
+
getattr(self.site, section.accessor).head(
|
|
117
|
+
epoch=self.epoch_param, include_deleted=False
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
for section in Site.sections()
|
|
122
|
+
},
|
|
123
|
+
"graphic": graphic,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@cached_property
|
|
127
|
+
def text(self):
|
|
128
|
+
return self.text_tmpl.render({**self.context, "include_templates": True})
|
|
129
|
+
|
|
130
|
+
@cached_property
|
|
131
|
+
def text_9char(self):
|
|
132
|
+
return self.text_9char_tmpl.render({**self.context, "include_templates": True})
|
slm/api/views.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from django.db.models import Q
|
|
4
|
+
from django.http import FileResponse
|
|
5
|
+
from django.utils.translation import gettext as _
|
|
6
|
+
from django_filters import filters
|
|
7
|
+
from django_filters.rest_framework import DjangoFilterBackend
|
|
8
|
+
from rest_framework import mixins, renderers, viewsets
|
|
9
|
+
|
|
10
|
+
from slm.api.filter import InitialValueFilterSet, SLMDateTimeFilter
|
|
11
|
+
from slm.defines import SiteLogFormat
|
|
12
|
+
from slm.models import ArchivedSiteLog, ArchiveIndex
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class LegacyRenderer(renderers.BaseRenderer):
|
|
16
|
+
"""
|
|
17
|
+
Renderer which serializes to legacy format.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
media_type = SiteLogFormat.LEGACY.mimetype
|
|
21
|
+
format = SiteLogFormat.LEGACY
|
|
22
|
+
|
|
23
|
+
def render(self, data, accepted_media_type=None, renderer_context=None):
|
|
24
|
+
return b""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ASCIIRenderer(renderers.BaseRenderer):
|
|
28
|
+
"""
|
|
29
|
+
Renderer which serializes to legacy format.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
media_type = SiteLogFormat.ASCII_9CHAR.mimetype
|
|
33
|
+
format = SiteLogFormat.ASCII_9CHAR
|
|
34
|
+
|
|
35
|
+
def render(self, data, accepted_media_type=None, renderer_context=None):
|
|
36
|
+
return b""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class GeodesyMLRenderer(renderers.BaseRenderer):
|
|
40
|
+
"""
|
|
41
|
+
Renderer which serializes to GeodesyML format.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
media_type = SiteLogFormat.GEODESY_ML.mimetype
|
|
45
|
+
format = SiteLogFormat.GEODESY_ML
|
|
46
|
+
|
|
47
|
+
def render(self, data, accepted_media_type=None, renderer_context=None):
|
|
48
|
+
return b""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class JSONRenderer(renderers.BaseRenderer):
|
|
52
|
+
"""
|
|
53
|
+
Renderer which serializes to GeodesyML format.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
media_type = SiteLogFormat.JSON.mimetype
|
|
57
|
+
format = SiteLogFormat.JSON
|
|
58
|
+
|
|
59
|
+
def render(self, data, accepted_media_type=None, renderer_context=None):
|
|
60
|
+
return b""
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class BaseSiteLogDownloadViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
|
|
64
|
+
renderer_classes = [ASCIIRenderer, LegacyRenderer, GeodesyMLRenderer]
|
|
65
|
+
|
|
66
|
+
site = None
|
|
67
|
+
|
|
68
|
+
lookup_field = "site__name__istartswith"
|
|
69
|
+
lookup_url_kwarg = "site"
|
|
70
|
+
|
|
71
|
+
queryset = ArchiveIndex.objects.all()
|
|
72
|
+
|
|
73
|
+
class ArchiveIndexFilter(InitialValueFilterSet):
|
|
74
|
+
epoch = SLMDateTimeFilter(
|
|
75
|
+
method="at_epoch",
|
|
76
|
+
initial=lambda: datetime.now(),
|
|
77
|
+
help_text=_("Get the log that was active at this given date or datetime."),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
name_len = filters.NumberFilter(
|
|
81
|
+
method="noop",
|
|
82
|
+
help_text=_(
|
|
83
|
+
"The number of characters to include in the filename from the "
|
|
84
|
+
"start of the 9 character site name."
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
lower_case = filters.BooleanFilter(
|
|
89
|
+
method="noop", help_text=_("If true filename will be lowercase.")
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def at_epoch(self, queryset, name, value):
|
|
93
|
+
return queryset.filter(
|
|
94
|
+
Q(begin__lte=value) & (Q(end__isnull=True) | Q(end__gt=value))
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def noop(self, queryset, _1, _2):
|
|
98
|
+
return queryset
|
|
99
|
+
|
|
100
|
+
class Meta:
|
|
101
|
+
model = ArchiveIndex
|
|
102
|
+
fields = ["name_len", "epoch", "lower_case"]
|
|
103
|
+
|
|
104
|
+
filter_backends = (DjangoFilterBackend,)
|
|
105
|
+
filterset_class = ArchiveIndexFilter
|
|
106
|
+
|
|
107
|
+
def get_format_suffix(self, **kwargs):
|
|
108
|
+
requested_format = super().get_format_suffix(**kwargs)
|
|
109
|
+
|
|
110
|
+
# if the site name is a 4-id return the old 4char log format
|
|
111
|
+
if "site" in kwargs and len(kwargs["site"]) == 4 and requested_format == "log":
|
|
112
|
+
return SiteLogFormat.LEGACY
|
|
113
|
+
|
|
114
|
+
# match suffix first
|
|
115
|
+
for fmt in reversed(SiteLogFormat):
|
|
116
|
+
if fmt.ext == requested_format:
|
|
117
|
+
return fmt
|
|
118
|
+
|
|
119
|
+
# if that fails accept alts by priority
|
|
120
|
+
return SiteLogFormat(requested_format)
|
|
121
|
+
|
|
122
|
+
def retrieve(self, request, *args, **kwargs):
|
|
123
|
+
"""
|
|
124
|
+
Download the site log rendered in the specified format - preferencing
|
|
125
|
+
the HTTP_ACCEPTS header over the format parameter. In most cases
|
|
126
|
+
from_site will fetch the archived log from disk, but if a format that
|
|
127
|
+
was not previously rendered is requested from_site might first create
|
|
128
|
+
a new ArchivedSiteLog. If no index is found and allow_unpublished is
|
|
129
|
+
true a new site log will be rendered from the current HEAD state.
|
|
130
|
+
|
|
131
|
+
:param request:
|
|
132
|
+
:param args:
|
|
133
|
+
:param kwargs:
|
|
134
|
+
:return:
|
|
135
|
+
"""
|
|
136
|
+
index = self.get_object()
|
|
137
|
+
archived = ArchivedSiteLog.objects.from_index(
|
|
138
|
+
index=index, log_format=request.accepted_renderer.format
|
|
139
|
+
)
|
|
140
|
+
return FileResponse(
|
|
141
|
+
archived.file,
|
|
142
|
+
filename=index.site.get_filename(
|
|
143
|
+
log_format=archived.log_format,
|
|
144
|
+
epoch=index.begin,
|
|
145
|
+
name_len=request.GET.get("name_len", None),
|
|
146
|
+
lower_case=request.GET.get("lower_case", False),
|
|
147
|
+
),
|
|
148
|
+
)
|
slm/apps.py
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pprint import pformat
|
|
3
|
+
|
|
4
|
+
from django.apps import AppConfig, apps
|
|
5
|
+
from django.conf import settings
|
|
6
|
+
from django.core.checks import Error, Tags, Warning, register
|
|
7
|
+
from django.db.models.signals import (
|
|
8
|
+
post_delete,
|
|
9
|
+
post_init,
|
|
10
|
+
post_migrate,
|
|
11
|
+
post_save,
|
|
12
|
+
pre_delete,
|
|
13
|
+
)
|
|
14
|
+
from django.dispatch import Signal
|
|
15
|
+
from django.utils.module_loading import import_string
|
|
16
|
+
from django.utils.translation import gettext as _
|
|
17
|
+
|
|
18
|
+
from slm.defines import GeodesyMLVersion
|
|
19
|
+
from slm.signals import signal_name
|
|
20
|
+
from slm.utils import clear_caches
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@register("slm", Tags.security)
|
|
24
|
+
def check_permission_groups_setting(**kwargs):
|
|
25
|
+
error_id = "slm.E002"
|
|
26
|
+
header = _("settings.SLM_DEFAULT_PERMISSION_GROUPS is invalid")
|
|
27
|
+
group_setting = getattr(settings, "SLM_DEFAULT_PERMISSION_GROUPS", {})
|
|
28
|
+
errors = []
|
|
29
|
+
if group_setting:
|
|
30
|
+
for group_name, permissions in group_setting.items():
|
|
31
|
+
if not isinstance(group_name, str):
|
|
32
|
+
errors.append(
|
|
33
|
+
Error(
|
|
34
|
+
header,
|
|
35
|
+
hint=_("{} is not a group name string.").format(
|
|
36
|
+
str(group_name)
|
|
37
|
+
),
|
|
38
|
+
id=error_id,
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
for perm in permissions:
|
|
45
|
+
if not isinstance(perm, str):
|
|
46
|
+
errors.append(
|
|
47
|
+
Error(
|
|
48
|
+
header,
|
|
49
|
+
hint=_(
|
|
50
|
+
"SLM_DEFAULT_PERMISSION_GROUPS[{}][{}] is not "
|
|
51
|
+
"a permission codename string."
|
|
52
|
+
"instead of {}."
|
|
53
|
+
).format(group_name, str(perm)),
|
|
54
|
+
id=error_id,
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
except TypeError:
|
|
59
|
+
errors.append(
|
|
60
|
+
Error(
|
|
61
|
+
header,
|
|
62
|
+
hint=_(
|
|
63
|
+
"{} must be an iterable list of permission code names "
|
|
64
|
+
"instead of {}."
|
|
65
|
+
).format(group_name, type(permissions)),
|
|
66
|
+
id=error_id,
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
return errors
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@register("slm", Tags.security)
|
|
73
|
+
def check_permissions_setting(**kwargs):
|
|
74
|
+
warning_id = "slm.W001"
|
|
75
|
+
permissions = getattr(settings, "SLM_PERMISSIONS", None)
|
|
76
|
+
if permissions:
|
|
77
|
+
try:
|
|
78
|
+
from django.utils.module_loading import import_string
|
|
79
|
+
|
|
80
|
+
import_string(permissions)
|
|
81
|
+
except ImportError:
|
|
82
|
+
return [
|
|
83
|
+
Warning(
|
|
84
|
+
_(
|
|
85
|
+
f"Was unable to load SLM_PERMISSIONS callable: "
|
|
86
|
+
f"{permissions}"
|
|
87
|
+
),
|
|
88
|
+
hint=_(
|
|
89
|
+
"Set SLM_PERMISSIONS to the import string for a "
|
|
90
|
+
"callable that returns a queryset of valid system"
|
|
91
|
+
"permissions."
|
|
92
|
+
),
|
|
93
|
+
id=warning_id,
|
|
94
|
+
)
|
|
95
|
+
]
|
|
96
|
+
return []
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@register("slm", Tags.signals)
|
|
100
|
+
def check_automated_alerts(**kwargs):
|
|
101
|
+
error_id = "slm.E001"
|
|
102
|
+
|
|
103
|
+
def alert_conf_error(hint):
|
|
104
|
+
return Error(_("settings.SLM_AUTOMATED_ALERTS is incorrect."), hint, error_id)
|
|
105
|
+
|
|
106
|
+
alerts = getattr(settings, "SLM_AUTOMATED_ALERTS", {})
|
|
107
|
+
if not isinstance(alerts, dict):
|
|
108
|
+
return [
|
|
109
|
+
alert_conf_error(
|
|
110
|
+
_(
|
|
111
|
+
"SLM_AUTOMATED_ALERTS is a {} but it must be a dictionary"
|
|
112
|
+
"keyed on Alert model labels, the values are dictionaries "
|
|
113
|
+
"containing the signals configured to issue the alert and/or"
|
|
114
|
+
"rescind the alert and any default Alert model parameter "
|
|
115
|
+
"overrides."
|
|
116
|
+
).format(type(alerts))
|
|
117
|
+
)
|
|
118
|
+
]
|
|
119
|
+
errors = []
|
|
120
|
+
for alert, config in alerts.items():
|
|
121
|
+
try:
|
|
122
|
+
AlertModel = apps.get_model(*alert.split(".", 1))
|
|
123
|
+
except LookupError:
|
|
124
|
+
errors.append(
|
|
125
|
+
alert_conf_error(
|
|
126
|
+
_(
|
|
127
|
+
"SLM_AUTOMATED_ALERTS[{}] is not a registered model label."
|
|
128
|
+
).format(alert)
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
continue
|
|
132
|
+
if not AlertModel.automated:
|
|
133
|
+
errors.append(
|
|
134
|
+
alert_conf_error(
|
|
135
|
+
_("SLM_AUTOMATED_ALERTS[{}] is a non-automated alert type.").format(
|
|
136
|
+
alert
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
if not isinstance(AlertModel.objects.SUPPORTED_SIGNALS, dict):
|
|
143
|
+
errors.append(
|
|
144
|
+
alert_conf_error(
|
|
145
|
+
_(
|
|
146
|
+
"{}.objects.SUPPORTED_SIGNALS must be a dictionary keyed "
|
|
147
|
+
"with `issue` and `rescind` signal lists that are supported."
|
|
148
|
+
).format(AlertModel.__name__)
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
continue
|
|
152
|
+
|
|
153
|
+
def check_signals(signal_type):
|
|
154
|
+
for signal in config.get(signal_type, []):
|
|
155
|
+
try:
|
|
156
|
+
signal = import_string(signal)
|
|
157
|
+
if not isinstance(signal, Signal):
|
|
158
|
+
errors.append(
|
|
159
|
+
alert_conf_error(
|
|
160
|
+
_(
|
|
161
|
+
"SLM_AUTOMATED_ALERTS[{}][{}][{}] is not a "
|
|
162
|
+
"Signal"
|
|
163
|
+
).format(alert, signal_type, signal_name(signal)),
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
except ImportError:
|
|
167
|
+
errors.append(
|
|
168
|
+
alert_conf_error(
|
|
169
|
+
_(
|
|
170
|
+
"SLM_AUTOMATED_ALERTS[{}][{}] contains a non "
|
|
171
|
+
"existent trigger signal ({})."
|
|
172
|
+
).format(alert, signal_type, signal_name(signal))
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
if signal not in AlertModel.objects.SUPPORTED_SIGNALS.get(
|
|
178
|
+
signal_type, []
|
|
179
|
+
):
|
|
180
|
+
errors.append(
|
|
181
|
+
alert_conf_error(
|
|
182
|
+
_(
|
|
183
|
+
"SLM_AUTOMATED_ALERTS[{}][{}] contains an "
|
|
184
|
+
"unsupported signal ({}) for alerts of type "
|
|
185
|
+
"{}. Must be one of:\n{}"
|
|
186
|
+
).format(
|
|
187
|
+
alert,
|
|
188
|
+
signal_type,
|
|
189
|
+
signal_name(signal),
|
|
190
|
+
AlertModel,
|
|
191
|
+
pformat(
|
|
192
|
+
[
|
|
193
|
+
signal_name(sig)
|
|
194
|
+
for sig in AlertModel.objects.SUPPORTED_SIGNALS[
|
|
195
|
+
signal_type
|
|
196
|
+
]
|
|
197
|
+
]
|
|
198
|
+
),
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
check_signals("issue")
|
|
204
|
+
check_signals("rescind")
|
|
205
|
+
return errors
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def alert_save(sender, instance, created, raw, using, update_fields, **kwargs):
|
|
209
|
+
from slm.signals import alert_issued
|
|
210
|
+
|
|
211
|
+
if created:
|
|
212
|
+
alert_issued.send(sender=sender, alert=instance)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def cache_realalert(sender, instance, using, **kwargs):
|
|
216
|
+
"""
|
|
217
|
+
Cache real alert instance onto the model because we wont be able
|
|
218
|
+
to get it in post because it no longer exists.
|
|
219
|
+
"""
|
|
220
|
+
#
|
|
221
|
+
instance._slm_real_alert = instance.get_real_instance()
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def alert_delete(sender, instance, using, **kwargs):
|
|
225
|
+
from slm.signals import alert_cleared
|
|
226
|
+
|
|
227
|
+
alert_cleared.send(
|
|
228
|
+
sender=sender, alert=getattr(instance, "_slm_real_alert", instance)
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def site_init(sender, instance, **kwargs):
|
|
233
|
+
# publishing may be tracked through a status update or if the
|
|
234
|
+
# last_publish timestamp changes
|
|
235
|
+
|
|
236
|
+
# an infinite recursion loop is triggered if you access a deferred
|
|
237
|
+
# field in a model's init(). We guard against that case here, which
|
|
238
|
+
# can happen when related fields are deleted. Such cases should
|
|
239
|
+
# not involve a status update
|
|
240
|
+
deferred = instance.get_deferred_fields()
|
|
241
|
+
if "status" not in deferred and "last_publish" not in deferred:
|
|
242
|
+
instance._slm_pre_status = instance.status
|
|
243
|
+
instance._slm_last_publish = instance.last_publish
|
|
244
|
+
if instance.pk is None:
|
|
245
|
+
instance._slm_pre_status = None
|
|
246
|
+
instance._slm_last_publish = None
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def site_save(sender, instance, created, raw, using, update_fields, **kwargs):
|
|
250
|
+
from slm.models import Site
|
|
251
|
+
from slm.signals import site_status_changed
|
|
252
|
+
|
|
253
|
+
if (
|
|
254
|
+
hasattr(instance, "_slm_pre_status")
|
|
255
|
+
and instance._slm_pre_status != instance.status
|
|
256
|
+
) or ( # todo why this second clause?
|
|
257
|
+
hasattr(instance, "_slm_last_publish")
|
|
258
|
+
and instance._slm_last_publish != instance.last_publish
|
|
259
|
+
):
|
|
260
|
+
site_status_changed.send(
|
|
261
|
+
sender=Site,
|
|
262
|
+
site=instance,
|
|
263
|
+
previous_status=instance._slm_pre_status,
|
|
264
|
+
new_status=instance.status,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def user_save(sender, instance, created, raw, using, update_fields, **kwargs):
|
|
269
|
+
"""Clear any relevant caches whenever a user is saved."""
|
|
270
|
+
clear_caches()
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def populate_groups(**kwargs):
|
|
274
|
+
from django.contrib.auth.models import Group, Permission
|
|
275
|
+
|
|
276
|
+
for group_name, permissions in getattr(
|
|
277
|
+
settings, "SLM_DEFAULT_PERMISSION_GROUPS", {}
|
|
278
|
+
).items():
|
|
279
|
+
group, created = Group.objects.get_or_create(name=group_name)
|
|
280
|
+
if created:
|
|
281
|
+
group.permissions.set(Permission.objects.filter(codename__in=permissions))
|
|
282
|
+
group.save()
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class SLMConfig(AppConfig):
|
|
286
|
+
name = "slm"
|
|
287
|
+
|
|
288
|
+
# space is used as a workaround to alphabetically push SLM to the
|
|
289
|
+
# top of the admin
|
|
290
|
+
verbose_name = " SLM"
|
|
291
|
+
|
|
292
|
+
def ready(self):
|
|
293
|
+
from django.contrib.auth import get_user_model
|
|
294
|
+
|
|
295
|
+
from slm.models import Alert, Site
|
|
296
|
+
from slm.receivers import register as register_receivers
|
|
297
|
+
|
|
298
|
+
register_receivers()
|
|
299
|
+
|
|
300
|
+
post_init.connect(site_init, sender=Site)
|
|
301
|
+
post_save.connect(site_save, sender=Site)
|
|
302
|
+
post_save.connect(user_save, sender=get_user_model())
|
|
303
|
+
post_migrate.connect(populate_groups)
|
|
304
|
+
|
|
305
|
+
for alert in Alert.objects.classes():
|
|
306
|
+
post_save.connect(alert_save, sender=alert)
|
|
307
|
+
pre_delete.connect(cache_realalert, sender=Alert)
|
|
308
|
+
post_delete.connect(alert_delete, sender=Alert)
|
|
309
|
+
|
|
310
|
+
# load schemas into memory - this can take a few moments and requires
|
|
311
|
+
# a live internet connection
|
|
312
|
+
xsd_preload = getattr(
|
|
313
|
+
settings, "SLM_PRELOAD_SCHEMAS", [geo for geo in GeodesyMLVersion]
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
if (
|
|
317
|
+
xsd_preload
|
|
318
|
+
and not getattr(settings, "SLM_MANAGEMENT_MODE", False)
|
|
319
|
+
and not (len(sys.argv) >= 2 and sys.argv[1] == "runserver")
|
|
320
|
+
):
|
|
321
|
+
from slm.parsing.xsd import load_schemas
|
|
322
|
+
|
|
323
|
+
load_schemas()
|