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.
Files changed (447) hide show
  1. igs_slm-0.1.0b0.dist-info/LICENSE +21 -0
  2. igs_slm-0.1.0b0.dist-info/METADATA +151 -0
  3. igs_slm-0.1.0b0.dist-info/RECORD +447 -0
  4. igs_slm-0.1.0b0.dist-info/WHEEL +4 -0
  5. igs_slm-0.1.0b0.dist-info/entry_points.txt +3 -0
  6. igs_tools/__init__.py +0 -0
  7. igs_tools/connection.py +88 -0
  8. igs_tools/defines/__init__.py +8 -0
  9. igs_tools/defines/constellation.py +21 -0
  10. igs_tools/defines/data_center.py +75 -0
  11. igs_tools/defines/rinex.py +49 -0
  12. igs_tools/directory.py +247 -0
  13. igs_tools/utils.py +66 -0
  14. slm/__init__.py +21 -0
  15. slm/admin.py +674 -0
  16. slm/api/edit/__init__.py +0 -0
  17. slm/api/edit/serializers.py +316 -0
  18. slm/api/edit/views.py +1632 -0
  19. slm/api/fields.py +89 -0
  20. slm/api/filter.py +504 -0
  21. slm/api/pagination.py +55 -0
  22. slm/api/permissions.py +65 -0
  23. slm/api/public/__init__.py +0 -0
  24. slm/api/public/serializers.py +249 -0
  25. slm/api/public/views.py +606 -0
  26. slm/api/serializers.py +132 -0
  27. slm/api/views.py +148 -0
  28. slm/apps.py +323 -0
  29. slm/authentication.py +198 -0
  30. slm/bin/__init__.py +0 -0
  31. slm/bin/startproject.py +262 -0
  32. slm/bin/templates/{{ project_dir }}/pyproject.toml +35 -0
  33. slm/bin/templates/{{ project_dir }}/sites/__init__.py +0 -0
  34. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/__init__.py +0 -0
  35. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/base.py +15 -0
  36. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/__init__.py +56 -0
  37. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/local.py +4 -0
  38. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/develop/wsgi.py +16 -0
  39. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/manage.py +34 -0
  40. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/__init__.py +61 -0
  41. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/production/wsgi.py +16 -0
  42. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/urls.py +7 -0
  43. slm/bin/templates/{{ project_dir }}/sites/{{ site }}/validation.py +11 -0
  44. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/__init__.py +0 -0
  45. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/admin.py +5 -0
  46. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/apps.py +14 -0
  47. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/__init__.py +0 -0
  48. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/__init__.py +0 -0
  49. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/management/commands/import_archive.py +64 -0
  50. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/migrations/__init__.py +0 -0
  51. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/models.py +6 -0
  52. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/templates/slm/base.html +8 -0
  53. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/urls.py +10 -0
  54. slm/bin/templates/{{ project_dir }}/{{ extension_app }}/views.py +5 -0
  55. slm/defines/AlertLevel.py +24 -0
  56. slm/defines/AntennaCalibration.py +25 -0
  57. slm/defines/AntennaFeatures.py +27 -0
  58. slm/defines/AntennaReferencePoint.py +22 -0
  59. slm/defines/Aspiration.py +13 -0
  60. slm/defines/CardinalDirection.py +19 -0
  61. slm/defines/CollocationStatus.py +12 -0
  62. slm/defines/EquipmentState.py +22 -0
  63. slm/defines/FlagSeverity.py +14 -0
  64. slm/defines/FractureSpacing.py +15 -0
  65. slm/defines/FrequencyStandardType.py +15 -0
  66. slm/defines/GeodesyMLVersion.py +48 -0
  67. slm/defines/ISOCountry.py +1194 -0
  68. slm/defines/Instrumentation.py +19 -0
  69. slm/defines/LogEntryType.py +30 -0
  70. slm/defines/SLMFileType.py +18 -0
  71. slm/defines/SiteFileUploadStatus.py +61 -0
  72. slm/defines/SiteLogFormat.py +49 -0
  73. slm/defines/SiteLogStatus.py +78 -0
  74. slm/defines/TectonicPlates.py +28 -0
  75. slm/defines/__init__.py +46 -0
  76. slm/forms.py +1126 -0
  77. slm/jinja2/slm/sitelog/ascii_9char.log +346 -0
  78. slm/jinja2/slm/sitelog/legacy.log +346 -0
  79. slm/jinja2/slm/sitelog/xsd/0.4/collocationInformation.xml +12 -0
  80. slm/jinja2/slm/sitelog/xsd/0.4/condition.xml +12 -0
  81. slm/jinja2/slm/sitelog/xsd/0.4/contact.xml +52 -0
  82. slm/jinja2/slm/sitelog/xsd/0.4/formInformation.xml +5 -0
  83. slm/jinja2/slm/sitelog/xsd/0.4/frequencyStandard.xml +12 -0
  84. slm/jinja2/slm/sitelog/xsd/0.4/gnssAntenna.xml +16 -0
  85. slm/jinja2/slm/sitelog/xsd/0.4/gnssReceiver.xml +11 -0
  86. slm/jinja2/slm/sitelog/xsd/0.4/humiditySensor.xml +13 -0
  87. slm/jinja2/slm/sitelog/xsd/0.4/localEpisodicEffect.xml +10 -0
  88. slm/jinja2/slm/sitelog/xsd/0.4/moreInformation.xml +22 -0
  89. slm/jinja2/slm/sitelog/xsd/0.4/multipathSource.xml +10 -0
  90. slm/jinja2/slm/sitelog/xsd/0.4/otherInstrumentation.xml +5 -0
  91. slm/jinja2/slm/sitelog/xsd/0.4/pressureSensor.xml +12 -0
  92. slm/jinja2/slm/sitelog/xsd/0.4/radioInterference.xml +11 -0
  93. slm/jinja2/slm/sitelog/xsd/0.4/sensor.xml +16 -0
  94. slm/jinja2/slm/sitelog/xsd/0.4/signalObstruction.xml +10 -0
  95. slm/jinja2/slm/sitelog/xsd/0.4/siteIdentification.xml +22 -0
  96. slm/jinja2/slm/sitelog/xsd/0.4/siteLocation.xml +21 -0
  97. slm/jinja2/slm/sitelog/xsd/0.4/surveyedLocalTie.xml +20 -0
  98. slm/jinja2/slm/sitelog/xsd/0.4/temperatureSensor.xml +13 -0
  99. slm/jinja2/slm/sitelog/xsd/0.4/waterVaporSensor.xml +11 -0
  100. slm/jinja2/slm/sitelog/xsd/0.5/document.xml +10 -0
  101. slm/jinja2/slm/sitelog/xsd/geodesyml_0.4.xml +99 -0
  102. slm/jinja2/slm/sitelog/xsd/geodesyml_0.5.xml +112 -0
  103. slm/management/__init__.py +0 -0
  104. slm/management/commands/__init__.py +53 -0
  105. slm/management/commands/build_index.py +96 -0
  106. slm/management/commands/generate_sinex.py +675 -0
  107. slm/management/commands/head_from_index.py +541 -0
  108. slm/management/commands/import_archive.py +908 -0
  109. slm/management/commands/import_equipment.py +351 -0
  110. slm/management/commands/set_site.py +56 -0
  111. slm/management/commands/sitelog.py +144 -0
  112. slm/management/commands/synchronize.py +60 -0
  113. slm/management/commands/update_data_availability.py +167 -0
  114. slm/management/commands/validate_db.py +186 -0
  115. slm/management/commands/validate_gml.py +73 -0
  116. slm/map/__init__.py +1 -0
  117. slm/map/admin.py +5 -0
  118. slm/map/api/__init__.py +0 -0
  119. slm/map/api/edit/__init__.py +0 -0
  120. slm/map/api/edit/serializers.py +28 -0
  121. slm/map/api/edit/views.py +46 -0
  122. slm/map/api/public/__init__.py +0 -0
  123. slm/map/api/public/serializers.py +29 -0
  124. slm/map/api/public/views.py +64 -0
  125. slm/map/apps.py +7 -0
  126. slm/map/defines.py +53 -0
  127. slm/map/migrations/0001_initial.py +115 -0
  128. slm/map/migrations/__init__.py +0 -0
  129. slm/map/models.py +63 -0
  130. slm/map/static/slm/css/map.css +86 -0
  131. slm/map/static/slm/js/map.js +159 -0
  132. slm/map/templates/slm/map.html +374 -0
  133. slm/map/templates/slm/station/base.html +11 -0
  134. slm/map/templates/slm/station/edit.html +10 -0
  135. slm/map/templates/slm/top_nav.html +17 -0
  136. slm/map/templatetags/__init__.py +0 -0
  137. slm/map/templatetags/slm_map.py +18 -0
  138. slm/map/urls.py +25 -0
  139. slm/map/views.py +36 -0
  140. slm/middleware.py +29 -0
  141. slm/migrations/0001_alter_siteantenna_marker_enu_alter_sitelocation_llh_and_more.py +47 -0
  142. slm/migrations/0001_initial.py +4826 -0
  143. slm/migrations/0002_alter_dataavailability_site.py +22 -0
  144. slm/migrations/0003_remove_logentry_slm_logentr_site_lo_7a2af7_idx_and_more.py +80 -0
  145. slm/migrations/0004_alter_logentry_timestamp_and_more.py +25 -0
  146. slm/migrations/0005_alter_logentry_options_alter_logentry_section_and_more.py +46 -0
  147. slm/migrations/0006_alter_logentry_options_alter_logentry_index_together.py +24 -0
  148. slm/migrations/0007_alter_dataavailability_rate.py +23 -0
  149. slm/migrations/0008_alter_archiveindex_options_and_more.py +64 -0
  150. slm/migrations/0009_alter_archiveindex_end.py +21 -0
  151. slm/migrations/0010_alter_dataavailability_rinex_version_and_more.py +844 -0
  152. slm/migrations/0011_alter_siteidentification_fracture_spacing.py +33 -0
  153. slm/migrations/0012_alter_logentry_type.py +36 -0
  154. slm/migrations/0013_unpublishedfilesalert.py +48 -0
  155. slm/migrations/0014_sitelogpublished.py +48 -0
  156. slm/migrations/0015_alter_siteantenna_options_and_more.py +181 -0
  157. slm/migrations/0016_alter_antenna_description_alter_radome_description_and_more.py +42 -0
  158. slm/migrations/0017_alter_logentry_unique_together_and_more.py +54 -0
  159. slm/migrations/0018_afix_deleted.py +34 -0
  160. slm/migrations/0018_alter_siteantenna_options_and_more.py +244 -0
  161. slm/migrations/0019_remove_siteantenna_marker_enu_siteantenna_marker_une_and_more.py +101 -0
  162. slm/migrations/0020_alter_manufacturer_options.py +16 -0
  163. slm/migrations/0021_alter_siteform_report_type.py +23 -0
  164. slm/migrations/0022_rename_antcal_antenna_radome_slm_antcal_antenna_20827a_idx_and_more.py +297 -0
  165. slm/migrations/0023_archivedsitelog_gml_version_and_more.py +55 -0
  166. slm/migrations/0024_alter_agency_name_alter_agency_shortname.py +24 -0
  167. slm/migrations/0025_alter_archivedsitelog_log_format_and_more.py +61 -0
  168. slm/migrations/0026_alter_archivedsitelog_log_format_and_more.py +61 -0
  169. slm/migrations/0027_importalert_file_contents_importalert_findings_and_more.py +41 -0
  170. slm/migrations/0028_antenna_replaced_manufacturer_url_radome_replaced_and_more.py +46 -0
  171. slm/migrations/0029_manufacturer_full_name.py +17 -0
  172. slm/migrations/0030_alter_antenna_state_alter_radome_state_and_more.py +43 -0
  173. slm/migrations/__init__.py +0 -0
  174. slm/migrations/load_satellitesystems.py +27 -0
  175. slm/models/__init__.py +118 -0
  176. slm/models/about.py +14 -0
  177. slm/models/alerts.py +1204 -0
  178. slm/models/data.py +58 -0
  179. slm/models/equipment.py +229 -0
  180. slm/models/help.py +14 -0
  181. slm/models/index.py +428 -0
  182. slm/models/sitelog.py +4279 -0
  183. slm/models/system.py +723 -0
  184. slm/models/user.py +304 -0
  185. slm/parsing/__init__.py +786 -0
  186. slm/parsing/legacy/__init__.py +4 -0
  187. slm/parsing/legacy/binding.py +817 -0
  188. slm/parsing/legacy/parser.py +377 -0
  189. slm/parsing/xsd/__init__.py +34 -0
  190. slm/parsing/xsd/binding.py +86 -0
  191. slm/parsing/xsd/geodesyml/0.4/commonTypes.xsd +133 -0
  192. slm/parsing/xsd/geodesyml/0.4/contact.xsd +29 -0
  193. slm/parsing/xsd/geodesyml/0.4/dataStreams.xsd +129 -0
  194. slm/parsing/xsd/geodesyml/0.4/document.xsd +64 -0
  195. slm/parsing/xsd/geodesyml/0.4/equipment.xsd +427 -0
  196. slm/parsing/xsd/geodesyml/0.4/fieldMeasurement.xsd +170 -0
  197. slm/parsing/xsd/geodesyml/0.4/geodesyML.xsd +71 -0
  198. slm/parsing/xsd/geodesyml/0.4/geodeticEquipment.xsd +343 -0
  199. slm/parsing/xsd/geodesyml/0.4/geodeticMonument.xsd +147 -0
  200. slm/parsing/xsd/geodesyml/0.4/lineage.xsd +614 -0
  201. slm/parsing/xsd/geodesyml/0.4/localInterferences.xsd +131 -0
  202. slm/parsing/xsd/geodesyml/0.4/measurement.xsd +473 -0
  203. slm/parsing/xsd/geodesyml/0.4/monumentInfo.xsd +251 -0
  204. slm/parsing/xsd/geodesyml/0.4/observationSystem.xsd +429 -0
  205. slm/parsing/xsd/geodesyml/0.4/project.xsd +38 -0
  206. slm/parsing/xsd/geodesyml/0.4/quality.xsd +176 -0
  207. slm/parsing/xsd/geodesyml/0.4/referenceFrame.xsd +194 -0
  208. slm/parsing/xsd/geodesyml/0.4/siteLog.xsd +71 -0
  209. slm/parsing/xsd/geodesyml/0.5/commonTypes.xsd +133 -0
  210. slm/parsing/xsd/geodesyml/0.5/contact.xsd +29 -0
  211. slm/parsing/xsd/geodesyml/0.5/dataStreams.xsd +129 -0
  212. slm/parsing/xsd/geodesyml/0.5/document.xsd +64 -0
  213. slm/parsing/xsd/geodesyml/0.5/equipment.xsd +427 -0
  214. slm/parsing/xsd/geodesyml/0.5/fieldMeasurement.xsd +170 -0
  215. slm/parsing/xsd/geodesyml/0.5/geodesyML.xsd +71 -0
  216. slm/parsing/xsd/geodesyml/0.5/geodeticEquipment.xsd +343 -0
  217. slm/parsing/xsd/geodesyml/0.5/geodeticMonument.xsd +147 -0
  218. slm/parsing/xsd/geodesyml/0.5/lineage.xsd +614 -0
  219. slm/parsing/xsd/geodesyml/0.5/localInterferences.xsd +131 -0
  220. slm/parsing/xsd/geodesyml/0.5/measurement.xsd +473 -0
  221. slm/parsing/xsd/geodesyml/0.5/monumentInfo.xsd +306 -0
  222. slm/parsing/xsd/geodesyml/0.5/observationSystem.xsd +429 -0
  223. slm/parsing/xsd/geodesyml/0.5/project.xsd +38 -0
  224. slm/parsing/xsd/geodesyml/0.5/quality.xsd +176 -0
  225. slm/parsing/xsd/geodesyml/0.5/referenceFrame.xsd +194 -0
  226. slm/parsing/xsd/geodesyml/0.5/siteLog.xsd +73 -0
  227. slm/parsing/xsd/parser.py +116 -0
  228. slm/parsing/xsd/resolver.py +28 -0
  229. slm/receivers/__init__.py +11 -0
  230. slm/receivers/alerts.py +87 -0
  231. slm/receivers/cleanup.py +41 -0
  232. slm/receivers/event_loggers.py +175 -0
  233. slm/receivers/index.py +67 -0
  234. slm/settings/__init__.py +55 -0
  235. slm/settings/auth.py +15 -0
  236. slm/settings/ckeditor.py +14 -0
  237. slm/settings/debug.py +47 -0
  238. slm/settings/internationalization.py +12 -0
  239. slm/settings/logging.py +113 -0
  240. slm/settings/platform/__init__.py +0 -0
  241. slm/settings/platform/darwin.py +10 -0
  242. slm/settings/rest.py +21 -0
  243. slm/settings/root.py +152 -0
  244. slm/settings/routines.py +43 -0
  245. slm/settings/secrets.py +37 -0
  246. slm/settings/security.py +5 -0
  247. slm/settings/slm.py +188 -0
  248. slm/settings/static_templates.py +53 -0
  249. slm/settings/templates.py +29 -0
  250. slm/settings/uploads.py +8 -0
  251. slm/settings/urls.py +126 -0
  252. slm/settings/validation.py +196 -0
  253. slm/signals.py +250 -0
  254. slm/singleton.py +49 -0
  255. slm/static/rest_framework/css/bootstrap-tweaks.css +204 -0
  256. slm/static/rest_framework/css/bootstrap.min.css +7 -0
  257. slm/static/rest_framework/css/bootstrap.min.css.map +1 -0
  258. slm/static/rest_framework/css/default.css +82 -0
  259. slm/static/rest_framework/css/prettify.css +30 -0
  260. slm/static/rest_framework/docs/css/base.css +344 -0
  261. slm/static/rest_framework/docs/css/highlight.css +125 -0
  262. slm/static/rest_framework/docs/css/jquery.json-view.min.css +11 -0
  263. slm/static/rest_framework/docs/img/favicon.ico +0 -0
  264. slm/static/rest_framework/docs/img/grid.png +0 -0
  265. slm/static/rest_framework/docs/js/api.js +321 -0
  266. slm/static/rest_framework/docs/js/highlight.pack.js +2 -0
  267. slm/static/rest_framework/docs/js/jquery.json-view.min.js +7 -0
  268. slm/static/rest_framework/img/grid.png +0 -0
  269. slm/static/rest_framework/js/ajax-form.js +127 -0
  270. slm/static/rest_framework/js/bootstrap.bundle.min.js +7 -0
  271. slm/static/rest_framework/js/bootstrap.bundle.min.js.map +1 -0
  272. slm/static/rest_framework/js/bootstrap.min.js.map +1 -0
  273. slm/static/rest_framework/js/coreapi-0.1.1.js +2043 -0
  274. slm/static/rest_framework/js/csrf.js +52 -0
  275. slm/static/rest_framework/js/default.js +47 -0
  276. slm/static/rest_framework/js/jquery-3.5.1.min.js +2 -0
  277. slm/static/rest_framework/js/prettify-min.js +28 -0
  278. slm/static/slm/css/admin.css +3 -0
  279. slm/static/slm/css/defines.css +82 -0
  280. slm/static/slm/css/forms.css +1 -0
  281. slm/static/slm/css/style.css +1004 -0
  282. slm/static/slm/img/email-branding.png +0 -0
  283. slm/static/slm/img/favicon.ico +0 -0
  284. slm/static/slm/img/login-bg.jpg +0 -0
  285. slm/static/slm/img/slm-logo.svg +4 -0
  286. slm/static/slm/js/autocomplete.js +341 -0
  287. slm/static/slm/js/enums.js +322 -0
  288. slm/static/slm/js/fileIcons.js +30 -0
  289. slm/static/slm/js/form.js +404 -0
  290. slm/static/slm/js/formWidget.js +23 -0
  291. slm/static/slm/js/persistable.js +33 -0
  292. slm/static/slm/js/slm.js +1028 -0
  293. slm/static/slm/js/time24.js +212 -0
  294. slm/static_templates/slm/css/defines.css +26 -0
  295. slm/static_templates/slm/js/enums.js +28 -0
  296. slm/static_templates/slm/js/fileIcons.js +16 -0
  297. slm/static_templates/slm/js/urls.js +5 -0
  298. slm/templates/account/base.html +20 -0
  299. slm/templates/account/email/base.html +43 -0
  300. slm/templates/account/email/base_message.txt +7 -0
  301. slm/templates/account/email/email_confirmation_message.html +16 -0
  302. slm/templates/account/email/email_confirmation_message.txt +7 -0
  303. slm/templates/account/email/email_confirmation_signup_message.html +1 -0
  304. slm/templates/account/email/email_confirmation_signup_message.txt +1 -0
  305. slm/templates/account/email/email_confirmation_signup_subject.txt +1 -0
  306. slm/templates/account/email/email_confirmation_subject.txt +4 -0
  307. slm/templates/account/email/password_reset_key_message.html +28 -0
  308. slm/templates/account/email/password_reset_key_message.txt +9 -0
  309. slm/templates/account/email/password_reset_key_subject.txt +4 -0
  310. slm/templates/account/email/unknown_account_message.html +25 -0
  311. slm/templates/account/email/unknown_account_message.txt +12 -0
  312. slm/templates/account/email/unknown_account_subject.txt +4 -0
  313. slm/templates/account/login.html +67 -0
  314. slm/templates/account/logout.html +38 -0
  315. slm/templates/account/password_change.html +48 -0
  316. slm/templates/account/password_reset.html +51 -0
  317. slm/templates/account/password_reset_done.html +20 -0
  318. slm/templates/account/password_reset_from_key.html +52 -0
  319. slm/templates/account/password_reset_from_key_done.html +17 -0
  320. slm/templates/admin/base.html +7 -0
  321. slm/templates/messages.html +8 -0
  322. slm/templates/rest_framework/README +16 -0
  323. slm/templates/rest_framework/admin/detail.html +10 -0
  324. slm/templates/rest_framework/admin/dict_value.html +11 -0
  325. slm/templates/rest_framework/admin/list.html +32 -0
  326. slm/templates/rest_framework/admin/list_value.html +11 -0
  327. slm/templates/rest_framework/admin/simple_list_value.html +2 -0
  328. slm/templates/rest_framework/admin.html +282 -0
  329. slm/templates/rest_framework/api.html +3 -0
  330. slm/templates/rest_framework/base.html +334 -0
  331. slm/templates/rest_framework/docs/auth/basic.html +42 -0
  332. slm/templates/rest_framework/docs/auth/session.html +40 -0
  333. slm/templates/rest_framework/docs/auth/token.html +41 -0
  334. slm/templates/rest_framework/docs/document.html +37 -0
  335. slm/templates/rest_framework/docs/error.html +71 -0
  336. slm/templates/rest_framework/docs/index.html +55 -0
  337. slm/templates/rest_framework/docs/interact.html +57 -0
  338. slm/templates/rest_framework/docs/langs/javascript-intro.html +5 -0
  339. slm/templates/rest_framework/docs/langs/javascript.html +15 -0
  340. slm/templates/rest_framework/docs/langs/python-intro.html +3 -0
  341. slm/templates/rest_framework/docs/langs/python.html +13 -0
  342. slm/templates/rest_framework/docs/langs/shell-intro.html +3 -0
  343. slm/templates/rest_framework/docs/langs/shell.html +6 -0
  344. slm/templates/rest_framework/docs/link.html +113 -0
  345. slm/templates/rest_framework/docs/sidebar.html +78 -0
  346. slm/templates/rest_framework/filters/base.html +16 -0
  347. slm/templates/rest_framework/filters/ordering.html +17 -0
  348. slm/templates/rest_framework/filters/search.html +13 -0
  349. slm/templates/rest_framework/horizontal/checkbox.html +23 -0
  350. slm/templates/rest_framework/horizontal/checkbox_multiple.html +32 -0
  351. slm/templates/rest_framework/horizontal/dict_field.html +11 -0
  352. slm/templates/rest_framework/horizontal/fieldset.html +16 -0
  353. slm/templates/rest_framework/horizontal/form.html +6 -0
  354. slm/templates/rest_framework/horizontal/input.html +21 -0
  355. slm/templates/rest_framework/horizontal/list_field.html +11 -0
  356. slm/templates/rest_framework/horizontal/list_fieldset.html +13 -0
  357. slm/templates/rest_framework/horizontal/radio.html +42 -0
  358. slm/templates/rest_framework/horizontal/select.html +36 -0
  359. slm/templates/rest_framework/horizontal/select_multiple.html +38 -0
  360. slm/templates/rest_framework/horizontal/textarea.html +21 -0
  361. slm/templates/rest_framework/inline/checkbox.html +8 -0
  362. slm/templates/rest_framework/inline/checkbox_multiple.html +14 -0
  363. slm/templates/rest_framework/inline/dict_field.html +9 -0
  364. slm/templates/rest_framework/inline/fieldset.html +6 -0
  365. slm/templates/rest_framework/inline/form.html +8 -0
  366. slm/templates/rest_framework/inline/input.html +9 -0
  367. slm/templates/rest_framework/inline/list_field.html +9 -0
  368. slm/templates/rest_framework/inline/list_fieldset.html +3 -0
  369. slm/templates/rest_framework/inline/radio.html +25 -0
  370. slm/templates/rest_framework/inline/select.html +24 -0
  371. slm/templates/rest_framework/inline/select_multiple.html +25 -0
  372. slm/templates/rest_framework/inline/textarea.html +9 -0
  373. slm/templates/rest_framework/login.html +3 -0
  374. slm/templates/rest_framework/login_base.html +65 -0
  375. slm/templates/rest_framework/pagination/numbers.html +47 -0
  376. slm/templates/rest_framework/pagination/previous_and_next.html +21 -0
  377. slm/templates/rest_framework/raw_data_form.html +11 -0
  378. slm/templates/rest_framework/schema.js +3 -0
  379. slm/templates/rest_framework/vertical/checkbox.html +16 -0
  380. slm/templates/rest_framework/vertical/checkbox_multiple.html +30 -0
  381. slm/templates/rest_framework/vertical/dict_field.html +7 -0
  382. slm/templates/rest_framework/vertical/fieldset.html +13 -0
  383. slm/templates/rest_framework/vertical/form.html +6 -0
  384. slm/templates/rest_framework/vertical/input.html +17 -0
  385. slm/templates/rest_framework/vertical/list_field.html +7 -0
  386. slm/templates/rest_framework/vertical/list_fieldset.html +7 -0
  387. slm/templates/rest_framework/vertical/radio.html +40 -0
  388. slm/templates/rest_framework/vertical/select.html +34 -0
  389. slm/templates/rest_framework/vertical/select_multiple.html +31 -0
  390. slm/templates/rest_framework/vertical/textarea.html +17 -0
  391. slm/templates/slm/about.html +21 -0
  392. slm/templates/slm/alerts/alert.html +15 -0
  393. slm/templates/slm/alerts/geodesymlinvalid.html +8 -0
  394. slm/templates/slm/alerts/importalert.html +10 -0
  395. slm/templates/slm/alerts.html +18 -0
  396. slm/templates/slm/auth_menu.html +41 -0
  397. slm/templates/slm/base.html +195 -0
  398. slm/templates/slm/emails/alert_issued.html +31 -0
  399. slm/templates/slm/emails/alert_issued.txt +9 -0
  400. slm/templates/slm/emails/base.html +6 -0
  401. slm/templates/slm/emails/changes_rejected.txt +7 -0
  402. slm/templates/slm/emails/review_requested.txt +7 -0
  403. slm/templates/slm/forms/widgets/auto_complete.html +21 -0
  404. slm/templates/slm/forms/widgets/auto_complete_multiple.html +18 -0
  405. slm/templates/slm/forms/widgets/checkbox_multiple.html +6 -0
  406. slm/templates/slm/forms/widgets/inline_multi.html +1 -0
  407. slm/templates/slm/forms/widgets/splitdatetime.html +14 -0
  408. slm/templates/slm/forms/widgets/time24.html +37 -0
  409. slm/templates/slm/help.html +54 -0
  410. slm/templates/slm/messages.html +13 -0
  411. slm/templates/slm/new_site.html +88 -0
  412. slm/templates/slm/profile.html +57 -0
  413. slm/templates/slm/register.html +40 -0
  414. slm/templates/slm/reports/file_log.html +43 -0
  415. slm/templates/slm/reports/head_log.html +23 -0
  416. slm/templates/slm/reports/head_report.html +55 -0
  417. slm/templates/slm/reports/index_log.html +23 -0
  418. slm/templates/slm/reports/index_report.html +71 -0
  419. slm/templates/slm/station/alert.html +8 -0
  420. slm/templates/slm/station/alerts.html +19 -0
  421. slm/templates/slm/station/base.html +104 -0
  422. slm/templates/slm/station/download.html +87 -0
  423. slm/templates/slm/station/edit.html +283 -0
  424. slm/templates/slm/station/form.html +110 -0
  425. slm/templates/slm/station/log.html +18 -0
  426. slm/templates/slm/station/review.html +461 -0
  427. slm/templates/slm/station/upload.html +295 -0
  428. slm/templates/slm/station/uploads/attachment.html +20 -0
  429. slm/templates/slm/station/uploads/geodesyml.html +1 -0
  430. slm/templates/slm/station/uploads/image.html +27 -0
  431. slm/templates/slm/station/uploads/json.html +0 -0
  432. slm/templates/slm/station/uploads/legacy.html +77 -0
  433. slm/templates/slm/top_nav.html +14 -0
  434. slm/templates/slm/user_activity.html +16 -0
  435. slm/templates/slm/widgets/alert_scroll.html +135 -0
  436. slm/templates/slm/widgets/filelist.html +258 -0
  437. slm/templates/slm/widgets/legend.html +12 -0
  438. slm/templates/slm/widgets/log_scroll.html +88 -0
  439. slm/templates/slm/widgets/stationlist.html +233 -0
  440. slm/templatetags/__init__.py +0 -0
  441. slm/templatetags/jinja2.py +9 -0
  442. slm/templatetags/slm.py +459 -0
  443. slm/urls.py +148 -0
  444. slm/utils.py +299 -0
  445. slm/validators.py +297 -0
  446. slm/views.py +654 -0
  447. slm/widgets.py +134 -0
@@ -0,0 +1,541 @@
1
+ """
2
+ If your site log file index is more current than the database state
3
+ (i.e. you've run :ref:`command_import_archive`), you may run this command to pull data
4
+ from the most recent indexed files into the database.
5
+
6
+ .. tip::
7
+
8
+ By default, rich HTML logs of the import process will be written to:
9
+
10
+ ``settings.LOG_DIR / head_from_index.TIMESTAMP``
11
+
12
+ ImportAlerts will also be issued for any errors flagged during import. When,
13
+ appropriate validation flags will be attached to site log fields. This allows you
14
+ to manually clean up any import errors through the web interface after the process
15
+ completes.
16
+ """
17
+
18
+ import inspect
19
+ import os
20
+ import sys
21
+ import typing as t
22
+ from dataclasses import dataclass
23
+ from datetime import datetime
24
+ from pathlib import Path
25
+
26
+ from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
27
+ from django.conf import settings
28
+ from django.db import DatabaseError, models, transaction
29
+ from django.template.loader import render_to_string
30
+ from django.utils.translation import gettext as _
31
+ from django_typer.completers import complete_directory, these_strings
32
+ from django_typer.management import TyperCommand, model_parser_completer
33
+ from django_typer.types import Traceback, Verbosity
34
+ from tqdm import tqdm
35
+ from typer import Argument, Option
36
+ from typing_extensions import Annotated
37
+
38
+ from slm.defines import AlertLevel, SiteLogFormat, SiteLogStatus
39
+ from slm.models import ArchivedSiteLog, ArchiveIndex, ImportAlert, Site
40
+ from slm.models.sitelog import (
41
+ SiteAntenna,
42
+ SiteCollocation,
43
+ SiteForm,
44
+ SiteFrequencyStandard,
45
+ SiteHumiditySensor,
46
+ SiteIdentification,
47
+ SiteLocalEpisodicEffects,
48
+ SiteLocation,
49
+ SiteMoreInformation,
50
+ SiteMultiPathSources,
51
+ SiteOperationalContact,
52
+ SiteOtherInstrumentation,
53
+ SitePressureSensor,
54
+ SiteRadioInterferences,
55
+ SiteReceiver,
56
+ SiteResponsibleAgency,
57
+ SiteSection,
58
+ SiteSignalObstructions,
59
+ SiteSubSection,
60
+ SiteSurveyedLocalTies,
61
+ SiteTemperatureSensor,
62
+ SiteWaterVaporRadiometer,
63
+ )
64
+ from slm.parsing import BaseBinder, Error, Warn
65
+
66
+
67
+ @dataclass
68
+ class ImportRecord:
69
+ index: ArchiveIndex
70
+ file: t.Optional[ArchivedSiteLog] = None
71
+ bound: t.Optional[BaseBinder] = None
72
+ alert: t.Optional[ImportAlert] = None
73
+ exception: t.Optional[str] = None
74
+ failed: str = "" # the reason!
75
+
76
+
77
+ class Command(TyperCommand):
78
+ help = _("Update the head state of each site from the most recent index.")
79
+ suppressed_base_arguments = {
80
+ "version",
81
+ "pythonpath",
82
+ "settings",
83
+ }
84
+
85
+ sites: t.Sequence[Site]
86
+ clean: bool = True
87
+ prompt: bool = True
88
+ logs: Path = Path("{LOG_DIR}") / "head_from_index.{TIMESTAMP}"
89
+ verbosity = 1
90
+
91
+ indexes: t.Sequence[ArchiveIndex]
92
+
93
+ formats: t.List[t.Union[str, SiteLogFormat]] = ["log"]
94
+ # list(
95
+ # set([fmt.ext for fmt in SiteLogFormat])
96
+ # )
97
+ unsupported = [SiteLogFormat.GEODESY_ML, SiteLogFormat.JSON]
98
+
99
+ imports: t.List[ImportRecord]
100
+ failed_imports: t.List[ImportRecord]
101
+ warnings: int
102
+ total_warnings: int
103
+ errors: int
104
+ total_errors: int
105
+
106
+ log_file_tmpl = "slm/reports/file_log.html"
107
+ log_index_tmpl = "slm/reports/head_log.html"
108
+
109
+ SECTION_MODELS = {
110
+ 0: SiteForm,
111
+ 1: SiteIdentification,
112
+ 2: SiteLocation,
113
+ 3: SiteReceiver,
114
+ 4: SiteAntenna,
115
+ 5: SiteSurveyedLocalTies,
116
+ 6: SiteFrequencyStandard,
117
+ 7: SiteCollocation,
118
+ (8, 1): SiteHumiditySensor,
119
+ (8, 2): SitePressureSensor,
120
+ (8, 3): SiteTemperatureSensor,
121
+ (8, 4): SiteWaterVaporRadiometer,
122
+ (8, 5): SiteOtherInstrumentation,
123
+ (9, 1): SiteRadioInterferences,
124
+ (9, 2): SiteMultiPathSources,
125
+ (9, 3): SiteSignalObstructions,
126
+ 10: SiteLocalEpisodicEffects,
127
+ 11: SiteOperationalContact,
128
+ 12: SiteResponsibleAgency,
129
+ 13: SiteMoreInformation,
130
+ }
131
+
132
+ def yes(self, ipt):
133
+ return ipt.lower() in {"y", "yes", "true", "continue"}
134
+
135
+ def handle(
136
+ self,
137
+ sites: Annotated[
138
+ t.Optional[t.List[Site]],
139
+ Argument(
140
+ **model_parser_completer(Site, "name"),
141
+ help=_("The sites (by name) to update. (all active sites by default)"),
142
+ ),
143
+ ] = None,
144
+ no_prompt: Annotated[
145
+ bool, Option("--no-prompt", help=_("Do not ask before proceeding."))
146
+ ] = not prompt,
147
+ logs: Annotated[
148
+ Path,
149
+ Option(
150
+ help=_(
151
+ "Write logs to this directory. No logs will be written by default."
152
+ ),
153
+ shell_complete=complete_directory,
154
+ ),
155
+ ] = logs,
156
+ formats: Annotated[
157
+ t.List[
158
+ str
159
+ ], # list of SiteLogFormat's does not work for some upstream reason
160
+ Option(
161
+ "--format",
162
+ metavar="FORMAT",
163
+ help=_(
164
+ "Only import state from these specified format(s) (in preference order)."
165
+ ),
166
+ shell_complete=these_strings(set([fmt.ext for fmt in SiteLogFormat])),
167
+ ),
168
+ ] = formats,
169
+ verbosity: Verbosity = verbosity,
170
+ traceback: Traceback = False,
171
+ ):
172
+ self.sites = sites or list(Site.objects.active())
173
+ self.prompt = not no_prompt
174
+
175
+ if self.prompt and not self.yes(
176
+ input(
177
+ _(
178
+ "This will clear and re-import data from the serialized archive for "
179
+ "{stations} stations. This cannot be undone. Continue? (y/N): "
180
+ ).format(stations=len(sites))
181
+ )
182
+ ):
183
+ return
184
+
185
+ self.logs = Path(
186
+ str(logs).format(
187
+ LOG_DIR=getattr(settings, "LOG_DIR", "./"),
188
+ TIMESTAMP=datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
189
+ )
190
+ )
191
+ self.verbosity = verbosity
192
+ self.traceback = traceback
193
+ self.formats = [SiteLogFormat(fmt) for fmt in formats]
194
+ for unsupported in self.unsupported:
195
+ if unsupported in self.formats:
196
+ self.secho(
197
+ _("{format} imports are not yet supported").format(
198
+ format=unsupported
199
+ ),
200
+ fg="yellow",
201
+ )
202
+ self.formats.remove(unsupported)
203
+ self.warnings = 0
204
+ self.total_warnings = 0
205
+ self.errors = 0
206
+ self.total_errors = 0
207
+
208
+ if SiteLogFormat.GEODESY_ML in self.formats:
209
+ from slm.parsing.xsd import load_schemas
210
+
211
+ load_schemas()
212
+
213
+ self.imports = []
214
+ self.failed_imports = []
215
+
216
+ self.indexes = (
217
+ ArchiveIndex.objects.filter(site__in=self.sites, end__isnull=True)
218
+ .order_by("site", "-begin")
219
+ .distinct("site")
220
+ )
221
+
222
+ with tqdm(
223
+ total=self.indexes.count(),
224
+ desc=_("Updating Head"),
225
+ unit="sites",
226
+ postfix={"site": ""},
227
+ disable=self.verbosity != 1,
228
+ ) as p_bar:
229
+ for index in self.indexes:
230
+ p_bar.set_postfix({"site": index.site.name})
231
+ try:
232
+ record = ImportRecord(index=index)
233
+ if self.update_head(record):
234
+ self.imports.append(record)
235
+ else:
236
+ self.failed_imports.append(record)
237
+ ImportAlert.objects.update_or_create(
238
+ site=index.site,
239
+ defaults={
240
+ "level": AlertLevel.ERROR,
241
+ "header": _("Import from index failed."),
242
+ "detail": record.failed
243
+ }
244
+ )
245
+ except Exception as err:
246
+ if self.traceback:
247
+ raise err
248
+
249
+ import traceback
250
+
251
+ record.exception = traceback.format_exc()
252
+ record.failed = f"{type(err)}: {str(err)}"
253
+ self.failed_imports.append(record)
254
+ ImportAlert.objects.update_or_create(
255
+ site=index.site,
256
+ defaults={
257
+ "level": AlertLevel.ERROR,
258
+ "header": _("Import from index failed."),
259
+ "detail": record.failed
260
+ }
261
+ )
262
+ p_bar.update(n=1)
263
+
264
+ if self.verbosity >= 1:
265
+ if self.imports:
266
+ self.secho(
267
+ _(
268
+ "Imported data from {stations} serialized station archives."
269
+ ).format(stations=len(self.imports)),
270
+ fg="green",
271
+ )
272
+ if self.warnings:
273
+ self.secho(
274
+ _("{warnings} station imports have warnings.").format(
275
+ warnings=self.warnings
276
+ ),
277
+ fg="yellow",
278
+ )
279
+ if self.errors:
280
+ self.secho(
281
+ _("{errors} station imports have errors.").format(
282
+ errors=self.errors
283
+ ),
284
+ fg="red",
285
+ )
286
+ if self.failed_imports:
287
+ self.secho(
288
+ _(
289
+ "Failed to import data from {stations} serialized station archives."
290
+ ).format(stations=len(self.failed_imports)),
291
+ fg="red",
292
+ )
293
+
294
+ if self.logs:
295
+ os.makedirs(self.logs, exist_ok=True)
296
+ with tqdm(
297
+ total=len(self.imports) + len(self.failed_imports),
298
+ desc=_("Writing logs"),
299
+ unit="station",
300
+ postfix={"station": ""},
301
+ disable=self.verbosity != 1,
302
+ ) as p_bar:
303
+ for record in [*self.imports, *self.failed_imports]:
304
+ p_bar.set_postfix({"station": record.index.site.name})
305
+ file_log = render_to_string(
306
+ self.log_file_tmpl,
307
+ {
308
+ "site": record.index.site,
309
+ "filename": os.path.basename(record.file.name),
310
+ "file": record.file.contents,
311
+ "findings": record.bound.parsed.findings_context,
312
+ "alert": record.alert,
313
+ "exception": record.exception,
314
+ "failed": record.failed,
315
+ "format": record.file.log_format,
316
+ "SiteLogFormat": SiteLogFormat,
317
+ },
318
+ )
319
+ log_file = self.logs / f"{record.index.site.name}.html"
320
+ if self.verbosity > 1:
321
+ self.secho(
322
+ _("Writing parsing log for {station} to {log_file}").format(
323
+ station=record.index.site.name, log_file=log_file
324
+ ),
325
+ fg="blue",
326
+ )
327
+ with open(log_file, "wt") as log_f:
328
+ log_f.write(file_log)
329
+ p_bar.update(n=1)
330
+
331
+ # todo write index
332
+ log_index = render_to_string(
333
+ self.log_index_tmpl,
334
+ {
335
+ "command": " ".join([Path(sys.argv[0]).name, *sys.argv[1:]]),
336
+ "runtime": datetime.now(),
337
+ "imports": self.imports,
338
+ "failed_imports": self.failed_imports,
339
+ "total_warnings": self.total_warnings,
340
+ "total_errors": self.total_errors,
341
+ },
342
+ )
343
+ index_file = self.logs / "index.html"
344
+ with open(index_file, "wt") as log_f:
345
+ log_f.write(log_index)
346
+
347
+ if self.verbosity > 0:
348
+ return index_file.absolute()
349
+
350
+ def update_head(self, record: ImportRecord) -> bool:
351
+ index = record.index
352
+ for fmt in self.formats:
353
+ record.file = index.files.filter(log_format=fmt).first()
354
+ if record.file:
355
+ break
356
+
357
+ if not record.file:
358
+ record.failed = _(
359
+ "Unable to find a current indexed file in one of the specified formats: {formats}"
360
+ ).format(formats=self.formats)
361
+ return False
362
+
363
+ with transaction.atomic():
364
+ # clear *all* current data for the site!
365
+ for section in self.SECTION_MODELS.values():
366
+ section.objects.filter(site=index.site).delete()
367
+ ########################
368
+
369
+ ImportAlert.objects.filter(site=index.site).delete()
370
+ record.bound = record.file.parse()
371
+ alert = {}
372
+ for section in reversed(record.bound.parsed.sections.values()):
373
+ if not section.contains_values:
374
+ # likely a placeholder section
375
+ continue
376
+
377
+ section_model = self.SECTION_MODELS.get(section.heading_index, None)
378
+ if (
379
+ not section_model
380
+ or not inspect.isclass(section_model)
381
+ or not issubclass(section_model, SiteSection)
382
+ ):
383
+ finding_at_line = record.bound.parsed.findings.get(
384
+ section.line_no, None
385
+ )
386
+ if (
387
+ finding_at_line is None
388
+ or finding_at_line.priority < Warn.priority
389
+ ):
390
+ record.bound.parsed.add_finding(
391
+ Warn(
392
+ lineno=section.line_no,
393
+ parser=section.parser,
394
+ message=_("Unexpected section!"),
395
+ section=section,
396
+ )
397
+ )
398
+ continue
399
+
400
+ field_updates = {
401
+ "site": index.site,
402
+ "published": True,
403
+ "edited": index.begin,
404
+ "_flags": {},
405
+ }
406
+ # many-many relations have to be set differently
407
+ many_relations = {}
408
+ try:
409
+ if not section.binding:
410
+ continue
411
+ for field, value in section.binding.items():
412
+ try:
413
+ if field := section_model._meta.get_field(field):
414
+ if isinstance(field, models.ManyToManyField):
415
+ many_relations[field.name] = value
416
+ continue
417
+ elif isinstance(
418
+ field, models.fields.related.RelatedField
419
+ ):
420
+ if not isinstance(value, field.related_model):
421
+ value = field.related_model.objects.get_by_natural_key(
422
+ value
423
+ )
424
+ field_updates[field.name] = value
425
+ except FieldDoesNotExist:
426
+ pass
427
+ except ObjectDoesNotExist:
428
+ alert["level"] = AlertLevel.ERROR
429
+ alert.setdefault("detail", "")
430
+ alert["detail"] = _(
431
+ "{detail}Unable to resolve '{value}'\n."
432
+ ).format(detail=alert["detail"], value=value)
433
+ continue
434
+
435
+ for parameter in section.parameters.values():
436
+ # pull out the parser findings based on line number, and add them as admin flags
437
+ # todo binder/parser interface should make this easier
438
+ for var in (parameter.binding or {}).keys():
439
+ if var not in field_updates:
440
+ continue
441
+ error = None
442
+ warning = None
443
+ for line_no in range(parameter.line_no, parameter.line_end + 1):
444
+ if error := record.bound.parsed.errors.get(line_no, None):
445
+ break
446
+ if not warning:
447
+ warning = record.bound.parsed.warnings.get(
448
+ line_no, None
449
+ )
450
+
451
+ flag = error or warning
452
+ if flag:
453
+ field_updates["_flags"][var] = (
454
+ f"Import issue?: {flag.message}"
455
+ )
456
+
457
+ field_updates["num_flags"] = len(field_updates["_flags"])
458
+ if isinstance(section_model, SiteSubSection):
459
+ field_updates["subsection"] = section.heading_index[-1]
460
+
461
+ try:
462
+ if section_model is SiteForm:
463
+ form = SiteForm()
464
+ for field, value in field_updates.items():
465
+ setattr(form, field, value)
466
+ form.previous = (
467
+ ArchiveIndex.objects.filter(
468
+ site=index.site, end__lte=index.begin
469
+ )
470
+ .order_by("-end")
471
+ .first()
472
+ )
473
+ form.save(skip_update=True, set_previous=False)
474
+ else:
475
+ model = section_model.objects.create(**field_updates)
476
+ if many_relations:
477
+ for field, relations in many_relations.items():
478
+ getattr(model, field).set(relations)
479
+ model.save()
480
+ except DatabaseError as db_err:
481
+ finding_at_line = record.bound.parsed.findings.get(
482
+ section.line_no, None
483
+ )
484
+ if (
485
+ finding_at_line is None
486
+ or finding_at_line.priority < Error.priority
487
+ ):
488
+ record.bound.parsed.add_finding(
489
+ Error(
490
+ lineno=section.line_no,
491
+ parser=section.parser,
492
+ message=_("Unable to save section: {}").format(
493
+ str(db_err)
494
+ ),
495
+ section=section,
496
+ )
497
+ )
498
+ raise
499
+
500
+ self.total_errors += len(record.bound.parsed.errors)
501
+ self.total_warnings += len(record.bound.parsed.warnings)
502
+ if record.bound.parsed.errors or record.bound.parsed.warnings:
503
+ level = (
504
+ AlertLevel.ERROR
505
+ if record.bound.parsed.errors
506
+ else AlertLevel.WARNING
507
+ )
508
+ alert.setdefault("level", level)
509
+ if alert["level"].value < level.value:
510
+ alert["level"] = level
511
+ alert.update(
512
+ {
513
+ "file_contents": "\n".join(record.bound.lines),
514
+ "findings": record.bound.parsed.findings_context,
515
+ "log_format": record.file.log_format,
516
+ }
517
+ )
518
+ if alert:
519
+ alert["site"] = index.site
520
+ alert.setdefault("level", AlertLevel.WARNING)
521
+ if alert["level"] is AlertLevel.ERROR:
522
+ alert.setdefault(
523
+ "header", _("Errors were encountered during import.")
524
+ )
525
+ self.errors += 1
526
+ if alert["level"] is AlertLevel.WARNING:
527
+ alert.setdefault(
528
+ "header", _("Warnings were encountered during import.")
529
+ )
530
+ self.warnings += 1
531
+ record.alert = ImportAlert.objects.create(**alert)
532
+
533
+ if index.site.status in [
534
+ *SiteLogStatus.active_states(),
535
+ SiteLogStatus.EMPTY,
536
+ ]:
537
+ index.site.status = SiteLogStatus.PUBLISHED
538
+ index.site.save()
539
+
540
+ index.site.synchronize(skip_form_updates=True)
541
+ return True