Skip to content

Commit

Permalink
Refine interface tools around structured streamlit keys and URL params
Browse files Browse the repository at this point in the history
  • Loading branch information
ejohb committed Feb 18, 2025
1 parent 08f3a02 commit af9dced
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 9 deletions.
89 changes: 81 additions & 8 deletions fmtr/tools/interface_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@
from fmtr.tools.path_tools import Path


def material(name):
"""
Get Material Design icon markdown
"""
return f":material/{name}:"


def color(name, text):
"""
Get markdown coloured text
"""
return f":{name}[{text}]"


class Interface(Base):
"""
Expand All @@ -17,19 +35,24 @@ class Interface(Base):

PATH: ClassVar = __file__
LAYOUT: ClassVar = 'centered'
NAME: ClassVar = None

parent: Base = None
st: ClassVar = st

@classmethod
def get_name(cls):
return cls.NAME or cls.__name__

def set_title(self):
"""
Set page title and layout when root interface
"""

self.st.set_page_config(page_title=self.NAME, layout=self.LAYOUT)
self.st.title(self.NAME)
self.st.set_page_config(page_title=self.get_name(), layout=self.LAYOUT)
self.st.title(self.get_name())

def render(self):
"""
Expand All @@ -45,10 +68,13 @@ def get_key(self, seg=None):
Get a structure-friendly unique ID
"""

suffix = f'{self.__class__.__name__}({self.get_key_self()})'

if self.parent is None:
base = Path()
base = Path(suffix)
else:
base = self.parent.get_key() / str(id(self))
base = self.parent.get_key() / suffix

if seg:
path = base / seg
Expand All @@ -57,13 +83,57 @@ def get_key(self, seg=None):

return path

def get_url_data(self):
"""
Get URL params data pertaining to the current object
"""

if self.parent is None:
data = {}
else:
data = self.parent.get_url_data()

url_self = self.get_url_self()

if url_self:
data |= {self.__class__.__name__.lower(): url_self}

return data

def get_url_self(self):
"""
Get URL params ID pertaining to the current object
"""
return str(id(self))

def get_key_self(self):
"""
Get a streamlit key pertaining to the current object
"""
return str(id(self))

def get_url(self):
"""
Get URL string suffix pertaining to the current object
"""
import urllib
return urllib.parse.urlencode(self.get_url_data())

def to_tabs(self, *classes):
"""
Add tabs from a list of interface classes
"""
tab_names = [cls.NAME for cls in classes]
tab_names = [cls.get_name() for cls in classes]
tabs = st.tabs(tab_names)

for cls, tab in zip(classes, tabs):
Expand All @@ -84,10 +154,11 @@ def is_streamlit(cls):
def get_state(cls):
"""
Initialise this Interface and keep cached
Initialise this Interface and keep cached. This needs to be a cached_resource to avoid serialisation/copying.
This is global, so session handling needs to happen downstream.
"""
msg = f'Initialising State "{cls.NAME}"...'
msg = f'Initialising State "{cls.get_name()}"...'
logger.info(msg)
self = cls()
return self
Expand All @@ -101,10 +172,11 @@ def launch(cls):
"""
if cls.is_streamlit():
self = cls.get_state()
logger.debug(f'Rendering Interface "{self.NAME}" with state: {st.session_state}...')
logger.debug(f'Rendering Interface "{self.get_name()}" with state: {st.session_state}...')
self.set_title()
self.render()
else:
logger.info(f'Launching Streamlit interface "{cls.get_name()}"...')
from streamlit.web import bootstrap
bootstrap.run(cls.PATH, False, [], {})

Expand All @@ -130,3 +202,4 @@ def render(self):

if __name__ == '__main__':
InterfaceTest.launch()

2 changes: 1 addition & 1 deletion fmtr/tools/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.13
1.0.14

0 comments on commit af9dced

Please sign in to comment.