acecalisto3 commited on
Commit
09b9180
·
verified ·
1 Parent(s): 4992b5e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +131 -122
app.py CHANGED
@@ -5,7 +5,7 @@ import logging
5
  import time
6
  import os
7
  from datetime import datetime
8
- from typing import List, Dict
9
  import requests
10
  import gradio as gr
11
  import atexit
@@ -15,8 +15,10 @@ import urllib.parse
15
  import warnings
16
  import torch
17
  import flask
 
18
  import spaces
19
  from accelerate import Accelerator
 
20
 
21
  # Constants
22
  INPUT_DIRECTORY = 'input'
@@ -26,7 +28,7 @@ RESOLUTIONS_DIRECTORY = 'resolutions'
26
  REPOS_DIRECTORY = 'repos'
27
 
28
  # Set up logging
29
- def initialize_logger():
30
  log_file = f"{LOGS_DIRECTORY}/github_bot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
31
  logging.basicConfig(
32
  level=logging.INFO,
@@ -40,7 +42,7 @@ def initialize_logger():
40
 
41
  # Set up environment
42
  @spaces.GPU
43
- def initialize_environment(input_file, output_directory):
44
  directories = [LOGS_DIRECTORY, RESOLUTIONS_DIRECTORY, REPOS_DIRECTORY, input_file, output_directory]
45
  for directory in directories:
46
  os.makedirs(directory, exist_ok=True)
@@ -71,7 +73,7 @@ class GitHubAPI:
71
  time.sleep(wait_time)
72
  return False
73
  return True
74
- except Exception as e:
75
  logger.error(f"Error checking rate limit: {str(e)}")
76
  return True
77
 
@@ -80,7 +82,7 @@ class GitHubAPI:
80
  response = requests.get(f"{self.base_url}/repos/{owner}/{repo}", headers=self.headers)
81
  response.raise_for_status()
82
  return response.json()
83
- except Exception as e:
84
  logger.error(f"Error getting repository: {str(e)}")
85
  return {}
86
 
@@ -89,7 +91,7 @@ class GitHubAPI:
89
  response = requests.get(f"{self.base_url}/repos/{owner}/{repo}/issues", headers=self.headers)
90
  response.raise_for_status()
91
  return response.json()
92
- except Exception as e:
93
  logger.error(f"Error getting issues: {str(e)}")
94
  return []
95
 
@@ -98,7 +100,7 @@ class GitHubAPI:
98
  response = requests.post(f"{self.base_url}/repos/{owner}/{repo}/issues", headers=self.headers, json={'title': title, 'body': body})
99
  response.raise_for_status()
100
  return response.json()
101
- except Exception as e:
102
  logger.error(f"Error creating issue: {str(e)}")
103
  return {}
104
 
@@ -107,22 +109,24 @@ class GitHubAPI:
107
  response = requests.patch(f"{self.base_url}/repos/{owner}/{repo}/issues/{issue_number}", headers=self.headers, json={'title': title, 'body': body})
108
  response.raise_for_status()
109
  return response.json()
110
- except Exception as e:
111
  logger.error(f"Error updating issue: {str(e)}")
112
  return {}
113
 
 
 
114
  @app.route('/fetch-issues', methods=['POST'])
115
- def fetch_issues():
116
  data = request.get_json()
117
  github_token = data['githubToken']
118
  repo_url = data['repoUrl']
119
  owner, repo = repo_url.split('/')[-2:]
120
  github_api = GitHubAPI(github_token)
121
- issues = github_api.get_issues(owner, repo)
122
  return jsonify({'issues': issues})
123
 
124
  @app.route('/resolve-issue', methods=['POST'])
125
- def resolve_issue():
126
  data = request.get_json()
127
  github_token = data['githubToken']
128
  repo_url = data['repoUrl']
@@ -136,13 +140,13 @@ def resolve_issue():
136
  return jsonify({'output': f"Issue {issue_number} resolved"})
137
 
138
  @app.route('/extract-info', methods=['POST'])
139
- def extract_info():
140
  data = request.get_json()
141
  url = data['url']
142
  # Extract info from URL
143
  return jsonify({'output': f"Info extracted from {url}"})
144
 
145
- def run_flask_app():
146
  app.run(debug=True, use_reloader=False)
147
 
148
  # HTML and CSS integration
@@ -161,7 +165,6 @@ custom_html = """
161
  color: #e0e0e0;
162
  font-family: 'Roboto', sans-serif;
163
  overflow-x: hidden; /* Prevent horizontal scrollbar */
164
-
165
  }
166
  .card {
167
  border-radius: 1.5rem;
@@ -173,12 +176,10 @@ custom_html = """
173
  border-radius: 0.75rem;
174
  padding-inline: 1.5rem;
175
  padding-block: 0.75rem;
176
-
177
  }
178
  h1, h2, h3 {
179
  color: #e0e0e0;
180
  }
181
-
182
  .output-area {
183
  padding: 1.5rem;
184
  border-radius: 0.75rem;
@@ -187,7 +188,6 @@ custom_html = """
187
  border-radius: 0.75rem;
188
  padding-block: 0.75rem;
189
  padding-inline: 1.5rem;
190
-
191
  }
192
  .btn-primary {
193
  background-color: #7928CA;
@@ -199,13 +199,14 @@ custom_html = """
199
  color: white;
200
  border: 2px solid #22c55e;
201
  }
 
 
 
202
  </style>
203
  </head>
204
  <body class="bg-gray-900">
205
- <div class="container mx-auto p-4" >
206
-
207
  <h1 class="text-4xl md:text-5xl font-extrabold text-center mb-8">GitHub Issue Manager</h1>
208
-
209
  <!-- GitHub Token & Repo URL -->
210
  <div class="card bg-gray-800 p-8">
211
  <div class="form-control">
@@ -221,19 +222,15 @@ custom_html = """
221
  <input type="text" placeholder="Enter the full GitHub repository URL" class="input input-bordered input-primary" id="repo-url">
222
  </div>
223
  </div>
224
-
225
  <!-- Fetch & Resolve Section -->
226
  <div class="card bg-gray-800 p-8">
227
  <div class="flex justify-between gap-4">
228
-
229
  <button class="btn btn-primary" id="fetch-issues">Fetch Issues</button>
230
-
231
- <select class="select select-primary w-full max-w-xs" id="issue-dropdown" >
232
  <option disabled selected>Select Issue</option>
233
  </select>
234
  </div>
235
- <div class="form-control mt-4">
236
- <label class="label">
237
  <span class="label-text">Resolution</span>
238
  </label>
239
  <textarea class="textarea textarea-primary" placeholder="Enter the resolution details" id="resolution-textarea"></textarea>
@@ -248,15 +245,13 @@ custom_html = """
248
  <button class="btn btn-success" id="resolve-issue">Resolve Issue</button>
249
  </div>
250
  </div>
251
-
252
  <!-- Output Area -->
253
- <div class="card bg-gray-800 p-8 mt-4" >
254
  <label class="label">
255
  <span class="label-text">Output</span>
256
  </label>
257
  <textarea class="textarea textarea-primary h-48" id="output-textarea" readonly></textarea>
258
  </div>
259
-
260
  <!-- URL to Extract -->
261
  <div class="card bg-gray-800 p-8 mt-4">
262
  <div class="form-control">
@@ -269,7 +264,7 @@ custom_html = """
269
  <button class="btn btn-primary" id="extract-info">Extract Info</button>
270
  </div>
271
  </div>
272
-
273
  </div>
274
  <script>
275
  const githubTokenInput = document.getElementById('github-token');
@@ -282,123 +277,137 @@ custom_html = """
282
  const outputTextarea = document.getElementById('output-textarea');
283
  const urlTextbox = document.getElementById('url-textbox');
284
  const extractInfoButton = document.getElementById('extract-info');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
 
286
  fetchIssuesButton.addEventListener('click', async () => {
287
- const token = githubTokenInput.value;
288
- const repoUrl = repoUrlInput.value;
289
- if (!token || !repoUrl) {
290
- outputTextarea.value = "Please provide both GitHub Token and Repository URL.";
291
- return;
292
- }
293
- try {
294
- const response = await fetch('/fetch-issues', {
295
- method: 'POST',
296
- headers: {
297
- 'Content-Type': 'application/json',
298
- },
299
- body: JSON.stringify({ githubToken: token, repoUrl: repoUrl }),
300
- });
301
-
302
- if (!response.ok) {
303
- throw new Error(`HTTP error! status: ${response.status}`);
304
  }
305
-
306
- const data = await response.json();
307
- if (data.error) {
308
- outputTextarea.value = data.error;
309
- } else {
310
- issueDropdown.innerHTML = '';
311
- data.issues.forEach(issue => {
312
- const option = document.createElement('option');
313
- option.value = JSON.stringify(issue);
314
- option.text = `${issue.number}: ${issue.title}`;
315
- issueDropdown.add(option);
316
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  }
318
-
319
- } catch (error) {
320
- outputTextarea.value = `Error fetching issues: ${error.message}`;
321
- }
322
  });
323
 
324
  resolveIssueButton.addEventListener('click', async () => {
325
- const token = githubTokenInput.value;
326
- const repoUrl = repoUrlInput.value;
327
- const issue = JSON.parse(issueDropdown.value);
328
- const resolution = resolutionTextarea.value;
329
- const forkedRepoUrl = forkedRepoUrlInput.value;
330
-
331
- if (!token || !repoUrl || !issue || !resolution) {
332
- outputTextarea.value ="Please provide all required fields.";
333
- return;
334
- }
335
- try {
336
- const response = await fetch('/resolve-issue', {
337
- method: 'POST',
338
- headers: {
339
- 'Content-Type': 'application/json',
340
- },
341
- body: JSON.stringify({ githubToken: token, repoUrl: repoUrl, issue: issue, resolution: resolution, forkedRepoUrl: forkedRepoUrl }),
342
- });
343
-
344
- if (!response.ok) {
345
- throw new Error(`HTTP error! status: ${response.status}`);
346
  }
347
-
348
- const data = await response.json();
349
- if (data.error) {
350
- outputTextarea.value = data.error;
351
- } else {
352
- outputTextarea.value = data.output;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
  }
354
- } catch (error) {
355
- outputTextarea.value = `Error resolving issue: ${error.message}`;
356
- }
357
  });
358
 
359
  extractInfoButton.addEventListener('click', async () => {
360
- const url = urlTextbox.value;
361
- if (!url) {
362
- outputTextarea.value = "Please provide a URL.";
363
- return;
364
- }
365
- try {
366
- const response = await fetch('/extract-info', {
367
- method: 'POST',
368
- headers: {
369
- 'Content-Type': 'application/json',
370
- },
371
- body: JSON.stringify({ url: url }),
372
- });
373
-
374
- if (!response.ok) {
375
- throw new Error(`HTTP error! status: ${response.status}`);
376
  }
377
-
378
- const data = await response.json();
379
- if (data.error) {
380
- outputTextarea.value = data.error;
381
- } else {
382
- outputTextarea.value = data.output;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  }
384
- } catch (error) {
385
- outputTextarea.value = `Error extracting info: ${error.message}`;
386
- }
387
  });
388
-
389
  </script>
390
  </body>
391
  </html>
392
  """
393
 
394
- def create_gradio_interface():
395
  with gr.Blocks(css=None, theme=None) as demo:
396
  gr.HTML(custom_html)
397
-
398
  return demo
399
 
400
  # Cleanup function
401
- def cleanup():
402
  try:
403
  temp_dirs = [REPOS_DIRECTORY]
404
  for dir_name in temp_dirs:
@@ -409,7 +418,7 @@ def cleanup():
409
  print(f"Error during cleanup: {str(e)}")
410
 
411
  # Signal handler
412
- def signal_handler(signum, frame):
413
  logger.info(f"Received signal {signum}")
414
  cleanup()
415
  sys.exit(0)
 
5
  import time
6
  import os
7
  from datetime import datetime
8
+ from typing import List, Dict, Any
9
  import requests
10
  import gradio as gr
11
  import atexit
 
15
  import warnings
16
  import torch
17
  import flask
18
+ from flask import Flask, request, jsonify
19
  import spaces
20
  from accelerate import Accelerator
21
+ from threading import Thread
22
 
23
  # Constants
24
  INPUT_DIRECTORY = 'input'
 
28
  REPOS_DIRECTORY = 'repos'
29
 
30
  # Set up logging
31
+ def initialize_logger() -> logging.Logger:
32
  log_file = f"{LOGS_DIRECTORY}/github_bot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
33
  logging.basicConfig(
34
  level=logging.INFO,
 
42
 
43
  # Set up environment
44
  @spaces.GPU
45
+ def initialize_environment(input_file: str, output_directory: str) -> logging.Logger:
46
  directories = [LOGS_DIRECTORY, RESOLUTIONS_DIRECTORY, REPOS_DIRECTORY, input_file, output_directory]
47
  for directory in directories:
48
  os.makedirs(directory, exist_ok=True)
 
73
  time.sleep(wait_time)
74
  return False
75
  return True
76
+ except requests.exceptions.RequestException as e:
77
  logger.error(f"Error checking rate limit: {str(e)}")
78
  return True
79
 
 
82
  response = requests.get(f"{self.base_url}/repos/{owner}/{repo}", headers=self.headers)
83
  response.raise_for_status()
84
  return response.json()
85
+ except requests.exceptions.RequestException as e:
86
  logger.error(f"Error getting repository: {str(e)}")
87
  return {}
88
 
 
91
  response = requests.get(f"{self.base_url}/repos/{owner}/{repo}/issues", headers=self.headers)
92
  response.raise_for_status()
93
  return response.json()
94
+ except requests.exceptions.RequestException as e:
95
  logger.error(f"Error getting issues: {str(e)}")
96
  return []
97
 
 
100
  response = requests.post(f"{self.base_url}/repos/{owner}/{repo}/issues", headers=self.headers, json={'title': title, 'body': body})
101
  response.raise_for_status()
102
  return response.json()
103
+ except requests.exceptions.RequestException as e:
104
  logger.error(f"Error creating issue: {str(e)}")
105
  return {}
106
 
 
109
  response = requests.patch(f"{self.base_url}/repos/{owner}/{repo}/issues/{issue_number}", headers=self.headers, json={'title': title, 'body': body})
110
  response.raise_for_status()
111
  return response.json()
112
+ except requests.exceptions.RequestException as e:
113
  logger.error(f"Error updating issue: {str(e)}")
114
  return {}
115
 
116
+ app = Flask(__name__)
117
+
118
  @app.route('/fetch-issues', methods=['POST'])
119
+ def fetch_issues() -> Dict[str, Any]:
120
  data = request.get_json()
121
  github_token = data['githubToken']
122
  repo_url = data['repoUrl']
123
  owner, repo = repo_url.split('/')[-2:]
124
  github_api = GitHubAPI(github_token)
125
+ issues = github_api.get_issues(owner , repo)
126
  return jsonify({'issues': issues})
127
 
128
  @app.route('/resolve-issue', methods=['POST'])
129
+ def resolve_issue() -> Dict[str, Any]:
130
  data = request.get_json()
131
  github_token = data['githubToken']
132
  repo_url = data['repoUrl']
 
140
  return jsonify({'output': f"Issue {issue_number} resolved"})
141
 
142
  @app.route('/extract-info', methods=['POST'])
143
+ def extract_info() -> Dict[str, Any]:
144
  data = request.get_json()
145
  url = data['url']
146
  # Extract info from URL
147
  return jsonify({'output': f"Info extracted from {url}"})
148
 
149
+ def run_flask_app() -> None:
150
  app.run(debug=True, use_reloader=False)
151
 
152
  # HTML and CSS integration
 
165
  color: #e0e0e0;
166
  font-family: 'Roboto', sans-serif;
167
  overflow-x: hidden; /* Prevent horizontal scrollbar */
 
168
  }
169
  .card {
170
  border-radius: 1.5rem;
 
176
  border-radius: 0.75rem;
177
  padding-inline: 1.5rem;
178
  padding-block: 0.75rem;
 
179
  }
180
  h1, h2, h3 {
181
  color: #e0e0e0;
182
  }
 
183
  .output-area {
184
  padding: 1.5rem;
185
  border-radius: 0.75rem;
 
188
  border-radius: 0.75rem;
189
  padding-block: 0.75rem;
190
  padding-inline: 1.5rem;
 
191
  }
192
  .btn-primary {
193
  background-color: #7928CA;
 
199
  color: white;
200
  border: 2px solid #22c55e;
201
  }
202
+ .loading {
203
+ display: none;
204
+ }
205
  </style>
206
  </head>
207
  <body class="bg-gray-900">
208
+ <div class="container mx-auto p-4">
 
209
  <h1 class="text-4xl md:text-5xl font-extrabold text-center mb-8">GitHub Issue Manager</h1>
 
210
  <!-- GitHub Token & Repo URL -->
211
  <div class="card bg-gray-800 p-8">
212
  <div class="form-control">
 
222
  <input type="text" placeholder="Enter the full GitHub repository URL" class="input input-bordered input-primary" id="repo-url">
223
  </div>
224
  </div>
 
225
  <!-- Fetch & Resolve Section -->
226
  <div class="card bg-gray-800 p-8">
227
  <div class="flex justify-between gap-4">
 
228
  <button class="btn btn-primary" id="fetch-issues">Fetch Issues</button>
229
+ <select class="select select-primary w-full max-w-xs" id="issue-dropdown">
 
230
  <option disabled selected>Select Issue</option>
231
  </select>
232
  </div>
233
+ <div class="form-control mt-4 <label class="label">
 
234
  <span class="label-text">Resolution</span>
235
  </label>
236
  <textarea class="textarea textarea-primary" placeholder="Enter the resolution details" id="resolution-textarea"></textarea>
 
245
  <button class="btn btn-success" id="resolve-issue">Resolve Issue</button>
246
  </div>
247
  </div>
 
248
  <!-- Output Area -->
249
+ <div class="card bg-gray-800 p-8 mt-4">
250
  <label class="label">
251
  <span class="label-text">Output</span>
252
  </label>
253
  <textarea class="textarea textarea-primary h-48" id="output-textarea" readonly></textarea>
254
  </div>
 
255
  <!-- URL to Extract -->
256
  <div class="card bg-gray-800 p-8 mt-4">
257
  <div class="form-control">
 
264
  <button class="btn btn-primary" id="extract-info">Extract Info</button>
265
  </div>
266
  </div>
267
+ <div class="loading" id="loading-indicator">Loading...</div>
268
  </div>
269
  <script>
270
  const githubTokenInput = document.getElementById('github-token');
 
277
  const outputTextarea = document.getElementById('output-textarea');
278
  const urlTextbox = document.getElementById('url-textbox');
279
  const extractInfoButton = document.getElementById('extract-info');
280
+ const loadingIndicator = document.getElementById('loading-indicator');
281
+
282
+ const showLoading = () => {
283
+ loadingIndicator.style.display = 'block';
284
+ fetchIssuesButton.disabled = true;
285
+ resolveIssueButton.disabled = true;
286
+ extractInfoButton.disabled = true;
287
+ };
288
+
289
+ const hideLoading = () => {
290
+ loadingIndicator.style.display = 'none';
291
+ fetchIssuesButton.disabled = false;
292
+ resolveIssueButton.disabled = false;
293
+ extractInfoButton.disabled = false;
294
+ };
295
 
296
  fetchIssuesButton.addEventListener('click', async () => {
297
+ const token = githubTokenInput.value;
298
+ const repoUrl = repoUrlInput.value;
299
+ if (!token || !repoUrl) {
300
+ outputTextarea.value = "Please provide both GitHub Token and Repository URL.";
301
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
302
  }
303
+ showLoading();
304
+ try {
305
+ const response = await fetch('/fetch-issues', {
306
+ method: 'POST',
307
+ headers: {
308
+ 'Content-Type': 'application/json',
309
+ },
310
+ body: JSON.stringify({ githubToken: token, repoUrl: repoUrl }),
 
 
 
311
  });
312
+ if (!response.ok) {
313
+ throw new Error(`HTTP error! status: ${response.status}`);
314
+ }
315
+ const data = await response.json();
316
+ if (data.error) {
317
+ outputTextarea.value = data.error;
318
+ } else {
319
+ issueDropdown.innerHTML = '';
320
+ data.issues.forEach(issue => {
321
+ const option = document.createElement('option');
322
+ option.value = JSON.stringify(issue);
323
+ option.text = `${issue.number}: ${issue.title}`;
324
+ issueDropdown.add(option);
325
+ });
326
+ }
327
+ } catch (error) {
328
+ outputTextarea.value = `Error fetching issues: ${error.message}`;
329
+ } finally {
330
+ hideLoading();
331
  }
 
 
 
 
332
  });
333
 
334
  resolveIssueButton.addEventListener('click', async () => {
335
+ const token = githubTokenInput.value;
336
+ const repoUrl = repoUrlInput.value;
337
+ const issue = JSON.parse(issueDropdown.value);
338
+ const resolution = resolutionTextarea.value;
339
+ const forkedRepoUrl = forkedRepoUrlInput.value;
340
+ if (!token || !repoUrl || !issue || !resolution) {
341
+ outputTextarea.value = "Please provide all required fields.";
342
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  }
344
+ show Loading();
345
+ try {
346
+ const response = await fetch('/resolve-issue', {
347
+ method: 'POST',
348
+ headers: {
349
+ 'Content-Type': 'application/json',
350
+ },
351
+ body: JSON.stringify({ githubToken: token, repoUrl: repoUrl, issue: issue, resolution: resolution, forkedRepoUrl: forkedRepoUrl }),
352
+ });
353
+ if (!response.ok) {
354
+ throw new Error(`HTTP error! status: ${response.status}`);
355
+ }
356
+ const data = await response.json();
357
+ if (data.error) {
358
+ outputTextarea.value = data.error;
359
+ } else {
360
+ outputTextarea.value = data.output;
361
+ }
362
+ } catch (error) {
363
+ outputTextarea.value = `Error resolving issue: ${error.message}`;
364
+ } finally {
365
+ hideLoading();
366
  }
 
 
 
367
  });
368
 
369
  extractInfoButton.addEventListener('click', async () => {
370
+ const url = urlTextbox.value;
371
+ if (!url) {
372
+ outputTextarea.value = "Please provide a URL.";
373
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
374
  }
375
+ showLoading();
376
+ try {
377
+ const response = await fetch('/extract-info', {
378
+ method: 'POST',
379
+ headers: {
380
+ 'Content-Type': 'application/json',
381
+ },
382
+ body: JSON.stringify({ url: url }),
383
+ });
384
+ if (!response.ok) {
385
+ throw new Error(`HTTP error! status: ${response.status}`);
386
+ }
387
+ const data = await response.json();
388
+ if (data.error) {
389
+ outputTextarea.value = data.error;
390
+ } else {
391
+ outputTextarea.value = data.output;
392
+ }
393
+ } catch (error) {
394
+ outputTextarea.value = `Error extracting info: ${error.message}`;
395
+ } finally {
396
+ hideLoading();
397
  }
 
 
 
398
  });
 
399
  </script>
400
  </body>
401
  </html>
402
  """
403
 
404
+ def create_gradio_interface() -> gr.Blocks:
405
  with gr.Blocks(css=None, theme=None) as demo:
406
  gr.HTML(custom_html)
 
407
  return demo
408
 
409
  # Cleanup function
410
+ def cleanup() -> None:
411
  try:
412
  temp_dirs = [REPOS_DIRECTORY]
413
  for dir_name in temp_dirs:
 
418
  print(f"Error during cleanup: {str(e)}")
419
 
420
  # Signal handler
421
+ def signal_handler(signum: int, frame) -> None:
422
  logger.info(f"Received signal {signum}")
423
  cleanup()
424
  sys.exit(0)