euler314 commited on
Commit
7f71c49
·
verified ·
1 Parent(s): b456e6f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -72
app.py CHANGED
@@ -1,103 +1,75 @@
1
  """
2
  Streamlit File Extension Renamer
3
  --------------------------------
4
- A lightweight Streamlit app intended for deployment on Hugging Face Spaces.
5
- The app lets users upload one or more files and rename (not convert) their
6
- extensions to any common file-type extension the user selects. Executable
7
- and binary files are blocked for security reasons.
8
- """
9
 
 
 
 
 
 
10
  from __future__ import annotations
11
 
12
- import os, pathlib
13
- # 1️⃣ give Streamlit a real home BEFORE importing it
14
- os.environ.setdefault("STREAMLIT_HOME", "/tmp/.streamlit")
15
- pathlib.Path(os.environ["STREAMLIT_HOME"]).mkdir(parents=True, exist_ok=True)
16
-
17
- import streamlit as st
18
-
19
  import zipfile
20
  from datetime import datetime
21
  from pathlib import Path
22
 
 
 
 
 
 
 
23
 
 
24
 
25
- # -----------------------------------------------------------------------------
26
  # Configuration
27
- # -----------------------------------------------------------------------------
28
- # List of target extensions displayed to the user. Extend this list as needed.
29
  ALLOWED_TARGET_EXTS: list[str] = [
30
- ".txt",
31
- ".pdf",
32
- ".doc",
33
- ".docx",
34
- ".json",
35
- ".csv",
36
- ".xml",
37
- ".html",
38
- ".css",
39
- ".js",
40
- ".md",
41
- ".jpg",
42
- ".jpeg",
43
- ".png",
44
- ".gif",
45
- ".bmp",
46
- ".tiff",
47
- ".svg",
48
- ".ico",
49
- ".mp3",
50
- ".wav",
51
- ".mp4",
52
- ".avi",
53
- ".mkv",
54
- ".mov",
55
- ".zip",
56
- ".tar",
57
- ".gz",
58
- ".7z",
59
  ]
60
 
61
- # Source‐file extensions that are disallowed (will be skipped if uploaded).
62
  DISALLOWED_SOURCE_EXTS: set[str] = {".exe", ".bin"}
63
 
64
- # -----------------------------------------------------------------------------
65
  # UI helpers
66
- # -----------------------------------------------------------------------------
67
 
68
  def make_sidebar() -> str:
69
- """Return the user-chosen target extension from sidebar controls."""
70
  st.sidebar.header("Settings")
71
  target_ext = st.sidebar.selectbox(
72
- label="Target extension (applied to **all** uploaded files)",
73
  options=ALLOWED_TARGET_EXTS,
74
  index=ALLOWED_TARGET_EXTS.index(".pdf"),
75
  )
76
-
77
  st.sidebar.markdown(
78
- """❗ **Note**: This tool only renames the file extension. It does **not**
79
- convert the underlying file format. Opening a renamed file with an
80
- incompatible program may fail or lead to data corruption."""
81
  )
82
  return target_ext
83
 
84
 
85
  def make_uploader():
86
- """Return the list of files uploaded by the user."""
87
  return st.file_uploader(
88
  "Upload one or more files",
89
  accept_multiple_files=True,
90
  type=[ext.lstrip(".") for ext in ALLOWED_TARGET_EXTS],
91
- help="Drag-and-drop or browse for files to rename.",
92
  )
93
 
94
-
95
- # -----------------------------------------------------------------------------
96
  # Core logic
97
- # -----------------------------------------------------------------------------
98
 
99
- def write_zip(uploaded_files: list[st.runtime.uploaded_file_manager.UploadedFile], target_ext: str) -> io.BytesIO:
100
- """Return an in-memory ZIP archive of the uploaded files with the new extension."""
101
  buffer = io.BytesIO()
102
  with zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) as zf:
103
  for file in uploaded_files:
@@ -105,25 +77,21 @@ def write_zip(uploaded_files: list[st.runtime.uploaded_file_manager.UploadedFile
105
  if orig_path.suffix.lower() in DISALLOWED_SOURCE_EXTS:
106
  st.warning(f"⏭️ Skipping disallowed file: **{orig_path.name}**")
107
  continue
108
-
109
  renamed = orig_path.with_suffix(target_ext)
110
  zf.writestr(renamed.name, file.read())
111
  st.success(f"✅ Renamed **{orig_path.name}** → **{renamed.name}**")
112
-
113
  buffer.seek(0)
114
  return buffer
115
 
116
-
117
- # -----------------------------------------------------------------------------
118
- # Main app
119
- # -----------------------------------------------------------------------------
120
 
121
  def main() -> None:
122
  st.set_page_config("Extension Renamer", page_icon="📄", layout="centered")
123
- st.title("📄 Universal File-Extension Renamer")
124
- st.write(
125
- "Upload files, choose a new extension, and download them renamed in a single ZIP archive."
126
- )
127
 
128
  target_ext = make_sidebar()
129
  uploaded_files = make_uploader()
@@ -138,8 +106,7 @@ def main() -> None:
138
  mime="application/zip",
139
  )
140
 
141
- st.caption("© 2025 File-Extension Renamer • Built with Streamlit • Deployed on Hugging Face Spaces")
142
-
143
 
144
  if __name__ == "__main__":
145
  main()
 
1
  """
2
  Streamlit File Extension Renamer
3
  --------------------------------
4
+ Lightweight Streamlit app for Hugging Face Spaces.
 
 
 
 
5
 
6
+ Updates (2025‑05‑22):
7
+ * Ensures Streamlit has a writable config dir (`STREAMLIT_HOME`) inside container.
8
+ * Sets a fallback `HOME` env so `~/.streamlit` resolves safely.
9
+ * Compatible with Streamlit >=1.45.1 (bug‑fixed event‑loop).
10
+ """
11
  from __future__ import annotations
12
 
13
+ import os
14
+ import pathlib
15
+ import io
 
 
 
 
16
  import zipfile
17
  from datetime import datetime
18
  from pathlib import Path
19
 
20
+ # ---------------------------------------------------------------------
21
+ # Environment hardening (MUST run before `import streamlit`)
22
+ # ---------------------------------------------------------------------
23
+ os.environ.setdefault("STREAMLIT_HOME", "/tmp/.streamlit")
24
+ os.environ.setdefault("HOME", "/tmp")
25
+ pathlib.Path(os.environ["STREAMLIT_HOME"]).mkdir(parents=True, exist_ok=True)
26
 
27
+ import streamlit as st
28
 
29
+ # ---------------------------------------------------------------------
30
  # Configuration
31
+ # ---------------------------------------------------------------------
 
32
  ALLOWED_TARGET_EXTS: list[str] = [
33
+ ".txt", ".pdf", ".doc", ".docx", ".json", ".csv", ".xml", ".html",
34
+ ".css", ".js", ".md", ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff",
35
+ ".svg", ".ico", ".mp3", ".wav", ".mp4", ".avi", ".mkv", ".mov",
36
+ ".zip", ".tar", ".gz", ".7z",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  ]
38
 
 
39
  DISALLOWED_SOURCE_EXTS: set[str] = {".exe", ".bin"}
40
 
41
+ # ---------------------------------------------------------------------
42
  # UI helpers
43
+ # ---------------------------------------------------------------------
44
 
45
  def make_sidebar() -> str:
 
46
  st.sidebar.header("Settings")
47
  target_ext = st.sidebar.selectbox(
48
+ "Target extension (applied to **all** uploaded files)",
49
  options=ALLOWED_TARGET_EXTS,
50
  index=ALLOWED_TARGET_EXTS.index(".pdf"),
51
  )
 
52
  st.sidebar.markdown(
53
+ "❗ **Note**: This tool only renames file extensions. It does **not** "
54
+ "convert the underlying format."
 
55
  )
56
  return target_ext
57
 
58
 
59
  def make_uploader():
 
60
  return st.file_uploader(
61
  "Upload one or more files",
62
  accept_multiple_files=True,
63
  type=[ext.lstrip(".") for ext in ALLOWED_TARGET_EXTS],
64
+ help="Draganddrop or browse for files to rename.",
65
  )
66
 
67
+ # ---------------------------------------------------------------------
 
68
  # Core logic
69
+ # ---------------------------------------------------------------------
70
 
71
+ def write_zip(uploaded_files: list[st.runtime.uploaded_file_manager.UploadedFile],
72
+ target_ext: str) -> io.BytesIO:
73
  buffer = io.BytesIO()
74
  with zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) as zf:
75
  for file in uploaded_files:
 
77
  if orig_path.suffix.lower() in DISALLOWED_SOURCE_EXTS:
78
  st.warning(f"⏭️ Skipping disallowed file: **{orig_path.name}**")
79
  continue
 
80
  renamed = orig_path.with_suffix(target_ext)
81
  zf.writestr(renamed.name, file.read())
82
  st.success(f"✅ Renamed **{orig_path.name}** → **{renamed.name}**")
 
83
  buffer.seek(0)
84
  return buffer
85
 
86
+ # ---------------------------------------------------------------------
87
+ # Main
88
+ # ---------------------------------------------------------------------
 
89
 
90
  def main() -> None:
91
  st.set_page_config("Extension Renamer", page_icon="📄", layout="centered")
92
+ st.title("📄 Universal FileExtension Renamer")
93
+ st.write("Upload files, choose a new extension, and download them renamed "
94
+ "in a ZIP archive.")
 
95
 
96
  target_ext = make_sidebar()
97
  uploaded_files = make_uploader()
 
106
  mime="application/zip",
107
  )
108
 
109
+ st.caption("© 2025 FileExtension Renamer • Streamlit • Hugging Face Spaces")
 
110
 
111
  if __name__ == "__main__":
112
  main()