Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,7 @@ geospatial/streamlit-apps/.streamlit/.DS_Store
.DS_Store
*.toml

*.pyc

.envrc
.direnv
103 changes: 91 additions & 12 deletions samples/streamlit-in-snowflake/sis-deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,44 @@ Often when developing SiS apps, you might want to graduate from the Snowsight UI
- Install the right dependencies
- Test and deploy your SiS apps from the command line

If you have issues with this example, feel free to open an issue, talk to your SE, or email me at [email protected]. You can find full documentation for the snowcli [here](https://github.com/Snowflake-Labs/snowcli) and specific documentation for the snowcli and SiS [here](https://docs.snowflake.com/LIMITEDACCESS/snowcli/streamlit-apps/overview).
If you have issues with this example, feel free to open an issue, talk to your SE, or email me at [email protected] or [email protected]. You can find full documentation for the snowcli [here](https://github.com/Snowflake-Labs/snowcli) and specific documentation for the snowcli and SiS [here](https://docs.snowflake.com/LIMITEDACCESS/snowcli-v2/streamlit-apps/).

# Install snowcli

```sh
pip install snowflake-cli-labs==2.0.0
```

# Download this folder

You can either download the files individually, clone this repo in git, or download the whole folder
by pasting this page's url in https://download-directory.github.io

NOTE: you can get a similar setup by simply doing
```
snow streamlit create my_app_name
```

Here's a brief summary of the files in the repo

├── .streamlit
│ └── secrets.toml # This is where your credentials go for testing your app locally
├── common
│ ├── get_data.py # Some functions for loading the sample data from Snowflake
│ └── utils.py # Some general utilty methods
├── environment.yml # Defines the python packages your app will use
├── event_data.csv # Some sample data
├── pages
│ └── users.py # An example page
├── snowflake.yml # Specifies your app's name and files for snowcli
└── streamlit_app.py # An example home page

Once you've downloaded the folder, unzip it if necessary and go into it.

# Secrets

Create your Streamlit secrets file (.streamlit/secrets.toml) and fill it out with the information below.
Edit the file called `.streamlit/secrets.toml` information below (
everything in <BRACKETS> should be filled in with your specific info):

```toml
[connections.snowflake]
Expand All @@ -22,10 +55,16 @@ schema = "<SCHEMA>"
warehouse = "<WAREHOUSE>"
```

Edit your global Snowflake config file (~/.snowflake/config.toml) with the information below.
Now add the same info to the global Snowflake config file (~/.snowflake/config.toml) by running
```sh
snow connection add --connection-name default
```
and putting in the same account, username, etc. as you put in your secrets.toml.

You can look at `~/.snowflake/config.toml` and you should see an entry that looks like this.

```toml
[connections.dev]
[connections.default]
account = "<ACCOUNT>"
user = "<USERNAME>"
authenticator = "externalbrowser"
Expand All @@ -37,28 +76,68 @@ warehouse = "<WAREHOUSE>"

# Set up local environment

Because streamlit-in-snowflake uses conda to install and packages, it's best to install
conda locally and use that. These are defined in environment.yml

```yml
name: sf_env
channels:
- snowflake
dependencies:
- python=3.8.12 # The latest python available in snowflake as of 2024-02-12
- streamlit=1.26.0 # The latest streamlit available in snowflake as of 2024-02-12

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so streamlit is 1.22 in SiS for most customers right now, we should be going into a public preview next week so I think this is fine

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good catch. Should I update the comment to reflect the date, or is this fine as-is?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah it is fine as is I think

- snowflake-snowpark-python
- plotly
```

If you want to use other packages, just check that they're available on the Snowflake
anaconda channel https://repo.anaconda.com/pkgs/snowflake/, and if they're on there,
they should work fine.

You can then install conda locally and create a conda environment from this file

```sh
pip install snowflake-cli-labs==1.2.1
brew install miniconda
conda env update
conda activate sis-deploy
conda activate sf_env
```

# Generate data
# Update files

`python generate_data.py`
Update `snowflake.yml` to have the name and warehouse you want to use

You need to upload this data to a table in Snowflake, feel free to upload in the Snowsight UI [here](https://docs.snowflake.com/en/user-guide/data-load-web-ui).
```yml
definition_version: 1
streamlit:
name: streamlit_app
query_warehouse: my_streamlit_warehouse # Note that an XS warehouse is recommended
main_file: streamlit_app.py
env_file: environment.yml
pages_dir: pages/
additional_source_files:
- common/*.py
```

# Upload data

There is a file called `event_data.csv`, which you can download and then upload into a table in Snowflake.
You can do this by by uploading it through the Snowsight UI [here](https://docs.snowflake.com/en/user-guide/data-load-web-ui).

Once you have uploaded the file, update `TABLE_NAME` in `common/get_data.py` to the
full location of the table.

# Test locally

To test and debug the app locally, run:

```sh
streamlit run app.py
streamlit run streamlit_app.py
```

# Deployment

To deploy the app to Snowflake, run:

```sh
snow streamlit deploy MY_APP --replace --query-warehouse=MY_WAREHOUSE
snow stage put "*.py" DATABASE.SCHEMA.streamlit/MY_APP --overwrite
snow streamlit deploy --open
```
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
import snowflake.snowpark as sp
import streamlit as st
from snowflake.snowpark.functions import col, date_trunc
from utils import (
get_pandas_df,
get_table,
)
from common.utils import get_pandas_df, get_table

TABLE_NAME = "NIVIS_DEMO.RAW4.RAW_EVENTS"
TABLE_NAME = "STREAMLIT.TASK_TABLES.RAW_EVENTS"


def get_events() -> sp.DataFrame:
Expand All @@ -22,7 +19,7 @@ def get_events() -> sp.DataFrame:

dates = col1.date_input(
"Select date range",
[date(2021, 6, 1), date(2021, 12, 29)],
value=[date(2021, 6, 1), date(2021, 12, 29)],
min_value=date(2021, 1, 1),
max_value=date(2021, 12, 29),
key="date_range",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import re
import time
from contextlib import contextmanager
from datetime import date
from functools import reduce
from typing import Mapping, cast

Expand Down Expand Up @@ -242,76 +241,6 @@ def format_sql_from_df(df: DataFrame, use_header: bool = True) -> str:
return header + format_sql(str(df._plan.queries[0].sql))


@st.cache_data

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this way better without

def get_download_link(_session: Session, df: pd.DataFrame, filename: str) -> str:
"""
Get download link for a dataframe.
Before this works, you need to create a stage using this command:
```
CREATE OR REPLACE STAGE {temp_stage}
ENCRYPTION = (TYPE = 'SNOWFLAKE_SSE')
FILE_FORMAT = (TYPE = CSV, COMPRESSION = NONE)
```
"""
temp_stage = "TEMP_STAGE_DOWNLOAD"

db = _session.get_current_database()
schema = _session.get_current_schema()
full_temp_stage = f"@{db}.{schema}.{temp_stage}"
snowpark_df = _session.create_dataframe(df)

snowpark_df.write.copy_into_location(
f"{full_temp_stage}/{filename}",
header=True,
overwrite=True,
single=True,
)

res = _session.sql(
f"select get_presigned_url({full_temp_stage}, '{filename}', 3600) as url"
).collect()
url = res[0]["URL"]

return f"[Download data 📥]({url})"


def sis_download_button(
data: pd.DataFrame, filename: str | None = None, key: str | None = None
) -> None:
"""
Adds a button to download a dataframe as a CSV file.
This is a workaround for st.download_button while it is not supported in SiS.
It uses Snowpark's get_presigned_url function to generate a link!
Args:
data (pd.DataFrame): Data to be downloaded
filename (str, optional): Filename. Defaults to None.
key (str, optional): Key of the streamlit button. Defaults to None.
"""

data_hash = hashlib.sha256(pd.util.hash_pandas_object(data).values).hexdigest()

if filename is None:
filename = f"{data_hash}_{date.today()}.csv"

if key is None:
key = f"{data_hash}_{filename}"

if st.button("Get link to download CSV", key=key):
if data.empty:
st.error("No data")
else:
st.info(
"""
Right click on the link below and select 'open in new tab' to download the
data.
"""
)
session = SnowparkConnection().connect()
st.write(get_download_link(session, data, filename))


@contextmanager
def tile_ctx(
df: sp.DataFrame | pd.DataFrame,
Expand Down Expand Up @@ -380,9 +309,12 @@ def tile_ctx(
pd.util.hash_pandas_object(data).values
).hexdigest()

sis_download_button(
data=data,
key=f"{description}_{data_hash}",
st.download_button(
"Download data as csv",
data.to_csv(index=False),
"data.csv",
mime="text/csv",
key=data_hash,
)

# When dataframe is a Snowpark dataframe, the SQL query is not explicitly passed
Expand All @@ -407,7 +339,7 @@ def tile_ctx(
def tile(
df: sp.DataFrame | pd.DataFrame,
description: str,
chart: alt.Chart | Figure | alt.LayerChart | None = None,
chart: alt.Chart | alt.LayerChart | Figure | None = None,
sql: str | None = None,
skip_chart: bool = False,
) -> None:
Expand Down
13 changes: 6 additions & 7 deletions samples/streamlit-in-snowflake/sis-deploy/environment.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
name: sis-deploy
name: sf_env
channels:
- snowflake
- snowflake
dependencies:
- python=3.8.12
- streamlit=1.22.0
- snowflake-snowpark-python
- plotly=5.9.0
- sqlparse
- python=3.8.12
- streamlit=1.26.0
- snowflake-snowpark-python
- plotly
Loading