1+ # general_utils.py
2+ import os
3+ import tempfile
4+ from libs .logger import logger
5+ import subprocess
6+ import traceback
7+ import streamlit as st
8+ from libs .lang_codes import LangCodes
9+
10+ # Import the service_account module
11+ from google .oauth2 import service_account
12+ from google .auth import exceptions
13+ from google .auth .transport import requests
14+
15+ class GeneralUtils :
16+
17+ def execute_code (self ,compiler_mode : str ):
18+ logger .info (f"Executing code: { st .session_state .generated_code [:100 ]} in language: { st .session_state .code_language } with Compiler Mode: { compiler_mode } " )
19+
20+ try :
21+ if len (st .session_state .generated_code ) == 0 or st .session_state .generated_code == "" :
22+ st .toast ("Generated code is empty. Cannot execute an empty code." , icon = "❌" )
23+ return
24+
25+ if compiler_mode .lower () == "online" :
26+ html_content = self .generate_dynamic_html (st .session_state .code_language , st .session_state .generated_code )
27+ logger .info (f"HTML Template: { html_content [:100 ]} " )
28+ return html_content
29+
30+ else :
31+ output = self .run_code (st .session_state .generated_code ,st .session_state .code_language )
32+ logger .info (f"Output execution: { output } " )
33+
34+ if "error" in output .lower () or "exception" in output .lower () or "SyntaxError" in output .lower () or "NameError" in output .lower ():
35+
36+ logger .error (f"Error in code execution: { output } " )
37+ response = st .session_state .sequential_chain ({'code_topic' : st .session_state .generated_code })
38+ fixed_code = response ['code_fix' ]
39+ st .code (fixed_code , language = st .session_state .code_language .lower ())
40+
41+ with st .expander ('Message History' ):
42+ st .info (st .session_state .memory .buffer )
43+ logger .warning (f"Trying to run fixed code: { fixed_code } " )
44+ output = GeneralUtils .run_code (fixed_code , st .session_state .code_language )
45+ logger .warning (f"Fixed code output: { output } " )
46+
47+ st .toast ("Execution Output:\n " + output , icon = "🔥" )
48+ logger .info (f"Execution Output: { output } " )
49+
50+ except Exception as e :
51+ st .toast ("Error in code execution:" ,icon = "❌" )
52+ # Output the stack trace
53+ st .toast (traceback .format_exc (), icon = "❌" )
54+ logger .error (f"Error in code execution: { traceback .format_exc ()} " )
55+
56+ # Generate Dynamic HTML for JDoodle Compiler iFrame Embedding.
57+ def generate_dynamic_html (self ,language , code_prompt ):
58+ logger .info ("Generating dynamic HTML for language: %s" , language )
59+ html_template = """
60+ <!DOCTYPE html>
61+ <html lang="en">
62+ <head>
63+ <meta charset="UTF-8">
64+ <title>Online JDoodle Compiler</title>
65+ </head>
66+ <body>
67+ <div data-pym-src='https://www.jdoodle.com/plugin' data-language="{language}"
68+ data-version-index="0" data-libs="" >{script_code}
69+ </div>
70+ <script src="https://www.jdoodle.com/assets/jdoodle-pym.min.js" type="text/javascript"></script>
71+ </body>
72+ </html>
73+ """ .format (language = LangCodes ()[language ], script_code = code_prompt )
74+ return html_template
75+
76+ def run_code (self ,code , language ):
77+ logger .info (f"Running code: { code [:100 ]} in language: { language } " )
78+
79+ if language == "Python" :
80+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".py" , delete = True ) as file :
81+ file .write (code )
82+ file .flush ()
83+
84+ logger .info (f"Input file: { file .name } " )
85+ output = subprocess .run (
86+ ["python" , file .name ], capture_output = True , text = True )
87+ logger .info (f"Runner Output execution: { output .stdout + output .stderr } " )
88+ return output .stdout + output .stderr
89+
90+ elif language == "C" or language == "C++" :
91+ ext = ".c" if language == "C" else ".cpp"
92+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ext , delete = True ) as src_file :
93+ src_file .write (code )
94+ src_file .flush ()
95+
96+ logger .info (f"Input file: { src_file .name } " )
97+
98+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = "" , delete = True ) as exec_file :
99+ compile_output = subprocess .run (
100+ ["gcc" if language == "C" else "g++" , "-o" , exec_file .name , src_file .name ], capture_output = True , text = True )
101+
102+ if compile_output .returncode != 0 :
103+ return compile_output .stderr
104+
105+ logger .info (f"Output file: { exec_file .name } " )
106+ run_output = subprocess .run (
107+ [exec_file .name ], capture_output = True , text = True )
108+ logger .info (f"Runner Output execution: { run_output .stdout + run_output .stderr } " )
109+ return run_output .stdout + run_output .stderr
110+
111+ elif language == "JavaScript" :
112+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".js" , delete = True ) as file :
113+ file .write (code )
114+ file .flush ()
115+
116+ logger .info (f"Input file: { file .name } " )
117+ output = subprocess .run (
118+ ["node" , file .name ], capture_output = True , text = True )
119+ logger .info (f"Runner Output execution: { output .stdout + output .stderr } " )
120+ return output .stdout + output .stderr
121+
122+ elif language == "Java" :
123+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".java" , delete = True ) as file :
124+ file .write (code )
125+ file .flush ()
126+ classname = "Main" # Assuming the class name is Main, adjust if needed
127+ compile_output = subprocess .run (["javac" , file .name ], capture_output = True , text = True )
128+ if compile_output .returncode != 0 :
129+ return compile_output .stderr
130+ run_output = subprocess .run (["java" , "-cp" , tempfile .gettempdir (), classname ], capture_output = True , text = True )
131+ return run_output .stdout + run_output .stderr
132+
133+ elif language == "Swift" :
134+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".swift" , delete = True ) as file :
135+ file .write (code )
136+ file .flush ()
137+ output = subprocess .run (["swift" , file .name ], capture_output = True , text = True )
138+ return output .stdout + output .stderr
139+
140+ elif language == "C#" :
141+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".cs" , delete = True ) as file :
142+ file .write (code )
143+ file .flush ()
144+ compile_output = subprocess .run (["csc" , file .name ], capture_output = True , text = True )
145+ if compile_output .returncode != 0 :
146+ return compile_output .stderr
147+ exe_name = file .name .replace (".cs" , ".exe" )
148+ run_output = subprocess .run ([exe_name ], capture_output = True , text = True )
149+ return run_output .stdout + run_output .stderr
150+
151+ elif language == "Scala" :
152+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".scala" , delete = True ) as file :
153+ file .write (code )
154+ file .flush ()
155+ output = subprocess .run (["scala" , file .name ], capture_output = True , text = True )
156+ return output .stdout + output .stderr
157+
158+ elif language == "Ruby" :
159+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".rb" , delete = True ) as file :
160+ file .write (code )
161+ file .flush ()
162+ output = subprocess .run (["ruby" , file .name ], capture_output = True , text = True )
163+ return output .stdout + output .stderr
164+
165+ elif language == "Kotlin" :
166+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".kt" , delete = True ) as file :
167+ file .write (code )
168+ file .flush ()
169+ compile_output = subprocess .run (["kotlinc" , file .name , "-include-runtime" , "-d" , "output.jar" ], capture_output = True , text = True )
170+ if compile_output .returncode != 0 :
171+ return compile_output .stderr
172+ run_output = subprocess .run (["java" , "-jar" , "output.jar" ], capture_output = True , text = True )
173+ return run_output .stdout + run_output .stderr
174+
175+ elif language == "Go" :
176+ with tempfile .NamedTemporaryFile (mode = "w" , suffix = ".go" , delete = True ) as file :
177+ file .write (code )
178+ file .flush ()
179+ compile_output = subprocess .run (["go" , "build" , "-o" , "output.exe" , file .name ], capture_output = True , text = True )
180+ if compile_output .returncode != 0 :
181+ return compile_output .stderr
182+ run_output = subprocess .run (["./output.exe" ], capture_output = True , text = True )
183+ return run_output .stdout + run_output .stderr
184+ else :
185+ return "Unsupported language."
186+
187+ def save_code (self , file_name ):
188+ try :
189+ # Check for empty file name
190+ if not file_name or len (file_name ) == 0 :
191+ st .toast ("Please enter a valid file name." , icon = "❌" )
192+ logger .error ("Error in code saving: Please enter a valid file name." )
193+ return
194+
195+ file_extension = file_name .split ("." )[- 1 ]
196+ logger .info (f"Saving code to file: { file_name } with extension: { file_extension } " )
197+
198+ # Create directory if it doesn't exist
199+ if not os .path .exists (file_extension ):
200+ os .makedirs (file_extension )
201+ logger .info (f"Directory { file_extension } created successfully" )
202+
203+ # Check for empty code
204+ if not st .session_state .generated_code or len (st .session_state .generated_code .strip ()) == 0 :
205+ st .toast ("Generated code is empty. Cannot save an empty file." , icon = "❌" )
206+ logger .error ("Error in code saving: Generated code is empty." )
207+ return
208+
209+ with open (f"{ file_extension } /{ file_name } " , "w" ) as file :
210+ file .write (st .session_state .generated_code )
211+
212+ st .toast (f"Code saved to file { file_name } " , icon = "✅" )
213+ logger .info (f"Code saved to file { file_name } " )
214+
215+ except Exception as e :
216+ st .toast (traceback .format_exc ())
217+ logger .error (f"Error in code saving: { traceback .format_exc ()} " )
218+
219+
220+
221+ # # Initialize Vertex AI
222+ def load_enviroment_variables (self , credentials_file_path , project , region ):
223+ """
224+ Consider running `gcloud config set project` or setting the GOOGLE_CLOUD_PROJECT environment variable
225+ """
226+ """Load environment variables"""
227+ if credentials_file_path :
228+ logger .info (f"Loading credentials from { credentials_file_path } " )
229+ try :
230+ credentials = service_account .Credentials .from_service_account_file (credentials_file_path )
231+ session = requests .AuthorizedSession (credentials )
232+ os .environ ["GOOGLE_APPLICATION_CREDENTIALS" ] = session .credentials .refresh (requests .Request ()).token
233+ except exceptions .GoogleAuthError as e :
234+ logger .error (f"Failed to load the service account key: { e } " )
235+ st .toast (f"Failed to load the service account key: { e } " , icon = "❌" )
236+ return False
237+ else :
238+ os .environ ["GOOGLE_APPLICATION_CREDENTIALS" ] = os .getenv ("GOOGLE_APPLICATION_CREDENTIALS" )
239+ logger .info ("Loading credentials from .env file" )
240+
241+
242+ if project :
243+ logger .info (f"Setting project to { project } " )
244+ os .environ ["GOOGLE_CLOUD_PROJECT" ] = project
245+ else :
246+ os .environ ["GOOGLE_CLOUD_PROJECT" ] = os .getenv ("GOOGLE_CLOUD_PROJECT" )
247+ logger .info ("Loading project from .env file" )
248+
249+ if region :
250+ logger .info (f"Setting region to { region } " )
251+ os .environ ["GOOGLE_CLOUD_REGION" ] = region
252+ else :
253+ os .environ ["GOOGLE_CLOUD_REGION" ] = os .getenv ("GOOGLE_CLOUD_REGION" )
254+ logger .info ("Loading region from .env file" )
255+
256+ # Create method which takes string and calulate its number of words,letter count and for each 1000 characters in that string it will multiply with $0.0005 and return the cost, cost per whole string and total cost..
257+ def calculate_code_generation_cost (self ,string ,price = 0.0005 ):
258+ # Calculate number of words
259+ number_of_words = len (string .split ())
260+
261+ # Calculate number of letters
262+ number_of_letters = len (string )
263+
264+ # Calculate cost
265+ cost = price * (number_of_letters / 1000 )
266+
267+ # Calculate cost per whole string
268+ cost_per_whole_string = price * (len (string ) / 1000 )
269+
270+ # Calculate total cost
271+ total_cost = cost * number_of_words
272+
273+ # Return the cost, cost per whole string and total cost
274+ return cost , cost_per_whole_string , total_cost
275+
276+ def codey_generation_cost (self ,string ):
277+ codey_price = 0.0005
278+ return self .calculate_code_generation_cost (string ,codey_price )
279+
280+ def gpt_3_generation_cost (self ,string ):
281+ chatgpt_price = 0.0002
282+ return self .calculate_code_generation_cost (string ,chatgpt_price )
283+
284+ def gpt_3_5_turbo_generation_costself (self ,string ):
285+ chatgpt_price = 0.0080
286+ return self .calculate_code_generation_cost (string ,chatgpt_price )
287+
288+ def gpt_4_generation_cost (self ,string ):
289+ chatgpt_price = 0.06
290+ return self .calculate_code_generation_cost (string ,chatgpt_price )
291+
292+ def gpt_text_davinci_generation_cost (self ,string ):
293+ chatgpt_price = 0.0060
294+ return self .calculate_code_generation_cost (string ,chatgpt_price )
0 commit comments