faizee07 commited on
Commit
9e9ff82
Β·
verified Β·
1 Parent(s): 9854860

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +192 -66
app.py CHANGED
@@ -1,47 +1,215 @@
1
  import os
2
  import shutil
3
  import tempfile
4
- from flask import Flask, request, jsonify, render_template
5
  import git
6
  import json
7
 
8
  app = Flask(__name__)
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  def analyze_repo(repo_path):
11
- """
12
- Analyzes the cloned repository to gather information.
13
- This is a simplified analysis function. A real-world agent
14
- would be much more sophisticated.
15
- """
16
  project_name = os.path.basename(repo_path)
17
  language = "Not Detected"
18
  dependencies = []
19
  install_command = "No install command found."
20
  run_command = "No run command found."
21
 
22
- # --- Technology and Dependency Analysis ---
23
  if os.path.exists(os.path.join(repo_path, 'requirements.txt')):
24
  language = "Python"
25
  with open(os.path.join(repo_path, 'requirements.txt'), 'r') as f:
26
  dependencies = [line.strip() for line in f.readlines() if line.strip()]
27
  install_command = "pip install -r requirements.txt"
28
- # Try to find a common run command
29
  if os.path.exists(os.path.join(repo_path, 'app.py')) or os.path.exists(os.path.join(repo_path, 'main.py')):
30
  run_command = "python app.py # or python main.py"
31
 
32
-
33
  elif os.path.exists(os.path.join(repo_path, 'package.json')):
34
  language = "JavaScript (Node.js)"
35
  with open(os.path.join(repo_path, 'package.json'), 'r') as f:
36
  package_data = json.load(f)
37
  dependencies = list(package_data.get('dependencies', {}).keys())
38
  install_command = "npm install"
39
- if package_data.get('scripts', {}).get('start'):
40
- run_command = "npm start"
41
- else:
42
- run_command = "node index.js # or appropriate script"
43
 
44
- # Simple logic to infer project purpose from file names
45
  purpose = f"A {language} project."
46
  if 'test' in str(os.listdir(repo_path)).lower():
47
  purpose += " It appears to have testing capabilities."
@@ -49,84 +217,42 @@ def analyze_repo(repo_path):
49
  purpose += " It can be containerized using Docker."
50
 
51
  return {
52
- "project_name": project_name,
53
- "language": language,
54
- "dependencies": dependencies,
55
- "install_command": install_command,
56
- "run_command": run_command,
57
- "purpose": purpose
58
  }
59
 
60
  def generate_readme_content(analysis):
61
  """Generates the README.md content from the analysis results."""
62
-
63
  readme = f"# {analysis['project_name']}\n\n"
64
  readme += f"## πŸ€– About This Project\n\n{analysis['purpose']}\n\n"
65
  readme += f"This project is primarily written in **{analysis['language']}**.\n\n"
66
-
67
  readme += "## πŸš€ Getting Started\n\n"
68
- readme += "### Prerequisites\n\n"
69
- readme += f"Make sure you have {analysis['language']} and the necessary build tools installed on your system.\n\n"
70
-
71
- readme += "### Installation\n\n"
72
- readme += "1. Clone the repository:\n"
73
- readme += " ```sh\n git clone <repository_url>\n ```\n"
74
- readme += "2. Navigate to the project directory:\n"
75
- readme += f" ```sh\n cd {analysis['project_name']}\n ```\n"
76
- readme += "3. Install the dependencies:\n"
77
- readme += f" ```sh\n {analysis['install_command']}\n ```\n\n"
78
-
79
- if analysis['dependencies']:
80
- readme += "Key dependencies include:\n"
81
- for dep in analysis['dependencies'][:5]: # Show first 5 dependencies
82
- readme += f"- `{dep}`\n"
83
- readme += "\n"
84
-
85
- readme += "### Usage\n\n"
86
- readme += "To run the project, execute the following command:\n"
87
  readme += f"```sh\n{analysis['run_command']}\n```\n\n"
88
-
89
- readme += "---\n"
90
- readme += "*This README was automatically generated by an AI agent.*"
91
-
92
  return readme
93
 
94
  @app.route('/')
95
  def index():
96
- return render_template('index.html')
97
 
98
  @app.route('/generate', methods=['POST'])
99
  def generate():
100
- data = request.get_json()
101
- repo_url = data.get('url')
102
-
103
  if not repo_url:
104
- return jsonify({"error": "GitHub repository URL is required."}), 400
105
 
106
  temp_dir = tempfile.mkdtemp()
107
-
108
  try:
109
- # --- Agent Tool 1: Git Clone ---
110
- print(f"Cloning repository: {repo_url} into {temp_dir}")
111
  git.Repo.clone_from(repo_url, temp_dir)
112
-
113
- # --- Agent Tool 2: File Analysis ---
114
- print("Analyzing repository structure...")
115
  analysis_result = analyze_repo(temp_dir)
116
-
117
- # --- Agent Step 3: Write README ---
118
- print("Generating README content...")
119
  readme_content = generate_readme_content(analysis_result)
120
-
121
  return jsonify({"readme": readme_content})
122
-
123
- except git.exc.GitCommandError as e:
124
- return jsonify({"error": f"Failed to clone repository. Is the URL correct and public? Error: {e}"}), 500
125
  except Exception as e:
126
- return jsonify({"error": f"An unexpected error occurred: {str(e)}"}), 500
127
  finally:
128
- # --- Cleanup ---
129
- print(f"Cleaning up temporary directory: {temp_dir}")
130
  shutil.rmtree(temp_dir)
131
 
132
  if __name__ == '__main__':
 
1
  import os
2
  import shutil
3
  import tempfile
4
+ from flask import Flask, request, jsonify, render_template_string
5
  import git
6
  import json
7
 
8
  app = Flask(__name__)
9
 
10
+ # --- HTML and CSS are now embedded inside the Python file ---
11
+ HTML_TEMPLATE = """
12
+ <!DOCTYPE html>
13
+ <html lang="en">
14
+ <head>
15
+ <meta charset="UTF-8">
16
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
17
+ <title>GitHub README Generator</title>
18
+ <style>
19
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
20
+
21
+ body {
22
+ font-family: 'Inter', sans-serif;
23
+ background-color: #f0f2f5;
24
+ color: #1c1e21;
25
+ margin: 0;
26
+ display: flex;
27
+ justify-content: center;
28
+ align-items: center;
29
+ min-height: 100vh;
30
+ padding: 20px;
31
+ box-sizing: border-box;
32
+ }
33
+
34
+ .container {
35
+ background-color: #ffffff;
36
+ padding: 40px 50px;
37
+ border-radius: 12px;
38
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
39
+ width: 100%;
40
+ max-width: 700px;
41
+ text-align: center;
42
+ }
43
+
44
+ h1 {
45
+ font-size: 2.2em;
46
+ color: #1877f2;
47
+ margin-bottom: 10px;
48
+ }
49
+
50
+ p {
51
+ color: #606770;
52
+ font-size: 1.1em;
53
+ margin-bottom: 30px;
54
+ }
55
+
56
+ .input-group {
57
+ display: flex;
58
+ margin-bottom: 20px;
59
+ }
60
+
61
+ #repo-url {
62
+ flex-grow: 1;
63
+ padding: 15px;
64
+ border: 1px solid #dddfe2;
65
+ border-radius: 6px 0 0 6px;
66
+ font-size: 1em;
67
+ outline: none;
68
+ min-width: 0; /* Fix for flexbox shrinking */
69
+ }
70
+
71
+ #repo-url:focus {
72
+ border-color: #1877f2;
73
+ box-shadow: 0 0 0 2px rgba(24, 119, 242, 0.2);
74
+ }
75
+
76
+ button {
77
+ padding: 15px 25px;
78
+ border: none;
79
+ background-color: #1877f2;
80
+ color: white;
81
+ font-size: 1em;
82
+ font-weight: 600;
83
+ border-radius: 0 6px 6px 0;
84
+ cursor: pointer;
85
+ transition: background-color 0.3s;
86
+ }
87
+
88
+ button:hover {
89
+ background-color: #166fe5;
90
+ }
91
+
92
+ .loader {
93
+ border: 4px solid #f3f3f3;
94
+ border-top: 4px solid #1877f2;
95
+ border-radius: 50%;
96
+ width: 40px;
97
+ height: 40px;
98
+ animation: spin 1s linear infinite;
99
+ margin: 30px auto;
100
+ display: none; /* Hidden by default */
101
+ }
102
+
103
+ @keyframes spin {
104
+ 0% { transform: rotate(0deg); }
105
+ 100% { transform: rotate(360deg); }
106
+ }
107
+
108
+ #result-container {
109
+ display: none; /* Hidden by default */
110
+ margin-top: 20px;
111
+ }
112
+
113
+ #result {
114
+ margin-top: 10px;
115
+ padding: 20px;
116
+ background-color: #f7f7f7;
117
+ border: 1px solid #dddfe2;
118
+ border-radius: 6px;
119
+ text-align: left;
120
+ white-space: pre-wrap; /* Allows text to wrap */
121
+ font-family: 'Courier New', Courier, monospace;
122
+ max-height: 400px;
123
+ overflow-y: auto;
124
+ word-wrap: break-word;
125
+ }
126
+ </style>
127
+ </head>
128
+ <body>
129
+ <div class="container">
130
+ <h1>GitHub README Generator πŸ’»</h1>
131
+ <p>Enter a public GitHub repository URL and let the AI agent generate a professional README.md for you.</p>
132
+
133
+ <form id="repo-form">
134
+ <div class="input-group">
135
+ <input type="url" id="repo-url" placeholder="e.g., https://github.com/user/project" required>
136
+ <button type="submit">Generate</button>
137
+ </div>
138
+ </form>
139
+
140
+ <div class="loader" id="loader"></div>
141
+
142
+ <div id="result-container">
143
+ <h2>Generated README.md:</h2>
144
+ <pre id="result"></pre>
145
+ </div>
146
+ </div>
147
+
148
+ <script>
149
+ document.getElementById('repo-form').addEventListener('submit', async function(event) {
150
+ event.preventDefault();
151
+
152
+ const url = document.getElementById('repo-url').value;
153
+ const loader = document.getElementById('loader');
154
+ const resultContainer = document.getElementById('result-container');
155
+ const resultDiv = document.getElementById('result');
156
+
157
+ loader.style.display = 'block';
158
+ resultContainer.style.display = 'none';
159
+ resultDiv.textContent = '';
160
+
161
+ try {
162
+ const response = await fetch('/generate', {
163
+ method: 'POST',
164
+ headers: { 'Content-Type': 'application/json' },
165
+ body: JSON.stringify({ url: url })
166
+ });
167
+
168
+ const data = await response.json();
169
+
170
+ if (response.ok) {
171
+ resultDiv.textContent = data.readme;
172
+ } else {
173
+ resultDiv.textContent = 'Error: ' + data.error;
174
+ }
175
+ resultContainer.style.display = 'block';
176
+
177
+ } catch (error) {
178
+ resultDiv.textContent = 'An unexpected error occurred: ' + error.toString();
179
+ resultContainer.style.display = 'block';
180
+ } finally {
181
+ loader.style.display = 'none';
182
+ }
183
+ });
184
+ </script>
185
+ </body>
186
+ </html>
187
+ """
188
+
189
  def analyze_repo(repo_path):
190
+ """Analyzes the cloned repository to gather information."""
 
 
 
 
191
  project_name = os.path.basename(repo_path)
192
  language = "Not Detected"
193
  dependencies = []
194
  install_command = "No install command found."
195
  run_command = "No run command found."
196
 
 
197
  if os.path.exists(os.path.join(repo_path, 'requirements.txt')):
198
  language = "Python"
199
  with open(os.path.join(repo_path, 'requirements.txt'), 'r') as f:
200
  dependencies = [line.strip() for line in f.readlines() if line.strip()]
201
  install_command = "pip install -r requirements.txt"
 
202
  if os.path.exists(os.path.join(repo_path, 'app.py')) or os.path.exists(os.path.join(repo_path, 'main.py')):
203
  run_command = "python app.py # or python main.py"
204
 
 
205
  elif os.path.exists(os.path.join(repo_path, 'package.json')):
206
  language = "JavaScript (Node.js)"
207
  with open(os.path.join(repo_path, 'package.json'), 'r') as f:
208
  package_data = json.load(f)
209
  dependencies = list(package_data.get('dependencies', {}).keys())
210
  install_command = "npm install"
211
+ run_command = "npm start" if package_data.get('scripts', {}).get('start') else "node index.js"
 
 
 
212
 
 
213
  purpose = f"A {language} project."
214
  if 'test' in str(os.listdir(repo_path)).lower():
215
  purpose += " It appears to have testing capabilities."
 
217
  purpose += " It can be containerized using Docker."
218
 
219
  return {
220
+ "project_name": project_name, "language": language, "dependencies": dependencies,
221
+ "install_command": install_command, "run_command": run_command, "purpose": purpose
 
 
 
 
222
  }
223
 
224
  def generate_readme_content(analysis):
225
  """Generates the README.md content from the analysis results."""
 
226
  readme = f"# {analysis['project_name']}\n\n"
227
  readme += f"## πŸ€– About This Project\n\n{analysis['purpose']}\n\n"
228
  readme += f"This project is primarily written in **{analysis['language']}**.\n\n"
 
229
  readme += "## πŸš€ Getting Started\n\n"
230
+ readme += "### Installation\n\n1. Clone the repository.\n"
231
+ readme += f"2. Install dependencies:\n ```sh\n {analysis['install_command']}\n ```\n\n"
232
+ readme += "### Usage\n\nTo run the project, execute:\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  readme += f"```sh\n{analysis['run_command']}\n```\n\n"
234
+ readme += "---\n*This README was automatically generated by an AI agent.*"
 
 
 
235
  return readme
236
 
237
  @app.route('/')
238
  def index():
239
+ return render_template_string(HTML_TEMPLATE)
240
 
241
  @app.route('/generate', methods=['POST'])
242
  def generate():
243
+ repo_url = request.get_json().get('url')
 
 
244
  if not repo_url:
245
+ return jsonify({"error": "URL is required."}), 400
246
 
247
  temp_dir = tempfile.mkdtemp()
 
248
  try:
 
 
249
  git.Repo.clone_from(repo_url, temp_dir)
 
 
 
250
  analysis_result = analyze_repo(temp_dir)
 
 
 
251
  readme_content = generate_readme_content(analysis_result)
 
252
  return jsonify({"readme": readme_content})
 
 
 
253
  except Exception as e:
254
+ return jsonify({"error": f"An error occurred: {str(e)}"}), 500
255
  finally:
 
 
256
  shutil.rmtree(temp_dir)
257
 
258
  if __name__ == '__main__':