File size: 4,402 Bytes
8f54b3b
028d45f
 
 
 
8f54b3b
f6b050d
1765a9a
8f54b3b
77577b3
 
8f54b3b
028d45f
 
 
ddf8f02
028d45f
ddf8f02
 
 
 
028d45f
ddf8f02
028d45f
5a8848f
ddf8f02
028d45f
ddf8f02
 
028d45f
ddf8f02
 
028d45f
 
 
ddf8f02
 
028d45f
 
 
ddf8f02
 
028d45f
ddf8f02
028d45f
 
 
 
 
 
 
ddf8f02
 
028d45f
 
 
 
 
ddf8f02
028d45f
 
 
 
 
 
ddf8f02
 
 
028d45f
 
 
ddf8f02
 
 
 
 
 
 
 
 
 
028d45f
ddf8f02
028d45f
 
ddf8f02
028d45f
ddf8f02
 
 
 
 
 
 
 
028d45f
 
 
 
ddf8f02
 
 
028d45f
 
 
398bff1
 
 
84bd340
72dcbca
18700aa
8aaa6f4
84bd340
398bff1
18700aa
398bff1
8f54b3b
8d24883
8f54b3b
 
77577b3
7145c54
 
 
 
8f54b3b
 
1765a9a
 
 
 
 
 
398bff1
7145c54
1765a9a
 
7e04af3
5a8848f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import os
import secrets
from urllib.parse import urlencode
import requests

import streamlit as st
from src.inner.main import run
from src.inner.paths import MARKDOWN_OUTPUT_FILE, PLOT_OUTPUT_FILE

st.title("Query2Plot Demo")
st.write("This is a demo for the Query2Plot application.")



# OAUTH Logic Begin
OAUTH_CLIENT_ID     = os.getenv("OAUTH_CLIENT_ID")
OAUTH_CLIENT_SECRET = os.getenv("OAUTH_CLIENT_SECRET")
SPACE_HOST          = os.getenv("SPACE_HOST")
REDIRECT_URI        = f"https://{SPACE_HOST}"          # must match exactly
AUTH_URL            = "https://huggingface.co/oauth/authorize"
TOKEN_URL           = "https://huggingface.co/oauth/token"
OPENID_PROVIDER_URL = os.getenv("OPENID_PROVIDER_URL", "https://huggingface.co")
SCOPES              = os.getenv("OAUTH_SCOPES", "openid profile")


def oauth_login_url(state: str) -> str:
    query = urlencode({
        "client_id":     OAUTH_CLIENT_ID,
        "redirect_uri":  REDIRECT_URI,
        "response_type": "code",
        "scope":         SCOPES,
        "state":         state,
    })
    return f"{AUTH_URL}?{query}"


def exchange_code(code: str) -> dict:
    r = requests.post(
        TOKEN_URL,
        data={
            "grant_type":   "authorization_code",
            "code":         code,
            "redirect_uri": REDIRECT_URI,
            "client_id":    OAUTH_CLIENT_ID,
        },
        auth=(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET),
        timeout=20,
    )
    r.raise_for_status()
    return r.json()


def get_userinfo(access_token: str) -> dict:
    meta = requests.get(
        f"{OPENID_PROVIDER_URL}/.well-known/openid-configuration",
        timeout=20,
    ).json()
    r = requests.get(
        meta["userinfo_endpoint"],
        headers={"Authorization": f"Bearer {access_token}"},
        timeout=20,
    )
    r.raise_for_status()
    return r.json()


# Handle OAUTH Callback
code  = st.query_params.get("code")
state = st.query_params.get("state")

if code and "user" not in st.session_state:
    # NOTE: Because Streamlit resets session_state on redirect, we skip
    # strict state verification here.  If you need it, encode state in the
    # redirect_uri as a path/query param instead.
    try:
        tokens = exchange_code(code)
        user   = get_userinfo(tokens["access_token"])
        st.session_state["tokens"] = tokens
        st.session_state["user"]   = user
    except Exception as e:
        st.error(f"Login failed: {e}")
        st.stop()
    st.query_params.clear()   # remove code/state from URL
    st.rerun()

# Login gate
if "user" not in st.session_state:
    state     = secrets.token_urlsafe(24)
    login_url = oauth_login_url(state)
    # Use target="_blank" so the sign-in page opens in a new tab;
    # this avoids cookie issues when the Space runs inside an iframe.
    st.markdown(
        f'<a href="{login_url}" target="_blank">Sign in with Hugging Face</a>',
        unsafe_allow_html=True,
    )
    st.stop()

st.success(f"Signed in as @{st.session_state['user'].get('preferred_username', 'unknown')}")

# OAUTH Logic End





if "temp_file_path" not in st.session_state: # Ensures temp_file_path is only set once
    st.session_state.temp_file_path = None

uploaded_file = st.file_uploader("Upload a CSV file", type="csv")
if uploaded_file is not None and st.session_state.temp_file_path is None:
    import tempfile
    with tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix=".csv") as temp_file:
        temp_file.write(uploaded_file.getvalue())
        st.session_state.temp_file_path = temp_file.name
    
    st.success(f"File uploaded and saved as {st.session_state.temp_file_path}")

#st.write(f"Enter your query below.")
question = st.text_input("Enter your query:")

if st.button("Run Query2Plot"):
    with st.spinner("Running the program..."):
        st.write('\n')

        question = question + f"\nThe file path to use is: {st.session_state.temp_file_path}"
        result = run(question)

    if MARKDOWN_OUTPUT_FILE.exists():
        with MARKDOWN_OUTPUT_FILE.open("r", encoding="utf-8") as f:
            code_and_output = f.read()
            st.markdown(code_and_output)
    else:
        st.error(f"Markdown output file not found at {MARKDOWN_OUTPUT_FILE}")

    # TO DO: Display the generated plot if it exists
    if PLOT_OUTPUT_FILE.exists():
        st.image(str(PLOT_OUTPUT_FILE), caption="Generated Figure")