bluenevus commited on
Commit
550b4de
·
verified ·
1 Parent(s): 586d074

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -1
app.py CHANGED
@@ -29,7 +29,149 @@ hf_api = HfApi()
29
  GITHUB_TOKEN = os.environ.get('GITHUB_TOKEN')
30
  GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
31
 
32
- # ... (rest of the functions remain unchanged)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  # App layout
35
  app.layout = dbc.Container([
 
29
  GITHUB_TOKEN = os.environ.get('GITHUB_TOKEN')
30
  GEMINI_API_KEY = os.environ.get('GEMINI_API_KEY')
31
 
32
+ def is_ui_file(filename):
33
+ ui_extensions = ['.erb', '.haml', '.slim', '.php', '.aspx', '.jsp', '.ftl', '.twig', '.mustache', '.handlebars', '.ejs', '.pug', '.blade.php', '.xhtml', '.fxml', '.tsx', '.jsx', '.vue', '.html', '.cshtml', '.razor', '.xaml', '.jsx']
34
+ return any(filename.endswith(ext) for ext in ui_extensions)
35
+
36
+ def get_file_contents(git_provider, repo_url, exclude_folders):
37
+ file_contents = []
38
+ logger.info(f"Fetching files from {git_provider} repository: {repo_url}")
39
+ exclude_folders = [folder.strip() for folder in exclude_folders.split(',') if folder.strip()]
40
+ if git_provider == "GitHub":
41
+ g = Github(GITHUB_TOKEN)
42
+ repo = g.get_repo(repo_url)
43
+ contents = repo.get_contents("")
44
+ while contents:
45
+ file_content = contents.pop(0)
46
+ if file_content.type == "dir":
47
+ if not any(file_content.path.startswith(folder) for folder in exclude_folders):
48
+ contents.extend(repo.get_contents(file_content.path))
49
+ elif is_ui_file(file_content.name) and not any(file_content.path.startswith(folder) for folder in exclude_folders):
50
+ logger.info(f"Found UI file: {file_content.path}")
51
+ file_contents.append((file_content.path, file_content.decoded_content.decode('utf-8', errors='ignore')))
52
+ elif git_provider == "GitLab":
53
+ gl = gitlab.Gitlab(url='https://gitlab.com', private_token=GITHUB_TOKEN)
54
+ project = gl.projects.get(repo_url)
55
+ items = project.repository_tree(recursive=True)
56
+ for item in items:
57
+ if item['type'] == 'blob' and is_ui_file(item['name']) and not any(item['path'].startswith(folder) for folder in exclude_folders):
58
+ logger.info(f"Found UI file: {item['path']}")
59
+ file_content = project.files.get(item['path'], ref='main')
60
+ file_contents.append((item['path'], file_content.decode().decode('utf-8', errors='ignore')))
61
+ elif git_provider == "Gitea":
62
+ base_url = "https://gitea.com/api/v1"
63
+ headers = {"Authorization": f"token {GITHUB_TOKEN}"}
64
+ def recursive_get_contents(path=""):
65
+ response = requests.get(f"{base_url}/repos/{repo_url}/contents/{path}", headers=headers)
66
+ response.raise_for_status()
67
+ for item in response.json():
68
+ if item['type'] == 'file' and is_ui_file(item['name']) and not any(item['path'].startswith(folder) for folder in exclude_folders):
69
+ logger.info(f"Found UI file: {item['path']}")
70
+ file_content = requests.get(item['download_url']).text
71
+ file_contents.append((item['path'], file_content))
72
+ elif item['type'] == 'dir' and not any(item['path'].startswith(folder) for folder in exclude_folders):
73
+ recursive_get_contents(item['path'])
74
+ recursive_get_contents()
75
+ else:
76
+ raise ValueError("Unsupported Git provider")
77
+ logger.info(f"Total UI files found: {len(file_contents)}")
78
+ return file_contents
79
+
80
+ def generate_guide_section(file_path, file_content, guide_type):
81
+ logger.info(f"Generating {guide_type} section for file: {file_path}")
82
+ genai.configure(api_key=GEMINI_API_KEY)
83
+ model = genai.GenerativeModel('gemini-2.0-flash-lite')
84
+
85
+ if guide_type == "User Guide":
86
+ prompt = f"""Based on the following UI-related code file, generate a section for a user guide:
87
+
88
+ File: {file_path}
89
+ Content:
90
+ {file_content}
91
+
92
+ Please focus on:
93
+ 1. The specific features and functionality this UI component provides to the end users
94
+ 2. Step-by-step instructions on how to use these features
95
+ 3. Any user interactions or inputs required
96
+ 4. Expected outcomes or results for the user
97
+
98
+ Important formatting instructions:
99
+ - The output should be in plain text no markdown for example do not use * or ** or # or ##. Instead use numbers like 1., 2. for bullets
100
+ - Use clear section titles
101
+ - Follow this numbering heirarchy (1.0, 1.1, 1.2), (2.0, 2.1, 2.2), (3.0, 3.1, 3.2)
102
+ - Explain the purpose and benefit of each feature for non-technical users
103
+ - This is an end user manual, not a system administration manual so focus on the end user components
104
+ """
105
+ else: # Administration Guide
106
+ prompt = f"""Based on the following UI-related code file, generate a section for an System guide:
107
+
108
+ File: {file_path}
109
+ Content:
110
+ {file_content}
111
+
112
+ Please focus on explaining what that component is and does:
113
+ 1. Any configuration options or settings related to this UI component
114
+ 2. Security considerations or access control related to this feature
115
+ 3. How to monitor or troubleshoot issues with this component
116
+ 4. Best practices for managing and maintaining this part of the system
117
+
118
+ Important formatting instructions:
119
+ - The output should be in plain text no markdown for example for example do not use * or ** or # or ##. Instead use numbers like 1., 2. for bullets
120
+ - Use clear section titles
121
+ - Use clear section titles that has the name of the file in parenthesis
122
+ - Follow this numbering heirarchy (1.0, 1.1, 1.2), (2.0, 2.1, 2.2), (3.0, 3.1, 3.2)
123
+ - Explain the purpose and implications of each component
124
+ """
125
+
126
+ response = model.generate_content(prompt)
127
+ logger.info(f"Generated {guide_type} section for {file_path}")
128
+ return response.text
129
+
130
+ def generate_guide(git_provider, repo_url, guide_type, exclude_folders):
131
+ try:
132
+ logger.info(f"Starting guide generation for {repo_url}")
133
+ file_contents = get_file_contents(git_provider, repo_url, exclude_folders)
134
+
135
+ guide_sections = []
136
+ for file_path, content in file_contents:
137
+ section = generate_guide_section(file_path, content, guide_type)
138
+ guide_sections.append(section)
139
+ logger.info(f"Added section for {file_path}")
140
+
141
+ full_guide = f"# {guide_type}\n\n" + "\n\n".join(guide_sections)
142
+
143
+ logger.info("Creating DOCX file")
144
+ doc = docx.Document()
145
+ doc.add_heading(guide_type, 0)
146
+
147
+ for line in full_guide.split('\n'):
148
+ line = line.strip()
149
+ if line.startswith('# '):
150
+ doc.add_heading(line[2:], level=1)
151
+ elif line.startswith('## '):
152
+ doc.add_heading(line[3:], level=2)
153
+ elif line.startswith('Step'):
154
+ doc.add_paragraph(line, style='List Number')
155
+ else:
156
+ doc.add_paragraph(line)
157
+
158
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as temp_docx:
159
+ doc.save(temp_docx.name)
160
+ docx_path = temp_docx.name
161
+ logger.info(f"DOCX file saved: {docx_path}")
162
+
163
+ logger.info("Creating Markdown file")
164
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.md', mode='w', encoding='utf-8') as temp_md:
165
+ temp_md.write(full_guide)
166
+ md_path = temp_md.name
167
+ logger.info(f"Markdown file saved: {md_path}")
168
+
169
+ logger.info("Guide generation completed successfully")
170
+ return full_guide, docx_path, md_path
171
+
172
+ except Exception as e:
173
+ logger.error(f"An error occurred: {str(e)}", exc_info=True)
174
+ return f"An error occurred: {str(e)}", None, None
175
 
176
  # App layout
177
  app.layout = dbc.Container([