harvesthealth commited on
Commit
76906ae
·
verified ·
1 Parent(s): 7a76fea

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +32 -4
  2. verify_slides_logic.py +102 -0
app.py CHANGED
@@ -122,7 +122,15 @@ def setup_mkslides():
122
  # Install dependencies and mkslides
123
  subprocess.run(["pip", "install", "./external/mkslides"])
124
  else:
125
- print("mkslides already present.")
 
 
 
 
 
 
 
 
126
 
127
  setup_mkslides()
128
 
@@ -689,6 +697,16 @@ def get_reports_in_branch(repo_full_name, branch_name, filter_type=None):
689
 
690
  # Method 1: Check user_experience_reports directory
691
  reports = []
 
 
 
 
 
 
 
 
 
 
692
  try:
693
  contents = repo.get_contents("user_experience_reports", ref=branch_name)
694
  for content_file in contents:
@@ -730,6 +748,7 @@ def get_reports_in_branch(repo_full_name, branch_name, filter_type=None):
730
  # Highest priority: specific report.md and slides.md in user_experience_reports
731
  if filter_type == "report" and p_lower == "user_experience_reports/report.md": score -= 1000
732
  if filter_type == "slides" and p_lower == "user_experience_reports/slides.md": score -= 1000
 
733
 
734
  # High priority: other files in user_experience_reports
735
  if "user_experience_reports" in p_lower: score -= 100
@@ -819,7 +838,12 @@ def render_slides(repo_full_name, branch_name, report_path):
819
  # Method 1: Check for multi-file slides folder
820
  # We check this first if the report_path is in user_experience_reports or if it's default
821
  if "user_experience_reports" in report_path:
822
- slides_folder = "user_experience_reports/slides"
 
 
 
 
 
823
  try:
824
  folder_contents = repo.get_contents(slides_folder, ref=branch_name)
825
  if isinstance(folder_contents, list):
@@ -892,8 +916,12 @@ def render_slides(repo_full_name, branch_name, report_path):
892
 
893
  if os.path.exists(f"{output_dir}/index.html"):
894
  # Return IFrame pointing to the generated site.
895
- # We use /file= prefix which Gradio uses to serve files in allowed_paths.
896
- return f'<iframe src="/file={os.path.abspath(output_dir)}/index.html" width="100%" height="600px"></iframe>'
 
 
 
 
897
  else:
898
  return "Failed to render slides."
899
 
 
122
  # Install dependencies and mkslides
123
  subprocess.run(["pip", "install", "./external/mkslides"])
124
  else:
125
+ print("mkslides directory already present. Ensuring it is installed...")
126
+ subprocess.run(["pip", "install", "./external/mkslides"])
127
+
128
+ # Verify installation
129
+ res = subprocess.run(["which", "mkslides"], capture_output=True, text=True)
130
+ if res.returncode == 0:
131
+ print(f"mkslides verified at: {res.stdout.strip()}")
132
+ else:
133
+ print("WARNING: mkslides CLI not found in PATH after installation.")
134
 
135
  setup_mkslides()
136
 
 
697
 
698
  # Method 1: Check user_experience_reports directory
699
  reports = []
700
+
701
+ # Check for merged slides folder first if we are looking for slides
702
+ if filter_type == "slides":
703
+ try:
704
+ repo.get_contents("user_experience_reports/slides", ref=branch_name)
705
+ reports.append("user_experience_reports/slides")
706
+ add_log("Detected 'user_experience_reports/slides' directory. Added as merged presentation option.")
707
+ except:
708
+ pass
709
+
710
  try:
711
  contents = repo.get_contents("user_experience_reports", ref=branch_name)
712
  for content_file in contents:
 
748
  # Highest priority: specific report.md and slides.md in user_experience_reports
749
  if filter_type == "report" and p_lower == "user_experience_reports/report.md": score -= 1000
750
  if filter_type == "slides" and p_lower == "user_experience_reports/slides.md": score -= 1000
751
+ if filter_type == "slides" and p_lower == "user_experience_reports/slides": score -= 2000
752
 
753
  # High priority: other files in user_experience_reports
754
  if "user_experience_reports" in p_lower: score -= 100
 
838
  # Method 1: Check for multi-file slides folder
839
  # We check this first if the report_path is in user_experience_reports or if it's default
840
  if "user_experience_reports" in report_path:
841
+ # If the user selected the folder itself or a file within a folder that has a slides subfolder
842
+ if report_path.endswith("/slides") or report_path.endswith("/slides/"):
843
+ slides_folder = report_path
844
+ else:
845
+ slides_folder = "user_experience_reports/slides"
846
+
847
  try:
848
  folder_contents = repo.get_contents(slides_folder, ref=branch_name)
849
  if isinstance(folder_contents, list):
 
916
 
917
  if os.path.exists(f"{output_dir}/index.html"):
918
  # Return IFrame pointing to the generated site.
919
+ # Use a path relative to the current working directory for Gradio's /file endpoint
920
+ rel_path = os.path.relpath(f"{output_dir}/index.html", os.getcwd())
921
+ add_log(f"Slides rendered. Serving from relative path: {rel_path}")
922
+
923
+ # Use 'file={rel_path}' which is more robust in HF Spaces than '/file={abs_path}'
924
+ return f'<iframe src="file={rel_path}" width="100%" height="600px" frameborder="0"></iframe>'
925
  else:
926
  return "Failed to render slides."
927
 
verify_slides_logic.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import unittest
3
+ from unittest.mock import MagicMock, patch
4
+
5
+ # Mock Gradio and other imports that might fail or are not needed for logic test
6
+ import sys
7
+ sys.modules['gradio'] = MagicMock()
8
+ sys.modules['github'] = MagicMock()
9
+ sys.modules['openai'] = MagicMock()
10
+ sys.modules['chevron'] = MagicMock()
11
+
12
+ # Import the functions from app.py
13
+ # We need to handle the global variables in app.py
14
+ with patch('app.gh', MagicMock()):
15
+ import app
16
+
17
+ class TestSlidesLogic(unittest.TestCase):
18
+ def setUp(self):
19
+ self.repo_name = "test/repo"
20
+ self.branch_name = "main"
21
+ app.gh = MagicMock()
22
+ self.mock_repo = MagicMock()
23
+ app.gh.get_repo.return_value = self.mock_repo
24
+
25
+ def test_get_reports_in_branch_with_slides_folder(self):
26
+ # Mock successful detection of slides folder
27
+ def get_contents_mock(path, ref=None):
28
+ if path == "user_experience_reports/slides":
29
+ return MagicMock() # directory exists
30
+ if path == "user_experience_reports":
31
+ mock_file = MagicMock()
32
+ mock_file.name = "report.md"
33
+ return [mock_file]
34
+ raise Exception("404 Not Found")
35
+
36
+ self.mock_repo.get_contents.side_effect = get_contents_mock
37
+
38
+ # Mock tree for recursive scan
39
+ mock_tree_element = MagicMock()
40
+ mock_tree_element.type = "blob"
41
+ mock_tree_element.path = "user_experience_reports/slides/01_intro.md"
42
+ self.mock_repo.get_git_tree.return_value.tree = [mock_tree_element]
43
+
44
+ reports = app.get_reports_in_branch(self.repo_name, self.branch_name, filter_type="slides")
45
+
46
+ self.assertIn("user_experience_reports/slides", reports)
47
+ # Should be at the top due to score -2000
48
+ self.assertEqual(reports[0], "user_experience_reports/slides")
49
+
50
+ @patch('subprocess.run')
51
+ @patch('os.makedirs')
52
+ @patch('os.path.exists')
53
+ @patch('shutil.rmtree')
54
+ @patch('builtins.open', new_callable=unittest.mock.mock_open)
55
+ def test_render_slides_merging(self, mock_open, mock_rmtree, mock_exists, mock_makedirs, mock_run):
56
+ # Mock exists to say index.html is created
57
+ mock_exists.side_effect = lambda p: True if "index.html" in p else False
58
+
59
+ # Mock slides folder contents
60
+ slide1 = MagicMock()
61
+ slide1.name = "01_slide.md"
62
+ slide1.path = "user_experience_reports/slides/01_slide.md"
63
+
64
+ slide2 = MagicMock()
65
+ slide2.name = "02_slide.md"
66
+ slide2.path = "user_experience_reports/slides/02_slide.md"
67
+
68
+ def get_contents_mock(path, ref=None):
69
+ if path == "user_experience_reports/slides":
70
+ return [slide1, slide2]
71
+ if "01_slide.md" in path:
72
+ m = MagicMock()
73
+ m.decoded_content = b"Slide 1 Content"
74
+ return m
75
+ if "02_slide.md" in path:
76
+ m = MagicMock()
77
+ m.decoded_content = b"Slide 2 Content"
78
+ return m
79
+ return MagicMock()
80
+
81
+ self.mock_repo.get_contents.side_effect = get_contents_mock
82
+
83
+ # We also need to mock add_log to avoid errors if it tries to print
84
+ with patch('app.add_log', MagicMock()):
85
+ result = app.render_slides(self.repo_name, self.branch_name, "user_experience_reports/slides")
86
+
87
+ # Verify merging logic
88
+ mock_open.assert_any_call(unittest.mock.ANY, "w")
89
+ handle = mock_open()
90
+
91
+ # Check if Slide 1 and Slide 2 are merged with ---
92
+ written_content = "".join(call.args[0] for call in handle.write.call_args_list)
93
+ self.assertIn("Slide 1 Content", written_content)
94
+ self.assertIn("Slide 2 Content", written_content)
95
+ self.assertIn("\n\n---\n\n", written_content)
96
+
97
+ # Verify IFrame URL is relative
98
+ self.assertIn('src="file=slides_site_', result)
99
+ self.assertNotIn('src="/file=', result)
100
+
101
+ if __name__ == "__main__":
102
+ unittest.main()