GithubHelp home page GithubHelp logo

st_pages's Introduction

Streamlit-Pages

Releases Build Status Python Versions Streamlit versions License Ruff

Streamlit App

Author: @blackary

Code: https://github.com/blackary/st_pages

Installation

pip install st-pages

See it in action

Basic example: https://st-pages.streamlit.app/

Example with sections: https://st-pages-sections.streamlit.app/

Why st-pages?

Previously, st-pages allowed for a much more customizable and flexible declaration of pages in a Streamlit app, and was independent of the actual filenames of the python files in your project.

As of 1.0.0, st-pages is now a tiny wrapper that provides an easy method for defining the pages in your app in a toml file, as well as a few utility methods to let you add the current page's title to all pages, etc.

You are welcome to continue to use older versions of this package, but most of the old use-cases are now easy to do with native streamlit, so I would recommend checking out the documentation for more information.

How to use

Declare pages inside of a toml file

Contents of .streamlit/pages.toml

[[pages]]
path = "page1.py"
name = "Home"
icon = "๐Ÿ "

[[pages]]
path = "other_pages/page2.py"
name = "Page 2"
icon = ":books:"
url_path = "my_books" # You can override the default url path for a page

Example with sections, .stremalit/pages_sections.toml:

[[pages]]
path = "page1.py"
name = "Home"
icon = "๐Ÿ "

[[pages]]
path = "other_pages/page2.py"
name = "Page 2"
icon = ":books:"

[[pages]]
name = "My section"
icon = "๐ŸŽˆ๏ธ"
is_section = true

# Pages after an `is_section = true` will be indented
[[pages]]
name = "Another page"
icon = "๐Ÿ’ช"

Streamlit code:

import streamlit as st
from st_pages import add_page_title, get_nav_from_toml

st.set_page_config(layout="wide")

# If you want to use the no-sections version, this
# defaults to looking in .streamlit/pages.toml, so you can
# just call `get_nav_from_toml()`
nav = get_nav_from_toml(".streamlit/pages_sections.toml")

st.logo("logo.png")

pg = st.navigation(nav)

add_page_title(pg)

pg.run()

Hiding pages

You can now pass a list of page names to hide_pages to hide pages from now on.

This list of pages is custom to each viewer of the app, so you can hide pages from one viewer but not from another using this method. You can see another example of hiding pages in the docs here

from st_pages import hide_pages

hide_pages(["Another page"])

st_pages's People

Contributors

a-recknagel avatar blackary avatar marcjulianschwarz avatar mfriedy avatar pre-commit-ci[bot] avatar sairam90 avatar shariqmalik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

st_pages's Issues

Data uploading problem in postgre sql table.

I have one folder where continuous raw files are generated and my program takes these files from that folder reads it and uploads it into postgre sql and then moves into another folder but when i click on stop button files are moved into another folder. In postgre sql table is created but there is no data in table.
What I want is when i click on stop button iteration should be stopped and data should be uploaded into postgre sql table.
i am using below code for this. If there is any solution it would be great help.
This file i am getting error
code.zip

Hot loading was broken

After change code, it was not re-loading to take effect and have to stop streamlit server and re-start.
Checked on streamlit v1.28

page_config params

Hey @blackary ,

please pass at least **kwargs so that for example the layout-mode e.g. layout="wide" would be passed .
Otherwise, i get an error, that the set_layout_config only can be set once .

Best regards
Chris

Several Issues

Note: I am using the page_switch() module at the same time.

I am getting an error often (not always) that results in the page loading twice due to an exception. The exception is shown below.
This happens when using the pages menu in the sidebar. Click back and forth to the various pages repeatedly. cause exceptions. Clicking a subpage will result in the error below, which starts in the current home page called Site_Select.

Traceback (most recent call last):
File "/Users/jack/miniconda3/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 541, in _run_script
exec(code, module.dict)
File "/Users/jack/jmautogpt/masterpro.ai.dashboard/ultimate-flask-front-end-2.1/steamlitapp/pages/2_dashboard.py", line 5, in
import Site_Select
File "/Users/jack/jmautogpt/masterpro.ai.dashboard/ultimate-flask-front-end-2.1/steamlitapp/Site_Select.py", line 9, in
show_pages_from_config(".streamlit/pages.toml")
File "/Users/jack/miniconda3/lib/python3.9/site-packages/streamlit/runtime/metrics_util.py", line 367, in wrapped_func
result = non_optional_func(*args, **kwargs)
File "/Users/jack/miniconda3/lib/python3.9/site-packages/st_pages/init.py", line 295, in _show_pages_from_config
show_pages(pages)
File "/Users/jack/miniconda3/lib/python3.9/site-packages/streamlit/runtime/metrics_util.py", line 367, in wrapped_func
result = non_optional_func(*args, **kwargs)
File "/Users/jack/miniconda3/lib/python3.9/site-packages/st_pages/init.py", line 233, in _show_pages
first_page_hash = list(current_pages.keys())[0]
IndexError: list index out of range

If I restart the application and click back and forth between the Home page (Site_Select) and the first subpage I can get this error pop up Cannot read properties of undefined (reading 'pageScriptHash')

There are bugs in this module that take work to find. I can move back and forth from page to page and eventually get the error above. This is a popup error message, and the command line has no stack trace.

Thanks - Jack

Deprecation warning st.experimental_singleton

I am getting the following warning when starting my streamlit app.

st.experimental_singleton is deprecated. Please use the new command st.cache_resource instead, which has the same behavior. More information [in our docs](https://docs.streamlit.io/library/advanced-features/caching).

I think it stems from this line.

I would guess the decorator should be replaced with st.cache_resource according to the link in the warning.

Thanks for creating this library. It gives a much more pythonic feel when developing multipage streamlit apps ๐Ÿ™Œ

Streamlit 1.24.1 scrambling page order

Possibly related: #46

I am too facing the problem with combination of latest st_pages and streamlit 1.24.1.

In my case the order of pages is scrambled for whatever reason.

For now I just experimentally figured out that 0.4.1 and 1.24.0 combo seem to work.

As far as I get, the problem is along these lines:

def _show_pages(pages: list[Page]):
    current_pages: dict[str, dict[str, str | bool]] = get_pages("")  # type: ignore
    if set(current_pages.keys()) == set(p.page_hash for p in pages):
        return

In the latest version streamlit.source_util.get_pages("") seem to return unordered list of pages, and I suspect this is what causes the problem.

URL parsing

I noticed that URLs were parsed differently compared to the default way. In your example, the "Example Five" page has the URL "/Example%20Five" and I think it would be better if it was "/Example_Five" instead if it is possible for you.
Thanks for the package btw, very useful!

Could you provide the emoji.json in the folder rather than request url

Its so hard to use st_pages as i cant connect to the url(https://raw.githubusercontent.com/omnidan/node-emoji/master/lib/emoji.json):

ConnectionError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /omnidan/node-emoji/master/lib/emoji.json (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7fce29de7af0>: Failed to establish a new connection: [Errno 111] Connection refused'))

Make the emoji.json file to a config file will be really helpful.

Data uploading problem in postgresql using python script.

I have one folder where continuous raw files are generated and my program takes these files from that folder reads it and uploads it into postgre sql and then moves into another folder but when i click on stop button files are moved into another folder. In postgre sql table is created but there is no data in table.
What I want is when i click on stop button iteration should be stopped and data should be uploaded into postgre sql table.
i am using below code for this. If there is any solution it would be great help.

Import Module

from tkinter import *
import tkinter as tk
import tkinter.font as font
import os
import psycopg2
import numpy as np
import pandas as pd
import glob
from Enter_Details_ver2 import *
from tkinter.filedialog import askdirectory
from tkinter import filedialog
import shutil
import time
from PIL import ImageTk, Image
from tkinter import messagebox, ttk
from tkinter.ttk import Combobox
import psycopg2.extras as extras
from New_table import *
from tkinter import *
import tkinter as tk
from time import sleep
import schedule
from urllib.parse import quote_plus
from datetime import datetime
import IMCtermite
import json
import datetime
import io
from io import StringIO

root=Tk()
root.configure(bg='#BFBFBF')

setting the windows size

root.geometry("765x550")

setting the title of window

root.title("UPLOADING STATUS")

path = source()
dest_path = destination()

New file dictionary

newfilesDictionary = {}

hostname= host()
dbname=DB()
portID= Port_ID()
username=user()
password=pw()
filetype = fileType()
list_data_ = []
postgres_str = f'postgresql://{username}:%s@{hostname}:{portID}/{dbname}' % quote_plus(password)
print(postgres_str)

conn_string = "host=%s dbname=%s user=%s password=%s port=%s" % (hostname, dbname, username, password,portID)
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()

event = None
disconnect_flag = False

cnx = create_engine(postgres_str)

table= table_name()

def add_trigger_time(trigger_time, add_time) :
trgts = datetime.datetime.strptime(trigger_time,'%Y-%m-%dT%H:%M:%S')
dt = datetime.timedelta(seconds=add_time)
return (trgts + dt).strftime('%Y-%m-%dT%H:%M:%S')

def create_table():

if (filetype == ".csv"):
    files=os.path.join(path + "/**/", "*.csv")
    files = glob.glob(files)
    if any(".csv" in s for s in files):
        df = pd.concat(map(pd.read_csv,files),ignore_index=True)
        df.columns = [x.replace(" ", "_").replace("-","_").replace(r"/","_").replace("\\","_").replace(".","_")
                      .replace("$","_").replace("%","_").replace(":","_").replace("!","_").replace("@","_")
                      .replace("^","_").replace("&","_").replace(";","_").replace("*","_").replace("#","_")
                      for x in df.columns]
        df.columns = df.columns.str.lower()
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"{} :Appending to table: {}\n".format(dtime, table))
        df.to_sql(table, con=cnx, index=False)
        print("Done")
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Files inserted successfully\n" %dtime)

        for roote, dirs, files_ in os.walk(path):
            for dire in dirs:
                try:
                    shutil.move(path + "/"+ dire, dest_path)
                except Exception as e:
                    print(e)
                    pass

        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Files moved to destination folder successfully\n" %dtime)
        root.after(30000, start_append)
        
    else:
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Execution Completed: No more csv files to cocatenate" %dtime)
        tk.messagebox.showinfo("Completed","Execution Completed: No more csv files to cocatenate")
        start['state'] = tk.DISABLED

elif (filetype == ".xlsx"):
    files=os.path.join(path + "/**/", "*.xls")
    files = glob.glob(files)
    if any(".xls" in s for s in files):
        df = pd.concat(map(pd.read_excel,files),ignore_index=True)
        df.columns = [x.replace(" ", "_").replace("-","_").replace(r"/","_").replace("\\","_").replace(".","_")
                      .replace("$","_").replace("%","_").replace(":","_").replace("!","_").replace("@","_")
                      .replace("^","_").replace("&","_").replace(";","_").replace("*","_").replace("#","_")
                      for x in df.columns]
        df.columns = df.columns.str.lower()
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"{} :Appending to table: {}\n".format(dtime, table))
        df.to_sql(table, con=cnx, index=False)
        print("Done")
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Files inserted successfully\n" %dtime)

        for roote, dirs, files_ in os.walk(path):
            for dire in dirs:
                try:
                    shutil.move(path + "/"+ dire, dest_path)
                except Exception as e:
                    print(e)
                    pass


        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Files moved to destination folder successfully\n" %dtime)
        root.after(30000, start_append)
    else:
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Execution Completed: No more excel files to cocatenate" %dtime)
        tk.messagebox.showinfo("Completed","Execution Completed: No more excel files to cocatenate")
        start['state'] = tk.DISABLED

elif (filetype == ".raw"):
    files=os.path.join(path + "/**/", "*.raw")
    files = glob.glob(files)

print(files)

latest_file = max(files, key = os.path.getctime)

print(latest_file)

files.remove(latest_file)

print(files)

    if any(".raw" in s for s in files):
        for file in files:
            try:
                os.rename(file,file)
            except PermissionError as e:
                print(e)
                files.remove(file)

            imcraw = IMCtermite.imctermite(file.encode('utf-8'))
            #channels = imcraw.get_channels(False) 
            chns = imcraw.get_channels(True)
            xcol = "Datetime"
            xsts = [add_trigger_time(chns[0]['trigger-time'],tm) for tm in chns[0]['xdata']]
            chnnms = sorted([chn['name'] for chn in chns], reverse=False)
            chnsdict = {}
            for chn in chns :
                chnsdict[chn["name"]] = chn
            df = pd.DataFrame()
            df[xcol] = pd.Series(xsts)
            for chnnm in chnnms :
                chn = chnsdict[chnnm]
                ycol = chn['yname']+" ["+chn['yunit']+"]"
                df[ycol] = pd.Series(chn['ydata'])
                df.columns = [x.replace(" ", "_").replace("-","_").replace(r"/","_").replace("\\","_").replace(".","_")
                              .replace("$","_").replace("%","_").replace(":","_").replace("!","_").replace("@","_")
                              .replace("^","_").replace("&","_").replace(";","_").replace("*","_").replace("#","_").replace("[","_")
                              .replace("]","_" ).replace("(", "_").replace(")", "_").replace('"',"") for x in df.columns]
                df.columns = df.columns.str.lower()
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"{} :Appending to table: {}\n".format(dtime, table))
        try:
            df.to_sql(table, con=cnx, index=False)
            cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE TEXT USING CAST(datetime AS TEXT);"%table)
            conn.commit()
            query = "select * from %s" %table
            
            print(query)
        except ValueError as e:
            tk.messagebox.showerror("Error","Table name: %s already exists in the database. Please change the name of the table." %table)
            
        #cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE TEXT USING CAST(datetime AS TEXT);"%table)
        #conn.commit()
        #cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE timestamp USING to_timestamp(datetime, 'YYYY-MM-DD T HH24:MI:SS');" %table)
        #conn.commit()
        print("Uploaded the files: Done")
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Files inserted successfully\n" %dtime)

        for roote, dirs, files_ in os.walk(path):
            for dire in dirs:
                try:
                    t = os.path.getctime(path + "/" + dire)
                    c_time = time.ctime(t)
                    t_obj = time.strptime(c_time)
                    T_stamp = time.strftime("%Y-%m-%d-%H-%M-%S", t_obj)
                    os.rename(path + "/" + dire, path + "/" +  T_stamp)
                    shutil.move(path + "/"+ T_stamp, dest_path)
                except Exception as e:
                    print(e)
                    #root.after(500, start_append)
                    

        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Files moved to destination folder successfully\n" %dtime)
        
        root.after(30000, start_append)
                
    else:
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        #cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE TEXT USING CAST(datetime AS TEXT);"%table)
        #cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE timestamp USING to_timestamp(datetime, 'YYYY-MM-DD T HH24:MI:SS');" %table)
        #conn.commit()
        Connection_status.insert(tk.END,"%s :Execution Completed: No more raw files to cocatenate" %dtime)
        tk.messagebox.showinfo("Completed","Execution Completed: No more raw files to cocatenate")
        start['state'] = tk.DISABLED

def start_append():

if (filetype == ".csv"):
    files=os.path.join(path + "/**/", "*.csv")
    files = glob.glob(files)
    if any(".csv" in s for s in files):
        df = pd.concat(map(pd.read_csv,files),ignore_index=True)
        df.columns = [x.replace(" ", "_").replace("-","_").replace(r"/","_").replace("\\","_").replace(".","_")
                      .replace("$","_").replace("%","_").replace(":","_").replace("!","_").replace("@","_")
                      .replace("^","_").replace("&","_").replace(";","_").replace("*","_").replace("#","_")
                      for x in df.columns]
        df.columns = df.columns.str.lower()
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"{} :Appending to table: {}\n".format(dtime, table))
        tuples = [tuple(x) for x in df.to_numpy()]
        cols = ','.join(list(df.columns))
        query="INSERT INTO %s(%s) VALUES %%s" % (table, cols)
        try:
            extras.execute_values(cursor, query, tuples)
            conn.commit()
        except (Exception, psycopg2.DatabaseError) as error:
            print("Error: %s" % error)
            tk.messagebox.showerror("Error","ERROR: %s" %error)
            conn.rollback() 
        else:
            dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            Connection_status.insert(tk.END,"%s :Files inserted successfully\n" %dtime)
            for roote, dirs, files_ in os.walk(path):
                for dire in dirs:
                    try:
                        shutil.move(path + "/"+ dire, dest_path)
                    except Exception as e:
                        print(e)
                        pass

           
            dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            Connection_status.insert(tk.END,"%s :Files shifted to destination folder successfully\n" %dtime)
            

        root.after(30000, start_append)


        
    else:
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Execution Completed: No more csv files to cocatenate" %dtime)
        tk.messagebox.showinfo("Completed","Execution Completed: No more csv files to cocatenate")
        start['state'] = tk.DISABLED
        
        
elif (filetype == ".xlsx"):
    files=os.path.join(path + "/**/", "*.xls")
    files = glob.glob(files)
    if any(".xls" in s for s in files):
        df = pd.concat(map(pd.read_excel,files),ignore_index=True)
        df.columns = [x.replace(" ", "_").replace("-","_").replace(r"/","_").replace("\\","_").replace(".","_")
                      .replace("$","_").replace("%","_").replace(":","_").replace("!","_").replace("@","_")
                      .replace("^","_").replace("&","_").replace(";","_").replace("*","_").replace("#","_")
                      .replace('"',"")
                      for x in df.columns]
        df.columns = df.columns.str.lower()
     
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"{} :Appending to table: {}\n".format(dtime, table))
        tuples = [tuple(x) for x in df.to_numpy()]
        cols = ','.join(list(df.columns))
        query="INSERT INTO %s(%s) VALUES %%s" % (table, cols)
        try:
            extras.execute_values(cursor, query, tuples)
            conn.commit()
        except (Exception, psycopg2.DatabaseError) as error:
            print("Error: %s" % error)
            tk.messagebox.showerror("Error","ERROR: %s" %error)
            conn.rollback() 
        else:
            dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            Connection_status.insert(tk.END,"%s :Files inserted successfully\n" %dtime)
            for roote, dirs, files_ in os.walk(path):
                for dire in dirs:
                    try:
                        shutil.move(path + "/"+ dire, dest_path)
                    except Exception as e:
                        print(e)
                        pass

           
            dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            Connection_status.insert(tk.END,"%s :Files shifted to destination folder successfully\n" %dtime)        

        root.after(30000, start_append)

    else:
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"%s :Execution Completed: No more excel files to cocatenate" %dtime)
        tk.messagebox.showinfo("Completed","Execution Completed: No more excel files to cocatenate")
        start['state'] = tk.DISABLED

elif (filetype == ".raw"):
    files=os.path.join(path + "/**/", "*.raw")
    files = glob.glob(files)

print(files)

latest_file = max(files, key = os.path.getctime)

print(latest_file)

files.remove(latest_file)

print(files)

    if any(".raw" in s for s in files):
        for file in files:
            try:
                os.rename(file,file)
            except PermissionError as e:
                print(e)
                files.remove(file)

            
            imcraw = IMCtermite.imctermite(file.encode('utf-8'))
            #channels = imcraw.get_channels(False) 
            chns = imcraw.get_channels(True)
            xcol = "Datetime"
            xsts = [add_trigger_time(chns[0]['trigger-time'],tm) for tm in chns[0]['xdata']]
            chnnms = sorted([chn['name'] for chn in chns], reverse=False)
            chnsdict = {}
            for chn in chns :
                chnsdict[chn["name"]] = chn
            df = pd.DataFrame()
            df[xcol] = pd.Series(xsts)
            for chnnm in chnnms :
                chn = chnsdict[chnnm]
                ycol = chn['yname']+" ["+chn['yunit']+"]"
                df[ycol] = pd.Series(chn['ydata'])
                df.columns = [x.replace(" ", "_").replace("-","_").replace(r"/","_").replace("\\","_").replace(".","_")
                              .replace("$","_").replace("%","_").replace(":","_").replace("!","_").replace("@","_")
                              .replace("^","_").replace("&","_").replace(";","_").replace("*","_").replace("#","_").replace("[","_")
                              .replace("]","_" ).replace("(", "_").replace(")", "_")
                              .replace('"',"") for x in df.columns]
                df.columns = df.columns.str.lower()
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        Connection_status.insert(tk.END,"{} :Appending to table: {}\n".format(dtime, table))
        tuples = [tuple(x) for x in df.to_numpy()]
        cols = ','.join(list(df.columns))
        query="INSERT INTO %s(%s) VALUES %%s" % (table, cols)
        conn.set_session(autocommit=True)
        try:
            extras.execute_values(cursor, query, tuples)
            conn.commit()
        except (Exception, psycopg2.DatabaseError) as error:
            print("Error: %s" % error)
            tk.messagebox.showerror("Error","ERROR: %s" %error)
            conn.rollback() 
        else:
            dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            Connection_status.insert(tk.END,"%s :Files inserted successfully\n" %dtime)
            for roote, dirs, files_ in os.walk(path):
                for dire in dirs:
                    try:
                        t = os.path.getctime(path + "/" + dire)
                        c_time = time.ctime(t)
                        t_obj = time.strptime(c_time)
                        T_stamp = time.strftime("%Y-%m-%d-%H-%M-%S", t_obj)
                        os.rename(path + "/" + dire, path + "/" +  T_stamp)
                        shutil.move(path + "/"+ T_stamp, dest_path)
                    except Exception as e:
                        print(e)
                        #root.after(500, start_append)
                        

           
            dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            Connection_status.insert(tk.END,"%s :Files shifted to destination folder successfully\n" %dtime)
            

        if disconnect_flag == False:
            root.after(30000, start_append)
        else:
            dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE TEXT USING CAST(datetime AS TEXT);"%table)

            cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE timestamp USING to_timestamp(datetime, 'YYYY-MM-DD T HH24:MI:SS');" %table)
            conn.commit()
            Connection_status.insert(tk.END,"%s :Execution Completed: No more raw files to cocatenate" %dtime)
            tk.messagebox.showinfo("Completed","Execution Completed: No more raw files to cocatenate")
            ##start['state'] = tk.DISABLED

            

        #root.after(30000, start_append)   


    else:
        dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE TEXT USING CAST(datetime AS TEXT);"%table)

        cursor.execute("ALTER TABLE %s ALTER COLUMN datetime TYPE timestamp USING to_timestamp(datetime, 'YYYY-MM-DD T HH24:MI:SS');" %table)
        conn.commit()
        Connection_status.insert(tk.END,"%s :Execution Completed: No more raw files to cocatenate" %dtime)
        tk.messagebox.showinfo("Completed","Execution Completed: No more raw files to cocatenate")
        ##start['state'] = tk.DISABLED

def disconnect():
global disconnect_flag

confirm=tk.messagebox.askquestion("Confirmation","Are you sure you want to disconnect")
if confirm == 'yes' :
    disconnect_flag = True
    dtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    Connection_status.insert(tk.END,"%s :Connection disconnected" %dtime)

else:
    root.after(50000, start_append)

def go_back():
#root.destroy()
import ask_table_creation

Connection_status = Text(root, height = 18, width = 70,bg='#EEECE1')

Conn_label = Label(root, text = "Uploading Status", bg='#BFBFBF')

Connection_status.grid(row=2, column=1, pady=10, ipadx='10', ipady='10')
Conn_label.grid(row=1,column=1, ipadx="10",pady='10',ipady="10",padx='5')

start = Button(
root,
text='Start',
bg = '#17375E',
fg = 'White',
command = create_table
)
start.grid(row=0, column=1, pady=10, ipadx='20', ipady='10', sticky='W')

disconn = Button(
root,
text='STOP',
bg = '#17375E',
fg = 'White',
command = disconnect
)
disconn.grid(row=3, column=2, pady=10, ipadx='20', ipady='10', sticky='W')

back = Button(
root,
text='BACK',
bg = '#17375E',
fg = 'White',
command = go_back
)

back.grid(row=3, column=0, pady=10, ipadx='20', ipady='10', sticky='SE')

IGNORE

Drawback Observed

  • Currently, the documentation is a huge streamlit application with multiple pages to showcase each feature. Although, it sounds great from a proof of work perspective but has issues from a practical stand point
  • Firstly, on slower connections or times when many people are attempting to access the documentation, it takes almost a minute or so to load completely
  • Search Option is not available
  • Not SEO friendly. Most people who want to integrate X -> have to go and ask on the streamlit forum about the feature -> Then learn about streamlit-extras rather than it being the first search result
  • Need more elaborate tutorials for certain components to help beginners

Proposal

  • Dedicated Documenation Website
  • branch docs
  • Use mkdocs-material to ensure all the instructions are in markdown
  • Auto Deploy using Vercel

Conflict with set_page_config method

While trying to set my layout as wide with set_page_config(layout='wide'), I get the error StreamlitAPIException: 'set_page_config()' can only be called once per app, and must be called as the first Streamlit command in your script. because it seems like set_page_config() is probably called on any of the imports from st_pages import Page, Section, show_pages, hide_pages

Font Controllable.

The font is too small and we hope st_pages will add controllable parameters.

st.header() anchor links do not work

Hi. I just noticed that the #anchor links included with, say, st.header() do not work on st-pages pages. Instead one just gets redirected to the root/main page.

I double checked and anchor links in regular Streamlit pages/foo do work. So, I believe the issue is specific to st-pages.

Allow dynamic showing/hiding

I decided to hold off on this, because it's a trickier problem than just setting up which pages are visible from a static list. But, this would be a killer feature.

Readme Typo

I'm not sure if you prefer an Issue or a pull request for something so trivial, but the second code snippet in the readme file is missing Section in the import statement.

from st_pages import Page, show_pages, add_page_title

add_page_title() # By default this also adds indentation

# Specify what pages should be shown in the sidebar, and what their titles and icons
# should be
show_pages(
    [
        Page("streamlit_app.py", "Home", "๐Ÿ "),
        Page("other_pages/page2.py", "Page 2", ":books:"),
        Section("My section", icon="๐ŸŽˆ๏ธ"),
        # Pages after a section will be indented
        Page("Another page", icon="๐Ÿ’ช"),
    ]
)

should have

from st_pages import Page, Section, show_pages, add_page_title

Do not work for Streamlit 1.2.7 version

I tried the code in Streamlit 1.2.7, but the section function does not work: The section becomes clickable, the content is the same as the home page, and the location of pages under the section at the sidebar is the same as pages out of the section

Allow Python 3.7

Please update the dependencies to allow Python 3.7, I can't see anything in the code that isn't compatible?

First run shows an error

Not much of an issue as it's fixed for future runs for all users, but can be a big issue in a lambda-style environment. This was reported on the forum.

Section Pages aren't indented

Love the library so cool, but noticed a tiny issue.

If I create sections and don't call add_page_title() on the page, the sections don't indent.

show_pages(
    [
        Page("app.py", "Home", "๐Ÿ "),
        Section(name="My section", icon="๐ŸŽˆ๏ธ"),
        Page("pages/1_test.py", "test1 ", ":shark:", in_section=True),
        Page("pages/2_boom.py", "bang", "๐Ÿ’ฅ", in_section=True),
    ]
)
add_page_title()

Unless I add that last line, everything is left aligned.

I've recreated this on Chrome and Safari.

Support top tab menu

Hi,

I am developing an application using streamlit and after using this package my code is a lot cleaner. Thank you for that. I have a suggestion, with a side menu, can we also provide an option for the top menu? Like names of the pages appearing on the top with icons.
Thank you

BR,
Ikram

mypy compatibility: add a py.typed file.

Hi there. Liking your package so far. ๐Ÿ˜ธ

I noticed that you do use type hints in your code, but you are missing a py.typed file in the root of your package so that mypy can recognize that you use type hints.

Since mypy is the reference type checker for Python, being compatible with it would be a good thing.

Actually, py.typed seems part of PEP-0561 so that is even more universal than just mypy.

Anyway, hope this helps. Thanks.

Streamlit 1.23.1 breaking rerun on changes for pages

After upgrading to 1.23.1 of Streamlit, all of a sudden any pages do not capture changes when rerunning after saving.

In some cases it notifies that the file has changed, but rerunning the page does not reflect the updated report.

Simple replication:

  • install st_pages 0.4.1 and streamlit 1.22.0 for an app with 1 subpage
  • confirm that changing subpage (e.g. st.write) updates when changed
  • update to streamlit 1.23.1
  • the subpage now no longer will update

Not sure where this bug actually lies. But given a "normal" streamlit multipage app seems OK, is it something how st_pages registers the pages?

Same script for multiple pages

It would be useful to allow the same script to be used as the file for multiple pages.
This can be enabled by adding the page name during the MD5 hash computation.

The following script can then be used to determine which page reference is being requested:

from streamlit.runtime.scriptrunner import get_script_run_ctx
from streamlit.source_util import get_pages


def get_current_page():
    pages = get_pages("")
    ctx = get_script_run_ctx()
    if ctx is not None:
        try:
            return pages[ctx.page_script_hash]
        except KeyError:
            pass

    return None

st_pages deployment on streamlit cloud not working

I have been working on my app (two pages) here https://github.com/gloriamacia/pixarstar/blob/main/genai/.streamlit/pages.toml

This was my pages.toml

[[pages]]
path = "streamlit_app.py"
name = "Home"
icon = "๐ŸŽจ"

[[pages]]
path = "pages/stability_ai_app.py"
name = "Draw"
icon = "๐Ÿ–ผ๏ธ"

When I deployed, I specified as my entry point of the app genai/streamlit_app.py. I am getting this error:
https://pixarstar.streamlit.app/stability_ai_app

image

I tried changing pages.toml to

[[pages]]
path = "genai/streamlit_app.py"
name = "Home"
icon = "๐ŸŽจ"

[[pages]]
path = "genai/pages/stability_ai_app.py"
name = "Draw"
icon = "๐Ÿ–ผ๏ธ"

It still does not work. What I do not understand is that on the local development running the first version with poetry run python -m streamlit run streamlit_app.py was working just fine.

What am I missing here? Maybe the deployment instructions should be improved because it does not look obvious to me.
Thanks a lot in advance.

Bad message format Cannot read properties of undefined (reading 'pageScriptHash')

When I am interacting with a page (therefore causing reruns) and the icons for the pages are appearing normally (there's times that they don't appear) I sometimes get the message on streamlit:

Bad message format
Cannot read properties of undefined (reading 'pageScriptHash')

It will also sometimes if I am not in the main page redirect you to a page http://localhost:8501/undefined that doesn't exist. If i enter that url in the browser it gives "page not found".
if you keep interacting with this ghost page it will go back to the real one eventually. But in these changes back and forth from the ghost page all the session_state is lost which is pretty annoying and makes the app unusable.

The bug though disappears if I use version st-pages==0.4.1 and I think it's related to the component st_aggrid because only when I have an AgGrid that the ghost page and session state delete occurs. For the other pages it's only the message Bad message format Cannot read properties of undefined (reading 'pageScriptHash')

This is related to this post I made in the streamlit forums:
https://discuss.streamlit.io/t/using-aggrid-sometimes-changes-the-page-to-undefined-reseting-the-session-state/50090

Sections don't indent and clicking section names returns to main.py

Hi I am having an issue where I cant seem to get the sections to indent and in app these section names can be clicked on just like page titles. Doing so returns the user back to the main app. I have updates to version 0.3.5 and the issue remains. Any ideas what might be causing this behaviour?

can't hide pages

I have created a functionality for login register and logout, the basic logic to not show pages until login or register but i can still see pages in side bar.
here is the code:

import streamlit as st
import get_database
import bcrypt
from st_pages import Page, show_pages, hide_pages

dbname = get_database()
users = dbname["users"]
is_logged_in = False

def register(username, email, password):
    # Hash the password
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    # Check if the username already exists in the users collection
    existing_user = users.find_one({"username": username})
    if existing_user:
        return False
    else:
        # Insert user data into the users collection
        users.insert_one({
            "username": username,
            "email": email,
            "password": hashed_password.decode()
        })
        return True

def login(username, password):
    # Check if the user exists in the users collection
    user = users.find_one({"username": username})
    if user:
        # Compare the entered password with the hashed password stored in the database
        if bcrypt.checkpw(password.encode('utf-8'), user["password"].encode('utf-8')):
            return True
    return False

def login_page():
    global is_logged_in
    if not is_logged_in:
        username = st.text_input("Username")
        email = st.text_input("Email")
        password = st.text_input("Password", type='password')
        if st.button("Login"):
            if login(username, password):
                is_logged_in = True
                st.success("Logged in!")
            else:
                st.error("Invalid username or password")
        if st.button("Register"):
            if register(username, email, password):
                is_logged_in = True
                st.success("User registered!")
            else:
                st.error("Username already exists")

    if is_logged_in:
        # Show the logout button when the user is logged in
        if st.button("Logout"):
            is_logged_in = False
            st.success("Logged out!")


def show_pages_logged_in():
    return show_pages([[Page("hello.py", "page1l", ":books:"),
                Page("pages/page1.py", "page1l", ":books:"),
                Page("pages/page2.py", "page2", ":books:"),
                Page("pages/page3.py", "page3", ":books:")])

def hide_pages_logged_out():
    return hide_pages([Page("hello.py", "page1l", ":books:"),
                  Page("pages/page1.py", "page1l", ":books:"),
                Page("pages/page2.py", "page2", ":books:"),
                Page("pages/page3.py", "page3", ":books:")])


def main():
    login_page()
    if is_logged_in:
        show_pages_logged_in()
    else:
        hide_pages_logged_out()

if __name__ == "__main__":
    main()

Sections not working correctly

Hey Guys,
I experienced a problem with the sections, with my personal project as well as with your examples. They get displayed as normal pages and when i click on them, i get redirected to the page above. I used both methods to create sections and the results were the same.

I am using streamlit 1.25.0 and st-pages 0.4.3

Thanks in advance!

Sections Not working as expected

Hello,

I am trying to instantiate sections in my streamlit app, but It behaves as a Page.
I can click on the Section without any link or app behind, and I do not have the hierarchy of Sections - Pages I expected.

Remove numpy dependency specification

Would it be possible to remove numpy from pyproject.toml?
I'm trying to use this library but I cannot install this library with poetry because I have numba v0.55.2, and numba requires numpy<1.23 while st_pages requires numpy>=1.23.4.

And from the src folder, it doesn't look like numpy is needed as an upfront dependency.
Thanks

Suggestion: Make sections have a 'start' and an 'end'

I would quite like the ability to have pages not in sections, after a section, i.e.

Page 1
Page 2
Section
- Page 3
- Page 4
Page 5

I don't believe you can do this because you can't 'end' sections at present, correct?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.