Source code for seed_vault.ui.components.settings

import streamlit as st
import pandas as pd
import time

from copy import deepcopy
from seed_vault.enums.common import ClientType
from seed_vault.models.config import AuthConfig, SeismoLoaderSettings
from seed_vault.ui.app_pages.helpers.common import save_filter, reset_config

from seed_vault.service.seismoloader import populate_database_from_sds
from seed_vault.utils.constants import DOC_BASE_URL

import os
import jinja2
from copy import deepcopy


[docs] class SettingsComponent: settings: SeismoLoaderSettings old_settings: SeismoLoaderSettings is_new_cred_added = None df_clients = None def __init__(self, settings: SeismoLoaderSettings): self.settings = settings self.old_settings = deepcopy(settings)
[docs] def add_credential(self): for item in self.settings.auths: if item.nslc_code == "new": return False self.settings.auths.append(AuthConfig(nslc_code="new", username="new", password="new")) save_filter(self.settings) return True
[docs] def reset_is_new_cred_added(self): # time.sleep(5) self.is_new_cred_added = None
# st.rerun()
[docs] def refresh_filters(self): changes = self.settings.has_changed(self.old_settings) if changes.get('has_changed', False): self.old_settings = deepcopy(self.settings) save_filter(self.settings) st.rerun()
[docs] def render_auth(self): st.write("## Auth Records") # auths_lst = [item.model_dump() for item in settings.auths] # edited_df = st.data_editor(pd.DataFrame(auths_lst), num_rows="dynamic") for index, auth in enumerate(self.settings.auths): c1,c2,c3,c4 = st.columns([1,1,1,3]) # st.write(f"### Credential Set {index + 1}") with c1: nslc_code = st.text_input(f"N.S.L.C. code", help="NSLC Code for (Network.Station.Location.Channel)", value=auth.nslc_code, key=f"nslc_{index}") with c2: username = st.text_input(f"Username", value=auth.username, key=f"username_{index}") with c3: password = st.text_input(f"Password", value=auth.password, type="password", key=f"password_{index}") # Update session state with edited values self.settings.auths[index] = AuthConfig(nslc_code=nslc_code, username=username, password=password) with c4: st.text("") st.text("") if st.button(f"Delete", key=f"remove_{index}"): try: self.settings.auths.pop(index) save_filter(self.settings) self.reset_is_new_cred_added() st.rerun() except Exception as e: st.error(f"An error occured: {str(e)}") if st.button("Add Credential Set"): try: self.reset_is_new_cred_added() self.is_new_cred_added = self.add_credential() st.rerun() except Exception as e: st.error(f"An error occured: {str(e)}") if self.is_new_cred_added is not None: if self.is_new_cred_added: st.success("Added a new auth. Please fill up the entries.") else: st.error("You cannot define duplicate N.S.L.C code.")
# self.reset_is_new_cred_added()
[docs] def render_db(self): try: c1, c2 = st.columns([1,1]) with c1: self.settings.db_path = st.text_input("Database Path", value=self.settings.db_path, help="FULL path to your database, e.g. /archive/database.sqlite") self.settings.sds_path = st.text_input("Local Seismic Data Archive Path in [SDS structure](https://www.seiscomp.de/seiscomp3/doc/applications/slarchive/SDS.html)", value=self.settings.sds_path, help="ROOT path of your archive. If you change this you may have to resync your database.") st.write("## Sync database with existing archive") c1, c2, c3, c4 = st.columns([1,1,1,2]) with c1: search_patterns = st.text_input("Search Patterns", value="??.*.*.???.?.????.???", help="To input multiple values, separate your entries with comma.").strip().split(",") with c4: c11, c22 = st.columns([1,1]) with c11: selected_date_type = st.selectbox("Date selection", ["All", "Custom Time"], index=0) with c22: if selected_date_type == "All": newer_than=None else: newer_than = st.date_input("Update Since") with c2: self.settings.processing.num_processes = int(st.number_input( "Number of Processors", value=self.settings.processing.num_processes, min_value=0, help="Number of Processors >= 0. If set to zero, the app will use all available cpu to perform the operation." )) with c3: self.settings.processing.gap_tolerance = int(st.number_input( "Gap Tolerance (s)", value=self.settings.processing.gap_tolerance, min_value=0 )) if st.button("Sync Database", help="Synchronizes your SDS archive given the above parameters."): self.reset_is_new_cred_added() save_filter(self.settings) populate_database_from_sds( sds_path=self.settings.sds_path, db_path=self.settings.db_path, search_patterns=search_patterns, newer_than=newer_than, num_processes=self.settings.processing.num_processes, gap_tolerance=self.settings.processing.gap_tolerance ) self.refresh_filters() except Exception as e: st.error(str(e))
[docs] def render_clients(self): c1, c2 = st.columns([1,1]) extra_clients = self.settings.client_url_mapping.get_clients(client_type = ClientType.EXTRA) # load_extra_client() orig_clients = self.settings.client_url_mapping.get_clients(client_type = ClientType.ORIGINAL) with c1: st.write("## Extra Clients") df = pd.DataFrame([{"Client Name": k, "Url": v} for k,v in extra_clients.items()]) if df.empty: df = pd.DataFrame(columns=["Client Name", "Url"]) self.df_clients = st.data_editor(df, hide_index = True, num_rows = "dynamic") # st.write(extra_clients) with c2: st.write("## Existing Clients (via ObsPy)") st.write(orig_clients)
[docs] def reset_config(self): self.settings = reset_config() save_filter(self.settings) st.success("Settings have been reset to default.")
[docs] def render_license(self): st.text( """ CSIRO Open Source Software License Agreement (variation of the BSD/MIT License) Copyright (c) 2013, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230. All rights reserved. CSIRO is willing to grant you a license to this software product on the following terms, except where otherwise indicated for third party material. Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of CSIRO nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of CSIRO. EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS". CSIRO AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS, WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL CSIRO OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION FOR BREACH OF CONTRACT, NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER LIABILITY HOWSOEVER INCURRED. WITHOUT LIMITING THE SCOPE OF THE PREVIOUS SENTENCE THE EXCLUSION OF LIABILITY SHALL INCLUDE: LOSS OF PRODUCTION OR OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN CONNECTION WITH THIS LICENCE, THE USE OF THE SOFTWARE OR THE USE OF OR OTHER DEALINGS WITH THE SOFTWARE, EVEN IF CSIRO OR ITS CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS, DAMAGES OR OTHER LIABILITY. APPLICABLE LEGISLATION SUCH AS THE AUSTRALIAN CONSUMER LAW MAY IMPLY REPRESENTATIONS, WARRANTIES, OR CONDITIONS, OR IMPOSES OBLIGATIONS OR LIABILITY ON CSIRO OR ONE OF ITS CONTRIBUTORS IN RESPECT OF THE SOFTWARE THAT CANNOT BE WHOLLY OR PARTLY EXCLUDED, RESTRICTED OR MODIFIED "CONSUMER GUARANTEES". IF SUCH CONSUMER GUARANTEES APPLY THEN THE LIABILITY OF CSIRO AND ITS CONTRIBUTORS IS LIMITED, TO THE FULL EXTENT PERMITTED BY THE APPLICABLE LEGISLATION. WHERE THE APPLICABLE LEGISLATION PERMITS THE FOLLOWING REMEDIES TO BE PROVIDED FOR BREACH OF THE CONSUMER GUARANTEES THEN, AT ITS OPTION, CSIRO'S LIABILITY IS LIMITED TO ANY ONE OR MORE OF THEM: 1. THE REPLACEMENT OF THE SOFTWARE, THE SUPPLY OF EQUIVALENT SOFTWARE, OR SUPPLYING RELEVANT SERVICES AGAIN; 2. THE REPAIR OF THE SOFTWARE; 3. THE PAYMENT OF THE COST OF REPLACING THE SOFTWARE, OF ACQUIRING EQUIVALENT SOFTWARE, HAVING THE RELEVANT SERVICES SUPPLIED AGAIN, OR HAVING THE SOFTWARE REPAIRED. """ )
[docs] def render(self): c1, c2, c3 = st.columns([1,1,1]) with c1: st.write("# Settings") with c2: st.text("") st.text("") button_col1, button_col2 = st.columns([1, 1]) with button_col1: if st.button("Save Config"): try: self.reset_is_new_cred_added() save_filter(self.settings) df_copy = deepcopy(self.df_clients) df_copy = df_copy.rename(columns={"Client Name": 'client', "Url": 'url'}) self.settings.client_url_mapping.save(df_copy.to_dict('records')) with c3: st.text("") st.success("Config is successfully saved.") except Exception as e: with c3: st.text("") st.error(f"An error occured. Make sure there is no null value in the table.") st.error(e) with button_col2: st.button("Reset Settings", on_click=self.reset_config) with c3: st.text("") st.text("") st.link_button("Help", f"{DOC_BASE_URL}/app_settings.html") tab1, tab2, tab3, tab4 = st.tabs(["🛠️ Data", "🔑 Credentials", "📡 Clients", "📜 License"]) with tab1: self.render_db() with tab2: self.render_auth() with tab3: self.render_clients() with tab4: self.render_license()