Skip to content

Commit 73021ff

Browse files
committed
Change reader methos to static and file manager utils
1 parent cd4444b commit 73021ff

4 files changed

Lines changed: 131 additions & 39 deletions

File tree

src/app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import gradio as gr
22

33
import tts_page
4+
from utils.file_manager import FileManager as file_manager
45
from utils.translator import translator
56

67
SELECTED_LANGUAGE = "Languages_EN"
@@ -117,4 +118,5 @@ def change_language(language):
117118

118119
lang_code = SELECTED_LANGUAGE.split("_")[1]
119120
translator.set_language(lang_code)
121+
file_manager.ensure_dir("output")
120122
demo.launch()

src/tts_page.py

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
LANGUAGE_CODES_ALIASES_MAP,
66
TOP_LEVEL_DOMAIN_ALIASES_MAP,
77
)
8-
from utils.reader import reader
8+
from utils.reader import PDFReader as reader
99
from utils.translator import translator
1010

11+
SELECTED_ACCENT = "TTS_English_United_States"
12+
1113
input_text_component = None
1214
convert_btn_component = None
1315
audio_output_component = None
@@ -18,8 +20,6 @@
1820

1921
pdf_selected = True
2022

21-
SELECTED_ACCENT = "TTS_English_United_States"
22-
2323

2424
def get_selected_language(accent):
2525
"""
@@ -51,8 +51,11 @@ def update_tts_components():
5151
Updates the labels and values of the TTS components when the language changes.
5252
Returns a list of gr.update() objects.
5353
"""
54+
# Initialize the list of updates
5455
updates = []
5556

57+
# If there is a component for raw input text, changes the
58+
# label and placeholder to the translated values
5659
if input_text_component:
5760
updates.append(
5861
gr.update(
@@ -61,12 +64,18 @@ def update_tts_components():
6164
)
6265
)
6366

67+
# If there is a component for the convert button, changes the
68+
# value to the translated button text
6469
if convert_btn_component:
6570
updates.append(gr.update(value=translator.t("TTS_Button")))
6671

72+
# If there is a component for audio output, changes the
73+
# label to the translated audio label
6774
if audio_output_component:
6875
updates.append(gr.update(label=translator.t("Generated_Audio")))
6976

77+
# If there is a component for input type (PDF or text), changes the
78+
# choices and label to the translated values
7079
if input_type_component:
7180
updates.append(
7281
gr.update(
@@ -79,16 +88,22 @@ def update_tts_components():
7988
)
8089
)
8190

91+
# If there is a component for input file (PDF), changes the
92+
# label to the translated PDF input placeholder
8293
if input_file_component:
8394
updates.append(
8495
gr.update(
8596
label=translator.t("TTS_PDF_input_placeholder"),
8697
)
8798
)
8899

100+
# If there is a component for TTS description (it's text), changes the
101+
# value to the translated description
89102
if tts_description:
90103
updates.append(gr.update(value=translator.t("TTS_Description")))
91104

105+
# If there is a component for the language and dialect selection,
106+
# updates the choices and label to the translated values
92107
if language_component:
93108
updates.append(
94109
gr.update(
@@ -116,6 +131,8 @@ def update_tts_components():
116131
)
117132
)
118133

134+
# Return the list of updates to be
135+
# applied to the TTS components
119136
return updates
120137

121138

@@ -132,20 +149,30 @@ def convert_to_audio(text, pdf):
132149
global SELECTED_ACCENT
133150
audio_file = None
134151

152+
# Get the selected language code and domain based on the selected accent
135153
code, domain = get_selected_language(SELECTED_ACCENT)
136154

137155
if pdf_selected:
138-
# Generate audio from PDF
139-
reader.read_pdf(pdf)
140-
tts = gTTS(text=reader.content, lang=code, tld=domain)
156+
# --- Generate audio from PDF ---
157+
# 1. Read the PDF content
158+
content = reader.read_pdf(pdf)
159+
# 2. Use the content from the reader and the
160+
# selected language code and domain
161+
tts = gTTS(text=content, lang=code, tld=domain)
162+
# 3. Save the audio file to the output directory
141163
audio_file = "output/output.mp3"
164+
# 4. Save the audio file
142165
tts.save(audio_file)
143166
else:
144-
# Generate audio from text
167+
# --- Generate audio from text ---
168+
# 1. Use the input text and the selected language code and domain
145169
tts = gTTS(text=text, lang=code, tld=domain)
170+
# 2. Save the audio file to the output directory
146171
audio_file = "output/output.mp3"
172+
# 3. Save the audio file
147173
tts.save(audio_file)
148174

175+
# Return the path to the generated audio file
149176
return audio_file
150177

151178

@@ -171,6 +198,11 @@ def update_visibility(radio):
171198

172199

173200
def create_page():
201+
"""Creates the TTS page with input components, buttons, and audio output.
202+
203+
Returns:
204+
gr.Column: The TTS page layout with all components.
205+
"""
174206
global \
175207
input_text_component, \
176208
convert_btn_component, \
@@ -180,16 +212,25 @@ def create_page():
180212
tts_description, \
181213
language_component
182214

215+
# Create the TTS page using the column layout
183216
with gr.Column() as tts_page:
217+
# Set the description for the TTS page. It explains the functionality of the
218+
# gtts module/library and how it can be used to convert text to speech.
184219
tts_description = gr.Markdown(translator.t("TTS_Description"))
185220

221+
# Row for the input type selection and language selection
186222
with gr.Row():
223+
# Radio button for selecting the input type (PDF or plain text)
224+
# The default value is set to "PDF" input
187225
input_type_component = gr.Radio(
188226
[translator.t("TTS_PDF_input"), translator.t("TTS_Plain_Text_input")],
189227
label=translator.t("TTS_input_type"),
190228
value=translator.t("TTS_PDF_input"),
191229
)
192230

231+
# Dropdown that allows the user to select the language and dialect for TTS
232+
# The choices are based on the available languages and dialects in the gtts library
233+
# The default value is set to "English (United States)"
193234
language_component = gr.Dropdown(
194235
choices=[
195236
translator.t("TTS_English_Australia"),
@@ -215,47 +256,74 @@ def create_page():
215256
interactive=True,
216257
)
217258

218-
language_component.change(
219-
fn=change_accent,
220-
inputs=language_component,
221-
)
222-
259+
# Textbox where the user can input text to be converted to speech.
260+
# This component is initially hidden and will be shown when the user selects
261+
# the "Plain Text" input type.
223262
input_text_component = gr.Textbox(
224263
label=translator.t("TTS_Text_input"),
225264
placeholder=translator.t("TTS_Text_input_placeholder"),
226265
lines=5,
227266
visible=False,
228267
)
229268

269+
# File component where the user can upload a PDF file to be converted to speech.
270+
# This component is initially visible and will be hidden when the user selects
271+
# the "Plain Text" input type.
272+
# When the user selects the "PDF" input type, this component will be shown
273+
# and the user can upload a PDF file to be converted to speech.
230274
input_file_component = gr.File(
231275
label=translator.t("TTS_PDF_input_placeholder"),
232276
file_types=[".pdf"],
233277
visible=True,
234278
file_count="single",
235279
)
236280

281+
# Button that the user clicks to convert the input text or PDF to speech.
237282
convert_btn_component = gr.Button(
238283
value=translator.t("TTS_Button"), variant="primary"
239284
)
240285

286+
# Audio output component that will play the generated audio file.
287+
# This component shows a download button for the generated audio file.
241288
audio_output_component = gr.Audio(
242289
label=translator.t("Generated_Audio"), show_download_button=True
243290
)
244291

292+
# Set the function to update the visibility of the input text and file components
293+
# based on the selected input type (PDF or plain text).
294+
# When the user selects "PDF", the input file component will be shown
295+
# and the input text component will be hidden.
245296
input_type_component.change(
246297
fn=update_visibility,
247298
inputs=input_type_component,
248299
outputs=[input_text_component, input_file_component],
249300
)
250301

302+
# Set the function to convert the input text or PDF to audio when the user clicks
303+
# the convert button. It takes the input text and file as inputs and outputs the
304+
# generated audio file to the audio output component.
251305
convert_btn_component.click(
252306
fn=convert_to_audio,
253307
inputs=[input_text_component, input_file_component],
254308
outputs=audio_output_component,
255309
)
256310

311+
# Set the function to change the accent when the user selects a different accent and
312+
# dialect from the dropdown.
313+
language_component.change(
314+
fn=change_accent,
315+
inputs=language_component,
316+
)
317+
318+
# Return the TTS page layout with all components
257319
return tts_page
258320

259321

260322
def reload_page():
323+
"""Reloads the TTS page components to reflect the current language settings.
324+
325+
Returns:
326+
list: A list of gr.update() objects to update the TTS components.
327+
"""
328+
261329
return update_tts_components()

src/utils/file_manager.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import os
2+
3+
4+
class FileManager:
5+
@staticmethod
6+
def ensure_dir(path: str) -> None:
7+
"""Ensures that a directory exists at the specified path.
8+
If the directory does not exist, it creates it.
9+
10+
Args:
11+
path (str): The path to the directory to ensure.
12+
"""
13+
if not os.path.exists(path):
14+
os.makedirs(path)
15+
16+
@staticmethod
17+
def file_exists(path: str) -> bool:
18+
"""Checks if a file exists at the specified path.
19+
This method returns True if the file exists, otherwise False.
20+
21+
Args:
22+
path (str): The path to the file to check.
23+
24+
Returns:
25+
bool: True if the file exists, False otherwise.
26+
"""
27+
28+
return os.path.isfile(path)
29+
30+
@staticmethod
31+
def dir_exists(path: str) -> bool:
32+
"""Checks if a directory exists at the specified path.
33+
34+
Args:
35+
path (str): _description_
36+
37+
Returns:
38+
bool: _description_
39+
"""
40+
41+
return os.path.isdir(path)

src/utils/reader.py

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,12 @@
33

44

55
class PDFReader:
6-
"""Class for reading PDF files into smaller parts.
7-
6+
"""
87
Provides functionalities to read a PDF file.
9-
10-
Attributes:
11-
input_pdf_path (str): Path to the input PDF file to be read.
128
"""
139

14-
def __init__(self):
15-
self.defaultAttributes()
16-
17-
def defaultAttributes(self):
18-
"""Resets the attributes to their default values.
19-
20-
Sets the initial values for the input PDF path and the content.
21-
"""
22-
self.input_pdf_path = ""
23-
self.content = ""
24-
25-
def check_pdf(self, pdf):
10+
@staticmethod
11+
def check_pdf(pdf):
2612
"""Checks if the provided file is a valid PDF.
2713
2814
Args:
@@ -37,25 +23,20 @@ def check_pdf(self, pdf):
3723
except PyPDF2.errors.PdfReadError:
3824
return False
3925

40-
def read_pdf(self, pdf):
26+
@staticmethod
27+
def read_pdf(pdf: str) -> str:
4128
"""Reads a PDF file and returns a PdfReader object.
4229
4330
Args:
4431
pdf (str): Path to the PDF file to be read.
4532
4633
Returns:
47-
PdfReader: A PdfReader object representing the PDF file.
34+
str: The text content of the PDF file.
4835
"""
4936

50-
if not self.check_pdf(pdf):
37+
if not PDFReader.check_pdf(pdf):
5138
raise ValueError(f"The file {pdf} is not a valid PDF.")
5239

53-
self.input_pdf_path = pdf
5440
reader = PyPDF2.PdfReader(pdf)
5541

56-
self.content = "\n".join([page.extract_text() or "" for page in reader.pages])
57-
58-
return self.content
59-
60-
61-
reader = PDFReader()
42+
return "\n".join([page.extract_text() or "" for page in reader.pages])

0 commit comments

Comments
 (0)