Dannyar608 commited on
Commit
e581856
·
verified ·
1 Parent(s): 647dadd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -16
app.py CHANGED
@@ -21,6 +21,17 @@ def sanitize_input(text: str) -> str:
21
  """Sanitize user input to prevent XSS and injection attacks."""
22
  return html.escape(text.strip())
23
 
 
 
 
 
 
 
 
 
 
 
 
24
  def validate_age(age: Union[int, float, str]) -> int:
25
  """Validate and convert age input."""
26
  try:
@@ -36,12 +47,13 @@ def validate_file(file_obj) -> None:
36
  if not file_obj:
37
  raise gr.Error("No file uploaded")
38
 
39
- if not any(file_obj.name.endswith(ext) for ext in ALLOWED_FILE_TYPES):
40
- raise gr.Error(f"Only {', '.join(ALLOWED_FILE_TYPES)} files are allowed")
 
41
 
42
  file_size = os.path.getsize(file_obj.name) / (1024 * 1024) # MB
43
  if file_size > MAX_FILE_SIZE_MB:
44
- raise gr.Error(f"File size must be less than {MAX_FILE_SIZE_MB}MB")
45
 
46
  # ========== TRANSCRIPT PARSING ==========
47
  def extract_gpa(text: str, gpa_type: str) -> str:
@@ -116,6 +128,9 @@ def extract_courses_from_table(text: str) -> Dict[str, List[Dict]]:
116
  def parse_transcript(file_obj) -> Tuple[str, Optional[Dict]]:
117
  """Parse transcript file with robust error handling."""
118
  try:
 
 
 
119
  validate_file(file_obj)
120
 
121
  text = ''
@@ -335,7 +350,7 @@ learning_style_quiz = LearningStyleQuiz()
335
  class ProfileManager:
336
  def __init__(self):
337
  self.profiles_dir = Path(PROFILES_DIR)
338
- self.profiles_dir.mkdir(exist_ok=True)
339
 
340
  def save_profile(self, name: str, age: Union[int, str], interests: str,
341
  transcript: Dict, learning_style: str,
@@ -345,10 +360,7 @@ class ProfileManager:
345
  """Save student profile with validation."""
346
  try:
347
  # Validate required fields
348
- if not name.strip():
349
- raise gr.Error("Name is required")
350
-
351
- name = sanitize_input(name)
352
  age = validate_age(age)
353
  interests = sanitize_input(interests)
354
 
@@ -840,11 +852,11 @@ def create_interface():
840
  )
841
 
842
  quiz_submit.click(
843
- fn=lambda *answers: learning_style_quiz.evaluate_quiz(answers),
844
  inputs=quiz_components,
845
  outputs=learning_output
846
  ).then(
847
- fn=lambda: gr.update(visible=True),
848
  outputs=learning_output
849
  )
850
 
@@ -907,6 +919,7 @@ def create_interface():
907
  visible=bool(profile_manager.list_profiles())
908
  )
909
  load_btn = gr.Button("Load Profile", visible=bool(profile_manager.list_profiles()))
 
910
 
911
  with gr.Column(scale=2):
912
  output_summary = gr.Markdown(
@@ -929,6 +942,16 @@ def create_interface():
929
  inputs=load_profile_dropdown,
930
  outputs=output_summary
931
  )
 
 
 
 
 
 
 
 
 
 
932
 
933
  # ===== TAB 5: AI Teaching Assistant =====
934
  with gr.Tab("AI Assistant", id=4) as tab5:
@@ -949,27 +972,27 @@ def create_interface():
949
 
950
  # Tab navigation logic
951
  def navigate_to_tab(tab_index: int):
952
- return {tabs: gr.update(selected=tab_index)}
953
 
954
  step1.click(
955
  fn=lambda: navigate_to_tab(0),
956
- outputs={tabs: tabs}
957
  )
958
  step2.click(
959
  fn=lambda: navigate_to_tab(1),
960
- outputs={tabs: tabs}
961
  )
962
  step3.click(
963
  fn=lambda: navigate_to_tab(2),
964
- outputs={tabs: tabs}
965
  )
966
  step4.click(
967
  fn=lambda: navigate_to_tab(3),
968
- outputs={tabs: tabs}
969
  )
970
  step5.click(
971
  fn=lambda: navigate_to_tab(4),
972
- outputs={tabs: tabs}
973
  )
974
 
975
  return app
 
21
  """Sanitize user input to prevent XSS and injection attacks."""
22
  return html.escape(text.strip())
23
 
24
+ def validate_name(name: str) -> str:
25
+ """Validate name input."""
26
+ name = name.strip()
27
+ if not name:
28
+ raise gr.Error("Name cannot be empty")
29
+ if len(name) > 100:
30
+ raise gr.Error("Name is too long (max 100 characters)")
31
+ if any(c.isdigit() for c in name):
32
+ raise gr.Error("Name cannot contain numbers")
33
+ return name
34
+
35
  def validate_age(age: Union[int, float, str]) -> int:
36
  """Validate and convert age input."""
37
  try:
 
47
  if not file_obj:
48
  raise gr.Error("No file uploaded")
49
 
50
+ file_ext = os.path.splitext(file_obj.name)[1].lower()
51
+ if file_ext not in ALLOWED_FILE_TYPES:
52
+ raise gr.Error(f"Invalid file type. Allowed: {', '.join(ALLOWED_FILE_TYPES)}")
53
 
54
  file_size = os.path.getsize(file_obj.name) / (1024 * 1024) # MB
55
  if file_size > MAX_FILE_SIZE_MB:
56
+ raise gr.Error(f"File too large. Max size: {MAX_FILE_SIZE_MB}MB")
57
 
58
  # ========== TRANSCRIPT PARSING ==========
59
  def extract_gpa(text: str, gpa_type: str) -> str:
 
128
  def parse_transcript(file_obj) -> Tuple[str, Optional[Dict]]:
129
  """Parse transcript file with robust error handling."""
130
  try:
131
+ if not file_obj:
132
+ raise gr.Error("Please upload a file first")
133
+
134
  validate_file(file_obj)
135
 
136
  text = ''
 
350
  class ProfileManager:
351
  def __init__(self):
352
  self.profiles_dir = Path(PROFILES_DIR)
353
+ self.profiles_dir.mkdir(exist_ok=True, parents=True)
354
 
355
  def save_profile(self, name: str, age: Union[int, str], interests: str,
356
  transcript: Dict, learning_style: str,
 
360
  """Save student profile with validation."""
361
  try:
362
  # Validate required fields
363
+ name = validate_name(name)
 
 
 
364
  age = validate_age(age)
365
  interests = sanitize_input(interests)
366
 
 
852
  )
853
 
854
  quiz_submit.click(
855
+ fn=lambda *answers: learning_style_quiz.evaluate_quiz(*answers),
856
  inputs=quiz_components,
857
  outputs=learning_output
858
  ).then(
859
+ fn=lambda: gr.Markdown(visible=True),
860
  outputs=learning_output
861
  )
862
 
 
919
  visible=bool(profile_manager.list_profiles())
920
  )
921
  load_btn = gr.Button("Load Profile", visible=bool(profile_manager.list_profiles()))
922
+ clear_btn = gr.Button("Clear Form")
923
 
924
  with gr.Column(scale=2):
925
  output_summary = gr.Markdown(
 
942
  inputs=load_profile_dropdown,
943
  outputs=output_summary
944
  )
945
+
946
+ clear_btn.click(
947
+ fn=lambda: [gr.update(value="") for _ in range(12)],
948
+ outputs=[
949
+ name, age, interests,
950
+ movie, movie_reason, show, show_reason,
951
+ book, book_reason, character, character_reason,
952
+ blog_text
953
+ ]
954
+ )
955
 
956
  # ===== TAB 5: AI Teaching Assistant =====
957
  with gr.Tab("AI Assistant", id=4) as tab5:
 
972
 
973
  # Tab navigation logic
974
  def navigate_to_tab(tab_index: int):
975
+ return gr.Tabs(selected=tab_index)
976
 
977
  step1.click(
978
  fn=lambda: navigate_to_tab(0),
979
+ outputs=tabs
980
  )
981
  step2.click(
982
  fn=lambda: navigate_to_tab(1),
983
+ outputs=tabs
984
  )
985
  step3.click(
986
  fn=lambda: navigate_to_tab(2),
987
+ outputs=tabs
988
  )
989
  step4.click(
990
  fn=lambda: navigate_to_tab(3),
991
+ outputs=tabs
992
  )
993
  step5.click(
994
  fn=lambda: navigate_to_tab(4),
995
+ outputs=tabs
996
  )
997
 
998
  return app