euler314's picture
Update app.py
7f71c49 verified
raw
history blame
4.12 kB
"""
Streamlit File Extension Renamer
--------------------------------
Lightweight Streamlit app for Hugging Face Spaces.
Updates (2025‑05‑22):
* Ensures Streamlit has a writable config dir (`STREAMLIT_HOME`) inside container.
* Sets a fallback `HOME` env so `~/.streamlit` resolves safely.
* Compatible with Streamlit >=1.45.1 (bug‑fixed event‑loop).
"""
from __future__ import annotations
import os
import pathlib
import io
import zipfile
from datetime import datetime
from pathlib import Path
# ---------------------------------------------------------------------
# Environment hardening (MUST run before `import streamlit`)
# ---------------------------------------------------------------------
os.environ.setdefault("STREAMLIT_HOME", "/tmp/.streamlit")
os.environ.setdefault("HOME", "/tmp")
pathlib.Path(os.environ["STREAMLIT_HOME"]).mkdir(parents=True, exist_ok=True)
import streamlit as st
# ---------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------
ALLOWED_TARGET_EXTS: list[str] = [
".txt", ".pdf", ".doc", ".docx", ".json", ".csv", ".xml", ".html",
".css", ".js", ".md", ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff",
".svg", ".ico", ".mp3", ".wav", ".mp4", ".avi", ".mkv", ".mov",
".zip", ".tar", ".gz", ".7z",
]
DISALLOWED_SOURCE_EXTS: set[str] = {".exe", ".bin"}
# ---------------------------------------------------------------------
# UI helpers
# ---------------------------------------------------------------------
def make_sidebar() -> str:
st.sidebar.header("Settings")
target_ext = st.sidebar.selectbox(
"Target extension (applied to **all** uploaded files)",
options=ALLOWED_TARGET_EXTS,
index=ALLOWED_TARGET_EXTS.index(".pdf"),
)
st.sidebar.markdown(
"❗ **Note**: This tool only renames file extensions. It does **not** "
"convert the underlying format."
)
return target_ext
def make_uploader():
return st.file_uploader(
"Upload one or more files",
accept_multiple_files=True,
type=[ext.lstrip(".") for ext in ALLOWED_TARGET_EXTS],
help="Drag‑and‑drop or browse for files to rename.",
)
# ---------------------------------------------------------------------
# Core logic
# ---------------------------------------------------------------------
def write_zip(uploaded_files: list[st.runtime.uploaded_file_manager.UploadedFile],
target_ext: str) -> io.BytesIO:
buffer = io.BytesIO()
with zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) as zf:
for file in uploaded_files:
orig_path = Path(file.name)
if orig_path.suffix.lower() in DISALLOWED_SOURCE_EXTS:
st.warning(f"⏭️ Skipping disallowed file: **{orig_path.name}**")
continue
renamed = orig_path.with_suffix(target_ext)
zf.writestr(renamed.name, file.read())
st.success(f"✅ Renamed **{orig_path.name}** → **{renamed.name}**")
buffer.seek(0)
return buffer
# ---------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------
def main() -> None:
st.set_page_config("Extension Renamer", page_icon="📄", layout="centered")
st.title("📄 Universal File‑Extension Renamer")
st.write("Upload files, choose a new extension, and download them renamed "
"in a ZIP archive.")
target_ext = make_sidebar()
uploaded_files = make_uploader()
if uploaded_files and st.button("🔄 Rename & Package"):
zip_buffer = write_zip(uploaded_files, target_ext)
timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
st.download_button(
label="⬇️ Download ZIP",
data=zip_buffer,
file_name=f"renamed_{timestamp}.zip",
mime="application/zip",
)
st.caption("© 2025 File‑Extension Renamer • Streamlit • Hugging Face Spaces")
if __name__ == "__main__":
main()