From 0f975aa0118d5d08778922895e5e4a6546947f09 Mon Sep 17 00:00:00 2001 From: Indrajeet Mishra Date: Thu, 7 Dec 2023 17:42:55 +0530 Subject: [PATCH 1/3] Added a new Project- Code Compiler --- .DS_Store | Bin 12292 -> 14340 bytes Code Compiler/README.md | 67 +++++++++++++ Code Compiler/bin/logfile.log | 3 + Code Compiler/bin/output.txt | 0 Code Compiler/input/code.txt | 31 ++++++ Code Compiler/input/input.txt | 0 Code Compiler/input/language_list.txt | 77 ++++++++++++++ Code Compiler/requirements.txt | 2 + Code Compiler/src/list_languages.py | 62 ++++++++++++ Code Compiler/src/main.py | 138 ++++++++++++++++++++++++++ 10 files changed, 380 insertions(+) create mode 100644 Code Compiler/README.md create mode 100644 Code Compiler/bin/logfile.log create mode 100644 Code Compiler/bin/output.txt create mode 100644 Code Compiler/input/code.txt create mode 100644 Code Compiler/input/input.txt create mode 100644 Code Compiler/input/language_list.txt create mode 100644 Code Compiler/requirements.txt create mode 100644 Code Compiler/src/list_languages.py create mode 100644 Code Compiler/src/main.py diff --git a/.DS_Store b/.DS_Store index 8cd6e43023e287a14611571bb9bce19f123b4947..fd4144d5242094627558be701fdc194c3e8ae8d2 100644 GIT binary patch delta 2804 zcmeHJ-)~cO6hF7^Mz?ic*R9Y?U6ljqWv<%AxC85*fE-z5M__H=|b2X6=?~<(=g_{3PM$^?j4`*AZZ^$_P|o7 zGEfDe*h2zItOJ?F??o%x_6yM42037f_Rt&>NmIV|o5!wzX+gTkF;sX0{&stm5#n+0 zuYrDgOM1;9BF7x1ONe@n#RAhDjT!*Xe_MRzeW3J;c;A3{-Nf9HtF7BmvF#cMzKmlR(&U53#bWHvdDzEf zxyxXd0W*}uij@*Hu%NdWX=fmoD!aJMH8BNIX#ot%c*0WZkVb_^7B|z{jP2a)wk`2^ zC_3(uIu<4URX8;$t$+|GwA$Km>(45e$aaxt$L7ePajR5a9(vXYcPg?coKBF;<{#Ixc^1thU z*wFu9JvY-A-vrKeaBJzjw1g`#yq~+)Lb5|XE*iV+PG7&=&vlDpR6Gs5Gv#gA=ootL z?{nr*=opw;49`OArsCPId(n$xHhB6<7xb$jPW=#hA9v5)()770;s|_j>=le8Z+Tuj z>%enDO^l`Rb&OMdAKX{F7yMm0<)&#EV*KRF=2fp^x2)hBJHDlMEKA+RUh&Z@U%cC6 z?m46Q2^O5RdngDz}tzd|-~nLv?soYE%!(AP%_( z=bR}AN?{*s|8-dFD2hLY?-9qLV#zRxYxnRO$tIR!uSS7h)nFI;|a)cvd=v zs0ITTjL%c%v<&YWp71wUAb}Okr=M|_oQ2GcTCz$bUkc1PpH#)&&|IVw{c|2@K7V=V zEhEd8g2+?TL|x5^KSGlO9z-etu_%?{0pNj3iY@QpCQDgQ1}`G~HZt=ZV@?e#mMdu` zDaE{Qh`F2rexNBBH@xxQQ$p`7;Escv4TvWh5^a4wZYikgqpXYJktem!hQC&Z+L#aC tzPj-5O!FI9t=I9VUG#+KTsGqc?IhcYZ20y#Ul^bN$Nk0QF75??{0CSw)FS`@ delta 333 zcmZoEXh~3DU|?W$DortDV9)?EIe-{M3-B;7FmW<4C~!|y&}Ven7_gXG@IO$TfkB$V znIWGckD-hqb+aG`Gs|Xn4i*kZt;swBl9OWv0wzBcNZ7nxkcV;dccDv@1w~d#3NQpR z1TiRpwWTnm0$J`rGLNBX@&pYjCT6?MpF~)hCg+R4o7^kmwpm; +![Star Badge](https://img.shields.io/static/v1?label=%F0%9F%8C%9F&message=If%20Useful&style=style=flat&color=BC4E99) +![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103) +[![View My Profile](https://img.shields.io/badge/View-My_Profile-green?logo=GitHub)](https://github.com/thecoddiwompler) + +# Code Compiler + +## 🛠️ Description + +This project is a code execution tool that interacts with an online code compiler API. It consists of the following folders and files: + +- **src:** Contains the main Python scripts. + - `list_languages.py`: Retrieves and prints a list of available programming languages from the online code compiler API based on the contents of `language_list.txt` in the `input` folder. + - `main.py`: Prompts the user for a programming language, checks its availability using the API, and then executes the code from `code.txt` in the `input` folder with corresponding input from `input.txt`. The output is stored in `output.txt` in the `bin` folder. +- **bin:** Stores the output of code execution (`output.txt`) and logs (`logfile.log`). +- **input:** Contains input files for code (`code.txt` and `input.txt`) and a list of languages (`language_list.txt`). +- **.env:** Environment configuration file. +- **requirements.txt:** Specifies the project's dependencies. Developers can install these dependencies using the `pip install -r requirements.txt` command to ensure a consistent environment. +- **README.md:** Documentation file. +- **.gitignore:** Ignored files and directories for version control. +- **LICENSE:** License information for the project. + +## ⚙️ Languages or Frameworks Used + +The script was created with Python3 and the built-in functions in it + +## 🌟 How to run + +1. Use the following command to install dependencies: + + ```bash + pip install -r requirements.txt + ``` + +2. Set the following environment variables in the `.env` file. You can get these details by subscribing to - [Online Code Compiler](https://rapidapi.com/Glavier/api/online-code-compiler/) + + ```markdown + + - `API_KEY`: Your API key for authentication. + - `HOST` : Host for the online compiler. [online-code-compiler.p.rapidapi.com] + - `LANGUAGE_LIST_URL` : API base URL to GET Languages. [https://online-code-compiler.p.rapidapi.com/v1/languages/] + - `COMPILE_CODE_URL` : API base URL to POST Request on online code compiler to execute the code. [https://online-code-compiler.p.rapidapi.com/v1/] + + ``` + +3. Execute the `list_languages.py` script to retrieve and display the list of available programming languages. The information is sourced from the `language_list.txt` file located in the `input` directory. Note that this file is pre-populated for reference, and user don't need to run this script. + + + ```bash + python src/list_languages.py + ``` + +4. Execute the `main.py` script to run user-specified code. The script will prompt the user for a programming language input. It will then perform the following steps: + + 1. Check if the specified language exists using the `get_language` API call. + 2. Verify the presence of the `code.txt` file in the `input` directory, containing the code to be executed. + 3. Check for the existence of the `input.txt` file in the `input` directory for providing input to the code. + 4. If all checks pass, the script will execute the code and return the output, which will be recorded in `output.txt` in the `bin` directory. + 5. Logs for all operations will be generated and recorded in `logfile.log` in the `bin` directory.

+ + ```bash + python src/main.py + ``` + + +## 🤖 Author +[Indrajeet Mishra](https://github.com/thecoddiwompler) \ No newline at end of file diff --git a/Code Compiler/bin/logfile.log b/Code Compiler/bin/logfile.log new file mode 100644 index 00000000..87f9501d --- /dev/null +++ b/Code Compiler/bin/logfile.log @@ -0,0 +1,3 @@ +2023-11-26 15:42:58,582 - INFO - Successfully fetched language data. +2023-11-26 15:43:06,089 - INFO - Successfully compiled the code. +2023-11-26 15:43:06,094 - INFO - Output written to bin/output.txt. diff --git a/Code Compiler/bin/output.txt b/Code Compiler/bin/output.txt new file mode 100644 index 00000000..e69de29b diff --git a/Code Compiler/input/code.txt b/Code Compiler/input/code.txt new file mode 100644 index 00000000..94c67a25 --- /dev/null +++ b/Code Compiler/input/code.txt @@ -0,0 +1,31 @@ +public class FindGreatestNumber { + public static void main(String[] args) { + // Sample array + int[] numbers = {10, 5, 8, 20, 15}; + + // Find the greatest number + int greatestNumber = findGreatestNumber(numbers); + + // Print the result + System.out.println("The greatest number is: " + greatestNumber); + } + + // Method to find the greatest number in an array + public static int findGreatestNumber(int[] arr) { + if (arr == null || arr.length == 0) { + throw new IllegalArgumentException("Array is empty or null"); + } + + // Assume the first element is the greatest + int greatest = arr[0]; + + // Iterate through the array to find the greatest number + for (int i = 1; i < arr.length; i++) { + if (arr[i] > greatest) { + greatest = arr[i]; + } + } + + return greatest; + } +} \ No newline at end of file diff --git a/Code Compiler/input/input.txt b/Code Compiler/input/input.txt new file mode 100644 index 00000000..e69de29b diff --git a/Code Compiler/input/language_list.txt b/Code Compiler/input/language_list.txt new file mode 100644 index 00000000..1ef99e1f --- /dev/null +++ b/Code Compiler/input/language_list.txt @@ -0,0 +1,77 @@ +Ada +Algol 68 +AWK +Bash Shell +BC +Befunge +Blockly +Brainf**k +C +C-99 +CLISP +Clojure +COBOL +CoffeeScript +C++ +C++ 14 +C++ 17 +C# +D +Dart +Elixir +Erlang +Factor +Falcon +Fantom +FASM +Forth +Fortran +FREE BASIC +F# +Assembler - GCC +GO Lang +Groovy +Hack +Haskell +Haxe +Icon +Intercal +Java +JBang +J Language +Kotlin +LOLCODE +Lua +OZ Mozart +Assembler - NASM +Nemerle +Nim +NodeJS +Objective C +Ocaml +Octave +Pascal +Perl +PHP +Picolisp +Pike +Prolog +Python 2 +Python 3 +R Language +Racket +Rhino JS +Ruby +RUST +Scala +Scheme +SmallTalk +SpiderMonkey +SQL +Swift +TCL +Unlambda +VB.Net +VERILOG +Whitespace +YaBasic diff --git a/Code Compiler/requirements.txt b/Code Compiler/requirements.txt new file mode 100644 index 00000000..d44fe443 --- /dev/null +++ b/Code Compiler/requirements.txt @@ -0,0 +1,2 @@ +requests +python-dotenv \ No newline at end of file diff --git a/Code Compiler/src/list_languages.py b/Code Compiler/src/list_languages.py new file mode 100644 index 00000000..87a8179e --- /dev/null +++ b/Code Compiler/src/list_languages.py @@ -0,0 +1,62 @@ +import requests +import os +import logging +from dotenv import load_dotenv + +# Configure logging + +logging.basicConfig(filename='bin/logfile.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', filemode='w') + + +load_dotenv() + + +# Get API Key from environment path + +api_key = os.getenv("API_KEY") + + +# GET language list from Online Code Compiler API using requests library + +def get_language(api_key): + + url = os.getenv("LANGUAGE_LIST_URL") + + host = os.getenv("HOST") + + headers = { + "X-RapidAPI-Key" : api_key, + "X-RapidAPI-Host" : host + } + + try: + response = requests.get(url=url, headers=headers) + response.raise_for_status() # Raise an HTTPError for bad responses + + data = response.json() + logging.info("Successfully fetched language data.") + return data + + except requests.exceptions.RequestException as e: + logging.error(f"Error making the request: {e}") + return None + + except Exception as e: + logging.error(f"An unexpected error occurred: {e}") + return None + + +# Get the language details in JSON list and define the path to dump the language list + +language_extractor = get_language(api_key) + +file_path = "input/language_list.txt" + + +# Truncate the file_path if it exists or create a new one and Write all the Language names from language_extractor + +with open(file_path, mode='w') as file: + + for language_detail in language_extractor: + file.write(language_detail['name']+'\n') + logging.info(f"Language '{language_detail['name']}' written to file.") \ No newline at end of file diff --git a/Code Compiler/src/main.py b/Code Compiler/src/main.py new file mode 100644 index 00000000..af724099 --- /dev/null +++ b/Code Compiler/src/main.py @@ -0,0 +1,138 @@ +import requests +import os +import logging +from dotenv import load_dotenv + +# Configure logging + +logging.basicConfig(filename='bin/logfile.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', filemode='w') + + +load_dotenv() + + +# Get API Key from environment path + +api_key = os.getenv("API_KEY") + + +# GET language list from Online Code Compiler API using requests library + +def get_language(api_key): + + url = os.getenv("LANGUAGE_LIST_URL") + + host = os.getenv("HOST") + + headers = { + "X-RapidAPI-Key" : api_key, + "X-RapidAPI-Host" : host + } + + try: + response = requests.get(url=url, headers=headers) + response.raise_for_status() # Raise an HTTPError for bad responses + + data = response.json() + logging.info("Successfully fetched language data.") + return data + + except requests.exceptions.RequestException as e: + logging.error(f"Error making the request: {e}") + return None + + except Exception as e: + logging.error(f"An unexpected error occurred: {e}") + return None + + +# Compile the code by sending POST request to Online Code Compiler API + +def compile_code(language_id, api_key): + + # Grab the User input from input.txt and read it. + + input_path = "input/input.txt" + + with open(input_path, mode='r') as file: + user_input = file.read() + + + # Grab the user code from code.txt file + + code_path = "input/code.txt" + + with open(code_path, mode='r') as file: + code = file.read() + + + # Grab the host and url from Environment file + + host = os.getenv("HOST") + url = os.getenv("COMPILE_CODE_URL") + + + # Define the headers for the api call + + headers = { + "content-type": "application/json", + "X-RapidAPI-Key": api_key, + "X-RapidAPI-Host": host + } + + + # Define the body for the api call + + payload = { + "language": language_id, + "version": "latest", + "code": code, + "input": user_input + } + + + try: + # Hit the API to compile the code + response = requests.post(url=url, json=payload, headers=headers) + response.raise_for_status() # Raise an HTTPError for bad responses + + data = response.json() + logging.info("Successfully compiled the code.") + return data + + except requests.exceptions.RequestException as e: + logging.error(f"Error making the compile request: {e}") + return None + + except Exception as e: + logging.error(f"An unexpected error occurred during compilation: {e}") + return None + + +# Get the language details in JSON list and get the language_id from User input of language name. Return an exception if it doesn't exist. + +language_extractor = get_language(api_key) + +language_name = input("Enter your choice of language. You can refer to language_list.txt in input folder for reference : ") + +language_id = None # Initialize language_id to None + +for language_detail in language_extractor: + if language_detail['name'].lower() == language_name.lower(): + language_id = language_detail['id'] + break + +else: + # This block is executed when the loop completes without finding a match + error_message = f"Language '{language_name}' not found in the language list. Available languages are: {[lang['name'] for lang in language_extractor]}" + logging.error(error_message) + raise ValueError(error_message) + + +# Compile the code and write the result into /bin in output.txt + +output = compile_code(language_id, api_key) + +with open("bin/output.txt", mode='w') as file: + file.write(output['output']) + logging.info("Output written to bin/output.txt.") \ No newline at end of file From 04ccf168a4e0494e3806f03c9f6d426f0079c68a Mon Sep 17 00:00:00 2001 From: Indrajeet Mishra Date: Thu, 7 Dec 2023 17:50:35 +0530 Subject: [PATCH 2/3] Added Environment Files --- Code Compiler/.gitignore | 160 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 Code Compiler/.gitignore diff --git a/Code Compiler/.gitignore b/Code Compiler/.gitignore new file mode 100644 index 00000000..68bc17f9 --- /dev/null +++ b/Code Compiler/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ From 7e13f1059fc4bcc9f96ed8e82707e7baa328062c Mon Sep 17 00:00:00 2001 From: Indrajeet Mishra Date: Mon, 3 Jun 2024 00:27:28 +0530 Subject: [PATCH 3/3] Delete .DS_Store --- .DS_Store | Bin 14340 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index fd4144d5242094627558be701fdc194c3e8ae8d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14340 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