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
slm/models/index.py ADDED
@@ -0,0 +1,428 @@
1
+ import os
2
+
3
+ from django.core.files.base import ContentFile
4
+ from django.db import models, transaction
5
+ from django.db.models import F, OuterRef, Q, Subquery, Value
6
+ from django.db.models.functions import (
7
+ Cast,
8
+ Concat,
9
+ ExtractDay,
10
+ ExtractMonth,
11
+ ExtractYear,
12
+ Lower,
13
+ LPad,
14
+ Now,
15
+ Substr,
16
+ )
17
+ from django.utils.functional import cached_property
18
+ from django.utils.timezone import now
19
+ from django.utils.translation import gettext_lazy as _
20
+
21
+ from slm.defines import (
22
+ GeodesyMLVersion,
23
+ RinexVersion,
24
+ SiteLogFormat,
25
+ SiteLogStatus,
26
+ SLMFileType,
27
+ )
28
+ from slm.models.data import DataAvailability
29
+ from slm.models.system import SiteFile
30
+ from slm.parsing import BaseBinder
31
+ from slm.parsing import legacy as legacy_parsing
32
+ from slm.parsing import xsd as xsd_parsing
33
+
34
+
35
+ class ArchiveIndexManager(models.Manager):
36
+ def regenerate(self, site, log_format):
37
+ """
38
+ Regenerate the index file for this index. This will only be done for
39
+ the head index for this file.
40
+
41
+ :param site: The site to regenerate the archived index file for.
42
+ :param log_format: The log format to regenerate.
43
+ """
44
+ new_file = ArchivedSiteLog.objects.from_index(
45
+ index=self.get_queryset().filter(site=site).order_by("-begin").first(),
46
+ log_format=log_format,
47
+ regenerate=True,
48
+ )
49
+ return new_file
50
+
51
+ def add_index(self, site, formats=list(SiteLogFormat)):
52
+ assert site.last_publish, "last_publish must be set before calling add_index"
53
+ existing = self.filter(site=site, begin=site.last_publish).first()
54
+ if existing:
55
+ return existing
56
+
57
+ self.close_index(site)
58
+
59
+ new_index = self.create(site=site, begin=site.last_publish, end=None)
60
+
61
+ for log_format in formats:
62
+ if log_format in {SiteLogFormat.JSON}:
63
+ continue # todo - remove
64
+ ArchivedSiteLog.objects.from_site(site=site, log_format=log_format)
65
+
66
+ return new_index
67
+
68
+ def close_index(self, site):
69
+ if site.last_publish:
70
+ last = (
71
+ self.filter(site=site)
72
+ .filter(
73
+ Q(begin__lte=site.last_publish) & Q(end__isnull=True)
74
+ | Q(end__gt=site.last_publish)
75
+ )
76
+ .first()
77
+ )
78
+ if last:
79
+ last.end = site.last_publish
80
+ last.save()
81
+
82
+ def create(self, **kwargs):
83
+ return self.insert_index(**kwargs)
84
+
85
+ def get_or_create(self, site, begin, **kwargs):
86
+ self.insert_index(site=site, begin=begin, **kwargs)
87
+
88
+ def insert_index(self, begin, site, **kwargs):
89
+ """
90
+ Insert a new index into an existing index deck (i.e. between existing
91
+ indexes).
92
+ """
93
+ existing = self.get_queryset().filter(site=site, begin=begin).first()
94
+ if existing:
95
+ return existing
96
+ next_index = (
97
+ self.get_queryset()
98
+ .filter(site=site, begin__gt=begin)
99
+ .order_by("begin")
100
+ .first()
101
+ )
102
+ prev_index = (
103
+ self.get_queryset()
104
+ .filter(site=site, begin__lt=begin)
105
+ .order_by("-begin")
106
+ .first()
107
+ )
108
+ kwargs.setdefault("end", next_index.begin if next_index else None)
109
+ if prev_index:
110
+ prev_index.end = begin
111
+ prev_index.save()
112
+ return super().create(begin=begin, site=site, **kwargs)
113
+
114
+
115
+ class ArchiveIndexQuerySet(models.QuerySet):
116
+ def delete(self):
117
+ """
118
+ We can't just delete an archive to remove it - we also have to
119
+ update the end time of the previous archive in the index if there
120
+ is one to reflect the end time of the deleted log
121
+ """
122
+ from slm.models import Site, SiteForm
123
+
124
+ with transaction.atomic():
125
+ # also, sites where the deleted index is the current index
126
+ # (end=null) that are in the published state should be set to
127
+ # updated
128
+ # we trigger unpublished state by updating the SiteForm
129
+ # prepared date and synchronizing
130
+ published_sites = Site.objects.filter(
131
+ Q(indexes__in=self.filter(end__isnull=True))
132
+ & Q(status=SiteLogStatus.PUBLISHED)
133
+ ).distinct()
134
+
135
+ # these are the indexes that remain that must be updated - that
136
+ # includes any non-deleted index immediately preceding a deleted
137
+ # index, indexes immediately following a deleted index do not
138
+ # need to be updated
139
+ after = self.filter(Q(site=OuterRef("site")) & Q(begin=OuterRef("end")))
140
+ before = self.filter(Q(site=OuterRef("site")) & Q(end=OuterRef("begin")))
141
+ new_bookends = (
142
+ ArchiveIndex.objects.annotate(before=Subquery(before.values("pk")[:1]))
143
+ .filter(
144
+ Q(site=OuterRef("site"))
145
+ & Q(begin__gte=OuterRef("end"))
146
+ & ~Q(pk__in=self)
147
+ & Q(before__isnull=False)
148
+ )
149
+ .order_by("end")
150
+ )
151
+ adjacent_indexes = ArchiveIndex.objects.annotate(
152
+ adjacent=Subquery(after.values("pk")[:1]),
153
+ new_end=Subquery(new_bookends.values("begin")[:1]),
154
+ ).filter(Q(adjacent__isnull=False) & ~Q(pk__in=self))
155
+
156
+ # we use the new last indexes' old last end date
157
+ forms = []
158
+ for form in SiteForm.objects.filter(site__in=published_sites):
159
+ form.pk = None
160
+ form.published = False
161
+ form.date_prepared = now().date()
162
+ forms.append(form)
163
+
164
+ SiteForm.objects.bulk_create(forms)
165
+ published_sites.synchronize_denormalized_state()
166
+
167
+ adjacent_indexes.update(end=F("new_end"))
168
+ deleted = super().delete()
169
+ return deleted
170
+
171
+ @staticmethod
172
+ def epoch_q(epoch=None):
173
+ if epoch is None:
174
+ epoch = now()
175
+ return Q(begin__lte=epoch) & (Q(end__gt=epoch) | Q(end__isnull=True))
176
+
177
+ def at_epoch(self, epoch=None):
178
+ return self.filter(self.epoch_q(epoch))
179
+
180
+ def public(self):
181
+ return self.filter(site__agencies__public=True)
182
+
183
+ def availability(self):
184
+ last_data_avail = DataAvailability.objects.filter(site=OuterRef("pk")).order_by(
185
+ "-last"
186
+ )
187
+ return self.annotate(
188
+ last_data_time=Subquery(last_data_avail.values("last")[:1]),
189
+ last_data=Now() - F("last_data_time"),
190
+ last_rinex2=Subquery(
191
+ last_data_avail.filter(RinexVersion(2).major_q()).values("last")[:1]
192
+ ),
193
+ last_rinex3=Subquery(
194
+ last_data_avail.filter(RinexVersion(3).major_q()).values("last")[:1]
195
+ ),
196
+ last_rinex4=Subquery(
197
+ last_data_avail.filter(RinexVersion(4).major_q()).values("last")[:1]
198
+ ),
199
+ )
200
+
201
+ def annotate_filenames(
202
+ self, name_len=None, field_name="filename", lower_case=False, log_format=None
203
+ ):
204
+ """
205
+ Add the log names (w/o) extension as a property called filename to
206
+ each site.
207
+
208
+ :param name_len: If given a number, the filename will start with only
209
+ the first name_len characters of the site name.
210
+ :param field_name: Change the name of the annotated field.
211
+ :param lower_case: Filenames will be lowercase if true.
212
+ :param log_format: If given, add the extension for the given format
213
+ :return: A queryset with the filename annotation added.
214
+ """
215
+ name_str = F("site__name")
216
+ if name_len:
217
+ name_str = Cast(
218
+ Substr("site__name", 1, length=name_len), models.CharField()
219
+ )
220
+
221
+ if lower_case:
222
+ name_str = Lower(name_str)
223
+
224
+ parts = [
225
+ name_str,
226
+ Value("_"),
227
+ Cast(ExtractYear("begin"), models.CharField()),
228
+ LPad(
229
+ Cast(ExtractMonth("begin"), models.CharField()), 2, fill_text=Value("0")
230
+ ),
231
+ LPad(
232
+ Cast(ExtractDay("begin"), models.CharField()), 2, fill_text=Value("0")
233
+ ),
234
+ ]
235
+ if log_format:
236
+ parts.append(Value(f".{log_format.ext}"))
237
+
238
+ return self.annotate(**{field_name: Concat(*parts)})
239
+
240
+
241
+ class ArchiveIndex(models.Model):
242
+ site = models.ForeignKey(
243
+ "slm.Site", on_delete=models.CASCADE, null=False, related_name="indexes"
244
+ )
245
+
246
+ # the point in time at which this record begins being valid
247
+ begin = models.DateTimeField(
248
+ null=False,
249
+ db_index=True,
250
+ help_text=_("The point in time at which this archive became valid."),
251
+ )
252
+
253
+ # the point in time at which this record stops being valid
254
+ end = models.DateTimeField(
255
+ null=True,
256
+ db_index=True,
257
+ help_text=_("The point in time at which this archive stopped being valid."),
258
+ )
259
+
260
+ objects = ArchiveIndexManager.from_queryset(ArchiveIndexQuerySet)()
261
+
262
+ def __str__(self):
263
+ return (
264
+ f"{self.site.name} | {self.begin.date()} - "
265
+ f'{self.end.date() if self.end else "present"}'
266
+ )
267
+
268
+ def delete(self, using=None, keep_parents=False):
269
+ """
270
+ Deleting an index requires updating the end time of the previous
271
+ indexes - we use the queryset delete method to do this.
272
+ """
273
+ return ArchiveIndex.objects.filter(pk=self.pk).delete()
274
+
275
+ class Meta:
276
+ ordering = ("-begin",)
277
+ indexes = [
278
+ models.Index(fields=("begin", "end")),
279
+ models.Index(fields=("site", "begin", "end")),
280
+ ]
281
+ unique_together = (("site", "begin"),)
282
+ verbose_name = "Archive Index"
283
+ verbose_name_plural = "Archive Index"
284
+
285
+
286
+ class ArchivedSiteLogManager(models.Manager):
287
+ """
288
+ This manager is responsible for mediating access to serialized site logs.
289
+ Most frequently it will be fetching logs that match the given criteria from
290
+ disk, but it might also generate a log from the edit stack if an archived
291
+ file does not exist.
292
+ """
293
+
294
+ def from_index(self, index, log_format, regenerate=False):
295
+ from slm.api.serializers import SiteLogSerializer
296
+
297
+ if index:
298
+ file = index.files.filter(log_format=log_format).first()
299
+ if file and not regenerate:
300
+ return file
301
+ elif file:
302
+ file.delete()
303
+ return self.model.objects.create(
304
+ site=index.site,
305
+ log_format=log_format,
306
+ index=index,
307
+ timestamp=index.begin,
308
+ mimetype=log_format.mimetype,
309
+ file_type=SLMFileType.SITE_LOG,
310
+ name=index.site.get_filename(log_format=log_format, epoch=index.begin),
311
+ file=ContentFile(
312
+ SiteLogSerializer(instance=index.site)
313
+ .format(log_format)
314
+ .encode("utf-8"),
315
+ name=index.site.get_filename(
316
+ log_format=log_format, epoch=index.begin
317
+ ),
318
+ ),
319
+ gml_version=(
320
+ GeodesyMLVersion.latest()
321
+ if log_format is SiteLogFormat.GEODESY_ML
322
+ else None
323
+ ),
324
+ )
325
+ return None
326
+
327
+ def from_site(self, site, log_format=SiteLogFormat.LEGACY, epoch=None):
328
+ index = ArchiveIndex.objects.filter(site=site).at_epoch(epoch=epoch).first()
329
+ if index:
330
+ return self.from_index(index, log_format=log_format)
331
+ return None
332
+
333
+
334
+ class ArchivedSiteLogQuerySet(models.QuerySet):
335
+ def annotate_filenames(
336
+ self, name_len=None, field_name="filename", lower_case=False, log_format=None
337
+ ):
338
+ """
339
+ Add the log names (w/o) extension as a property called filename to
340
+ each site.
341
+
342
+ :param name_len: If given a number, the filename will start with only
343
+ the first name_len characters of the site name.
344
+ :param field_name: Change the name of the annotated field.
345
+ :param lower_case: Filenames will be lowercase if true.
346
+ :param log_format: If given, add the extension for the given format
347
+ :return: A queryset with the filename annotation added.
348
+ """
349
+ name_str = F("site__name")
350
+ if name_len:
351
+ name_str = Cast(
352
+ Substr("site__name", 1, length=name_len), models.CharField()
353
+ )
354
+
355
+ if lower_case:
356
+ name_str = Lower(name_str)
357
+
358
+ parts = [
359
+ name_str,
360
+ Value("_"),
361
+ Cast(ExtractYear("index__begin"), models.CharField()),
362
+ LPad(
363
+ Cast(ExtractMonth("index__begin"), models.CharField()),
364
+ 2,
365
+ fill_text=Value("0"),
366
+ ),
367
+ LPad(
368
+ Cast(ExtractDay("index__begin"), models.CharField()),
369
+ 2,
370
+ fill_text=Value("0"),
371
+ ),
372
+ ]
373
+ if log_format:
374
+ parts.append(Value(f".{log_format.ext}"))
375
+ return self.annotate(**{field_name: Concat(*parts)})
376
+
377
+
378
+ class ArchivedSiteLog(SiteFile):
379
+ SUB_DIRECTORY = "archive"
380
+
381
+ index = models.ForeignKey(
382
+ ArchiveIndex, on_delete=models.CASCADE, related_name="files"
383
+ )
384
+
385
+ name = models.CharField(max_length=50)
386
+
387
+ objects = ArchivedSiteLogManager.from_queryset(ArchivedSiteLogQuerySet)()
388
+
389
+ def __str__(self):
390
+ if self.name:
391
+ return f"[{self.index}] {self.name}"
392
+ return f"[{self.index}] {os.path.basename(self.file.path)}"
393
+
394
+ def parse(self) -> BaseBinder:
395
+ if self.log_format is SiteLogFormat.GEODESY_ML:
396
+ return xsd_parsing.SiteLogBinder(
397
+ xsd_parsing.SiteLogParser(self.contents, site_name=self.site.name)
398
+ )
399
+ elif self.log_format in [SiteLogFormat.LEGACY, SiteLogFormat.ASCII_9CHAR]:
400
+ return legacy_parsing.SiteLogBinder(
401
+ legacy_parsing.SiteLogParser(self.contents, site_name=self.site.name)
402
+ )
403
+ raise NotImplementedError(
404
+ _("{format} is not currently supported for site log parsing.").format(
405
+ format=self.log_format
406
+ )
407
+ )
408
+
409
+ @cached_property
410
+ def contents(self) -> str:
411
+ """
412
+ Decode the contents of a log file. The site log format has been around since the
413
+ early 1990s so we may encounter exotic encodings.
414
+
415
+ :param contents: The bytes of the log file contents.
416
+ :return a decoded string of the contents
417
+ """
418
+ file_bytes = self.file.open("rb").read()
419
+ try:
420
+ return file_bytes.decode("utf-8")
421
+ except UnicodeDecodeError:
422
+ try:
423
+ return file_bytes.decode("ascii")
424
+ except UnicodeDecodeError:
425
+ return file_bytes.decode("latin")
426
+
427
+ class Meta:
428
+ unique_together = ("index", "log_format")