File size: 4,168 Bytes
a81bd64
36e2c9e
a81bd64
 
 
 
36e2c9e
 
 
a81bd64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36e2c9e
 
 
a81bd64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d93cdad
 
a81bd64
 
 
 
 
 
 
 
36e2c9e
a81bd64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d93cdad
a81bd64
 
 
36e2c9e
 
d93cdad
36e2c9e
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
141
142
143
import os
import uuid
import tempfile
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
import gradio as gr


# ---------------------------
# Configuration (no hardcodes)
# ---------------------------
@dataclass
class Config:
    # App texts
    TITLE: str
    INSTRUCTIONS_MD: str
    LABEL_COUNT: str
    LABEL_OUTPUT: str
    LABEL_GENERATE_BTN: str
    LABEL_DOWNLOAD_BTN: str

    # Behavior and limits
    DEFAULT_COUNT: int
    MIN_UUIDS: int
    MAX_UUIDS: int

    # UI layout
    TEXTBOX_LINES: int
    BUTTON_VARIANT: str  # e.g., "primary" | "secondary"

    # File output
    OUTPUT_DIR: str      # if empty, uses temp dir
    FILENAME_PREFIX: str
    TIME_FORMAT: str     # strftime format, e.g. "%Y%m%d_%H%M%S"
    FILE_EXTENSION: str  # e.g., ".txt"


def getenv_int(key: str, default: int) -> int:
    """Safely parse an int from environment variables with a default."""
    try:
        return int(os.getenv(key, str(default)))
    except Exception:
        return default


CFG = Config(
    # Texts
    TITLE=os.getenv("APP_TITLE", "UUID Generator"),
    INSTRUCTIONS_MD=os.getenv(
        "APP_INSTRUCTIONS_MD",
        "Enter how many UUIDs you want and click **Generate**.",
    ),
    LABEL_COUNT=os.getenv("LABEL_COUNT", "How many UUIDs?"),
    LABEL_OUTPUT=os.getenv("LABEL_OUTPUT", "UUIDs (one per line)"),
    LABEL_GENERATE_BTN=os.getenv("LABEL_GENERATE_BTN", "Generate"),
    LABEL_DOWNLOAD_BTN=os.getenv("LABEL_DOWNLOAD_BTN", "Download as .txt"),

    # Behavior and limits
    DEFAULT_COUNT=getenv_int("DEFAULT_COUNT", 10),
    MIN_UUIDS=getenv_int("MIN_UUIDS", 1),
    MAX_UUIDS=getenv_int("MAX_UUIDS", 1000),

    # UI layout
    TEXTBOX_LINES=getenv_int("TEXTBOX_LINES", 16),
    BUTTON_VARIANT=os.getenv("BUTTON_VARIANT", "primary"),

    # File output
    OUTPUT_DIR=os.getenv("OUTPUT_DIR", ""),  # "" -> tempdir
    FILENAME_PREFIX=os.getenv("FILENAME_PREFIX", "uuids"),
    TIME_FORMAT=os.getenv("TIME_FORMAT", "%Y%m%d_%H%M%S"),
    FILE_EXTENSION=os.getenv("FILE_EXTENSION", ".txt"),
)


# ---------------------------
# Core logic
# ---------------------------
def _resolve_output_dir() -> Path:
    """Pick output directory from config or fall back to a temporary directory."""
    if CFG.OUTPUT_DIR.strip():
        p = Path(CFG.OUTPUT_DIR).expanduser().resolve()
        p.mkdir(parents=True, exist_ok=True)
        return p
    # HF Spaces-friendly temp dir
    return Path(tempfile.gettempdir())


def generate_uuids_and_file(count: int):
    """Generate UUIDs (one per line) and create a downloadable file path."""
    # Parse and clamp
    try:
        n = int(count)
    except Exception:
        n = CFG.DEFAULT_COUNT
    n = max(CFG.MIN_UUIDS, min(n, CFG.MAX_UUIDS))

    # Build newline-separated UUIDs
    text = "\n".join(str(uuid.uuid4()) for _ in range(n))

    # Prepare file path
    ts = datetime.utcnow().strftime(CFG.TIME_FORMAT)
    fname = f"{CFG.FILENAME_PREFIX}_{n}_{ts}{CFG.FILE_EXTENSION}"
    outdir = _resolve_output_dir()
    fpath = outdir / fname

    # Write to file
    fpath.write_text(text, encoding="utf-8")

    # IMPORTANT: use gr.update(...) instead of DownloadButton.update(...)
    return text, gr.update(value=str(fpath), visible=True)


# ---------------------------
# Gradio UI
# ---------------------------
with gr.Blocks(title=CFG.TITLE) as demo:
    gr.Markdown(f"# {CFG.TITLE}\n{CFG.INSTRUCTIONS_MD}")

    with gr.Row():
        num = gr.Number(
            value=CFG.DEFAULT_COUNT,
            precision=0,
            minimum=CFG.MIN_UUIDS,
            maximum=CFG.MAX_UUIDS,
            label=CFG.LABEL_COUNT,
        )
        btn = gr.Button(CFG.LABEL_GENERATE_BTN, variant=CFG.BUTTON_VARIANT)

    out = gr.Textbox(
        label=CFG.LABEL_OUTPUT,
        lines=CFG.TEXTBOX_LINES,
        show_copy_button=True,
    )

    # Initially hidden; becomes visible with a valid file path
    dbtn = gr.DownloadButton(CFG.LABEL_DOWNLOAD_BTN, visible=False)

    btn.click(generate_uuids_and_file, inputs=num, outputs=[out, dbtn])

if __name__ == "__main__":
    # Tip: on HF Spaces, set share=True if you want a public link
    demo.launch()