├── testfiles ├── input │ ├── input.txt │ ├── input2.txt │ ├── input3.txt │ └── input4.txt ├── output │ ├── output6.txt │ ├── output8.txt │ ├── output3.txt │ ├── output5.txt │ ├── output2.txt │ ├── output.txt │ ├── output7.txt │ └── output4.txt ├── test_python.py ├── test_c_input.c ├── test_python_input.py ├── test_c.c ├── test_c++.cpp ├── test_java.java ├── test_c++_input.cpp └── test_java_input.java ├── MANIFEST.in ├── _config.yml ├── requirements.txt ├── coderunner ├── __init__.py └── coderunner.py ├── CONTRIBUTING.md ├── .readthedocs.yml ├── docs ├── installation.md ├── about.md ├── judge0.md ├── changelog.md ├── index.md └── usage.md ├── .github ├── ISSUE_TEMPLATE │ ├── ---say-thank-you.md │ ├── ---feature-request.md │ └── ----bug-report.md └── FUNDING.yml ├── mkdocs.yml ├── .travis.yml ├── demo.py ├── ppp ├── LICENSE ├── setup.py ├── .gitignore ├── CHANGELOG.md ├── README.md └── tests.py /testfiles/input/input.txt: -------------------------------------------------------------------------------- 1 | 232 -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGELOG.md -------------------------------------------------------------------------------- /testfiles/input/input2.txt: -------------------------------------------------------------------------------- 1 | 12 33 -------------------------------------------------------------------------------- /testfiles/input/input3.txt: -------------------------------------------------------------------------------- 1 | 121 -------------------------------------------------------------------------------- /testfiles/input/input4.txt: -------------------------------------------------------------------------------- 1 | Shruti 2 | 50000 -------------------------------------------------------------------------------- /testfiles/output/output6.txt: -------------------------------------------------------------------------------- 1 | Hello, World! -------------------------------------------------------------------------------- /testfiles/output/output8.txt: -------------------------------------------------------------------------------- 1 | Factorial = 362880 -------------------------------------------------------------------------------- /testfiles/output/output3.txt: -------------------------------------------------------------------------------- 1 | Sum of the numbers = 45 -------------------------------------------------------------------------------- /testfiles/output/output5.txt: -------------------------------------------------------------------------------- 1 | Not eligible for loan! -------------------------------------------------------------------------------- /testfiles/test_python.py: -------------------------------------------------------------------------------- 1 | print("Hello, World!") 2 | -------------------------------------------------------------------------------- /testfiles/output/output2.txt: -------------------------------------------------------------------------------- 1 | The number is a palindrome! -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate 2 | show_downloads: true 3 | -------------------------------------------------------------------------------- /testfiles/output/output.txt: -------------------------------------------------------------------------------- 1 | 1 4 9 16 2 | 25 36 49 3 | 64 81 4 | 100 -------------------------------------------------------------------------------- /testfiles/output/output7.txt: -------------------------------------------------------------------------------- 1 | 0 11 2 3 5 8 13 21 34 55 89 144 233 377 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | isort==4.3.21 2 | black 3 | flake8 4 | pylint 5 | python-dotenv 6 | -------------------------------------------------------------------------------- /testfiles/output/output4.txt: -------------------------------------------------------------------------------- 1 | The reverse of the number is: 121 2 | The number is a palindrome. -------------------------------------------------------------------------------- /coderunner/__init__.py: -------------------------------------------------------------------------------- 1 | """Import Run() for initializing program data""" 2 | from coderunner.coderunner import code 3 | -------------------------------------------------------------------------------- /testfiles/test_c_input.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | int a, b, c; 5 | 6 | scanf("%d%d", &a, &b); 7 | 8 | c = a + b; 9 | 10 | printf("Sum of the numbers = %d\n", c); 11 | 12 | return 0; 13 | } -------------------------------------------------------------------------------- /testfiles/test_python_input.py: -------------------------------------------------------------------------------- 1 | n = int(input()) 2 | temp = n 3 | rev = 0 4 | while n > 0: 5 | dig = n % 10 6 | rev = rev * 10 + dig 7 | n = n // 10 8 | if temp == rev: 9 | print("The number is a palindrome!") 10 | else: 11 | print("The number isn't a palindrome!") 12 | -------------------------------------------------------------------------------- /testfiles/test_c.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | int F1 = 0, F2 = 1, F3, n = 15; 5 | if(n == 2) printf ("%d %d ", F1, F2); 6 | else{ 7 | printf("%d %d", F1, F2); 8 | do{ 9 | F3 = F1 + F2; 10 | printf("%d ", F3); 11 | F1 = F2; 12 | F2 = F3; 13 | n--; 14 | }while(n > 2); 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to CodeRunner 2 | 3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: 4 | 5 | Make sure you follow below guidelines before contributing. 6 | 7 | 1. Raise an issue before sending any PR. 8 | 2. Make you changes to `feature` branch. 9 | 3. See if there is already an open PR for the same issue. 10 | -------------------------------------------------------------------------------- /testfiles/test_c++.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | // calculate factorial of a number 5 | long Fact(long); 6 | 7 | int main () { 8 | long x = 9, fact; 9 | fact = Fact (x); 10 | cout << "Factorial = " << fact; 11 | 12 | return 0; 13 | } 14 | 15 | long Fact (long a) { 16 | if (a == 0) return 1; 17 | else return a * Fact (a - 1); 18 | } -------------------------------------------------------------------------------- /testfiles/test_java.java: -------------------------------------------------------------------------------- 1 | import static java.lang.Math.pow; 2 | 3 | // program to print a given pattern 4 | 5 | class Main { 6 | public static void main (String[] args) { 7 | int p; 8 | for (int i = 1; i <= 10; i++) { 9 | p = (int) (pow (i, 2)); 10 | System.out.print (p + " "); 11 | if (i == 4 || i == 7 || i == 9) System.out.println (); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation with MkDocs 9 | mkdocs: 10 | configuration: mkdocs.yml 11 | fail_on_warning: false 12 | 13 | # Optionally build your docs in additional formats such as PDF and ePub 14 | formats: all -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | Installing coderunner is pretty simple, just run 4 | 5 | `pip install coderunner` 6 | 7 | Install a specific verison 8 | 9 | `pip install coderunner==0.4` 10 | 11 | or directly from GitHub if you cannot wait to test new features 12 | 13 | `pip install git+https://github.com/codeclassroom/CodeRunner.git` 14 | 15 | If you have already installed it and want to update 16 | 17 | `pip install --upgrade coderunner` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---say-thank-you.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F49F Say thank you" 3 | about: Just say thanks if you liked CodeRunner 4 | title: '' 5 | labels: 'thanks' 6 | assignees: '' 7 | 8 | --- 9 | 10 | if you liked **CodeRunner** - please let us know. We'd love to hear from you! 11 | 12 | You can help me in any way possible 13 | 14 | - [ ] Give the repository a star ⭐️ 15 | - [ ] Help out with issues 16 | - [ ] Share CodeRunner with others 17 | - [ ] Support me on [Patreon](https://www.patreon.com/bePatron?u=18082750) 18 | 19 | Thank you! 💐 20 | -------------------------------------------------------------------------------- /testfiles/test_c++_input.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int main(){ 4 | int n, num, digit, rev = 0; 5 | cin >> num; 6 | n = num; 7 | do 8 | { 9 | digit = num % 10; 10 | rev = (rev * 10) + digit; 11 | num = num / 10; 12 | } while (num != 0); 13 | cout << "The reverse of the number is: " << rev << endl; 14 | if (n == rev) 15 | cout << "The number is a palindrome."; 16 | else 17 | cout << "The number is not a palindrome."; 18 | return 0; 19 | } -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: CodeRunner 2 | site_url: https://codeclassroom.github.io/CodeRunner/ 3 | repo_url: https://github.com/codeclassroom/CodeRunner 4 | site_author: Bhupesh Varshney 5 | site_description: CodeRunner v1.0 Documentation 6 | copyright: © 2020, Bhupesh Varshney 7 | nav: 8 | - Documentation: index.md 9 | - Installation: installation.md 10 | - Usage: usage.md 11 | - Judge0: judge0.md 12 | - Changelog: changelog.md 13 | - About: about.md 14 | theme: readthedocs 15 | markdown_extensions: 16 | - toc: 17 | permalink: "#" -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | - "3.7" 5 | - "3.8" 6 | 7 | install: 8 | - pip install -r requirements.txt 9 | - pip install codecov 10 | script: 11 | - python tests.py 12 | - coverage run tests.py 13 | - isort --check-only --recursive coderunner 14 | - black --check --diff coderunner 15 | - flake8 coderunner --max-line-length=88 --ignore=F401 16 | - pylint coderunner --disable=bad-continuation,invalid-name,too-many-instance-attributes,too-many-arguments,attribute-defined-outside-init,no-self-use 17 | after_success: 18 | - codecov 19 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | from coderunner import coderunner 2 | import os 3 | 4 | from dotenv import load_dotenv 5 | load_dotenv() 6 | 7 | source_code = "testfiles/" + "test_python_input.py" 8 | language = "Python3" 9 | output = "testfiles/output/" + "output2.txt" 10 | Input = "testfiles/input/" + "input.txt" 11 | 12 | API_KEY = os.environ["API_KEY"] 13 | 14 | r = coderunner.code(source_code, language, output, Input) 15 | 16 | # Necessary step to initialize API keys & URL 17 | r.api(key=API_KEY) 18 | 19 | # run the code 20 | r.run() 21 | 22 | print("Running r :") 23 | print("Status : " + r.getStatus()) 24 | print("Output : " + r.getOutput()) 25 | -------------------------------------------------------------------------------- /docs/about.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | coderunner was built by : 4 | 5 | 👥 **Bhupesh Varshney** 6 | 7 | - Twitter: [@bhupeshimself](https://twitter.com/bhupeshimself) 8 | - DEV: [bhupesh](https://dev.to/bhupesh) 9 | - GitHub: [Bhupesh-V](https://github.com/Bhupesh-V) 10 | 11 | ## 📝 License 12 | 13 | This project is licensed under the MIT License. See the [LICENSE](https://github.com/codeclassroom/CodeRunner/blob/master/LICENSE) file for details. 14 | 15 | ## 👋 Contributing 16 | 17 | Please read the [CONTRIBUTING](https://github.com/codeclassroom/CodeRunner/blob/master/CONTRIBUTING.md) guidelines for the process of submitting pull requests to us. -------------------------------------------------------------------------------- /docs/judge0.md: -------------------------------------------------------------------------------- 1 | # [judge0](https://judge0.com/) 2 | 3 | CodeRunner is powered by Judge0 api.
4 | 5 | ### [API Docs](https://api.judge0.com/) 6 | ### [GItHub Repository](https://github.com/judge0/api) 7 | 8 | 9 | The following api parameters are set default by coderunner: 10 | ```python 11 | 12 | { 13 | "cpu_time_limit": "2", 14 | "cpu_extra_time": "0.5", 15 | "wall_time_limit": "5", 16 | "memory_limit": "128000", 17 | "stack_limit": "64000", 18 | "max_processes_and_or_threads": "30", 19 | "enable_per_process_and_thread_time_limit": "false", 20 | "enable_per_process_and_thread_memory_limit": "true", 21 | "max_file_size": "1024", 22 | } 23 | 24 | ``` -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: bhupesh 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /testfiles/test_java_input.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | class Loan extends Exception { 3 | String name; 4 | double salary; 5 | void getInfo () { 6 | Scanner input = new Scanner (System.in); 7 | name = input.nextLine (); 8 | salary = input.nextDouble (); 9 | } 10 | void checkEligibility () throws Loan { 11 | if (salary < 70000) throw new Loan (); 12 | else System.out.println (name + " is eligible for loan!"); 13 | } 14 | public String toString () { 15 | return "Not eligible for loan!"; 16 | } 17 | } 18 | class Main { 19 | public static void main(String[] args) { 20 | Loan person = new Loan (); 21 | person.getInfo (); 22 | try { 23 | person.checkEligibility (); 24 | } 25 | catch (Loan l) { 26 | System.out.println (l); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature request" 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /ppp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Shell Script to Publish a Python Package 4 | find_setup_py(){ 5 | setupfile="setup.py" 6 | if [ -f "$setupfile" ] 7 | then 8 | return 9 | else 10 | echo -e "\nERROR : $setupfile Not Found." 11 | exit 12 | fi 13 | } 14 | 15 | remove_old_dist(){ 16 | echo -e "\033[92;1mRemoving Old Distributions ... \n\033[0m" 17 | rm -r dist/ 18 | rm -r build/ 19 | ls | grep "egg-info$" | xargs rm -r 20 | } 21 | 22 | create_new_dist(){ 23 | echo -e "\033[92;1mGenerating new Distributions ... \n\033[0m" 24 | python3 setup.py sdist bdist_wheel 25 | } 26 | 27 | run_twine(){ 28 | echo -e "\033[92;1m\nUploading Package ... \n\033[0m" 29 | twine upload dist/* 30 | } 31 | 32 | find_setup_py 33 | remove_old_dist 34 | create_new_dist 35 | run_twine -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/----bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug report" 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Python Version [e.g 3.6] 29 | - CodeRunner version [e.g 0.4] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Bhupesh Varshney 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name="coderunner", 8 | version="1.0", 9 | license="MIT", 10 | author="Bhupesh Varshney", 11 | author_email="varshneybhupesh@gmail.com", 12 | description="A judge for your programs, run and test your programs using python", 13 | keywords="judge0 coderunner judge0api codeclassroom", 14 | long_description=long_description, 15 | long_description_content_type="text/markdown", 16 | url="https://codeclassroom.github.io/CodeRunner/", 17 | project_urls={ 18 | "Documentation": "https://coderunner.readthedocs.io/en/latest/", 19 | "Source Code": "https://github.com/codeclassroom/CodeRunner", 20 | "Funding": "https://www.patreon.com/bePatron?u=18082750", 21 | "Say Thanks!": "https://github.com/codeclassroom/CodeRunner/issues/new?assignees=&labels=&template=---say-thank-you.md&title=", 22 | "Tracker": "https://github.com/codeclassroom/CodeRunner/issues", 23 | }, 24 | packages=setuptools.find_packages(), 25 | classifiers=[ 26 | "Programming Language :: Python :: 3", 27 | "Programming Language :: Python :: 3.6", 28 | "Programming Language :: Python :: 3.7", 29 | "Programming Language :: Python :: 3.8", 30 | "Programming Language :: Python :: 3 :: Only", 31 | "License :: OSI Approved :: MIT License", 32 | "Topic :: Education", 33 | "Topic :: Education", 34 | "Topic :: Software Development", 35 | "Topic :: Software Development :: Libraries", 36 | "Topic :: Software Development :: Libraries :: Python Modules", 37 | "Operating System :: OS Independent", 38 | ], 39 | python_requires=">=3.6", 40 | ) 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/python 3 | # Edit at https://www.gitignore.io/?templates=python 4 | 5 | ### Python ### 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | wheels/ 28 | pip-wheel-metadata/ 29 | share/python-wheels/ 30 | *.egg-info/ 31 | .installed.cfg 32 | *.egg 33 | MANIFEST 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .nox/ 49 | .coverage 50 | .coverage.* 51 | .cache 52 | nosetests.xml 53 | coverage.xml 54 | *.cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | local_settings.py 65 | db.sqlite3 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | docs/_static 77 | docs/_templates 78 | 79 | # PyBuilder 80 | target/ 81 | 82 | # Jupyter Notebook 83 | .ipynb_checkpoints 84 | 85 | # IPython 86 | profile_default/ 87 | ipython_config.py 88 | 89 | # pyenv 90 | .python-version 91 | 92 | # pipenv 93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 95 | # having no cross-platform support, pipenv may install dependencies that don’t work, or not 96 | # install all needed dependencies. 97 | #Pipfile.lock 98 | 99 | # celery beat schedule file 100 | celerybeat-schedule 101 | 102 | # SageMath parsed files 103 | *.sage.py 104 | 105 | # Environments 106 | .env 107 | .venv 108 | env/ 109 | venv/ 110 | ENV/ 111 | env.bak/ 112 | venv.bak/ 113 | 114 | # Spyder project settings 115 | .spyderproject 116 | .spyproject 117 | 118 | # Rope project settings 119 | .ropeproject 120 | 121 | # mkdocs documentation 122 | /site 123 | 124 | # mypy 125 | .mypy_cache/ 126 | .dmypy.json 127 | dmypy.json 128 | 129 | # Pyre type checker 130 | .pyre/ 131 | 132 | # End of https://www.gitignore.io/api/python 133 | 134 | # Custom 135 | sample.py 136 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## [1.0] - July 23 , 2020 6 | ⚠ **Major Update (Breaking Changes)** 7 | 8 | ### Added 9 | - Add API key authorizations 10 | - Custom API URL support 11 | 12 | ### Changed 13 | - Due to Judge0 API going [freemium](https://github.com/judge0/api/issues/171), the default API URL, [https://api.judge0.com] is no longer available. To use the API signup for a plan on [RapidAPI](https://rapidapi.com/hermanzdosilovic/api/judge0/pricing) & use the token to access the API through coderunner. 14 | 15 | 16 | ## [0.8] - May 27, 2020 17 | 18 | ### Fix 19 | - Fixed bug where compiling a Java program resulted in Compilation Error. 20 | 21 | 22 | ## [0.7] - Jan 19, 2020 23 | 24 | ### Changed 25 | - `code()` class now ignores `output`. i.e you can just provide source code & language to run a program. 26 | 27 | 28 | ## [0.6] - Jan 5, 2020 29 | 30 | ### Added 31 | 32 | - New optional argument, `number_of_runs` in `run()` method, use this to specify no.of times you want to run the code. Default is set to 1. 33 | - Ported NEW Languages. CodeRunner now supports all languages provided by Judge0. 34 | - `setFlags(options)` for setting options for the compiler (i.e. compiler flags). 35 | - `setArguments(arguments)` for setting Command line arguments for the program. 36 | 37 | ### Changed 38 | - Minor internal improvemets. 39 | 40 | 41 | ## [0.5] - Dec 20, 2019 42 | 43 | ### Added 44 | 45 | - New instance method - `run()`. 46 | - `run()` is now used to run the code i.e the code is submitted to Judge0 api using this method. 47 | - Support for *Bash 4.4*. 48 | 49 | ### Changed 50 | - Renamed Class `Run` to `code` for easier usage. 51 | - `getStatus()`, now only returns the status in comparison to earlier versions where it performed multiple tasks. 52 | This is effect fixes [#2](https://github.com/codeclassroom/CodeRunner/issues/2). 53 | 54 | ### Removed 55 | - `requests` as a dependency, Network requests are now 50% faster. 56 | 57 | 58 | ## [0.4] - Nov 11, 2019 59 | 60 | ### Added 61 | 62 | - `getSubmissionDate()`, `getExitCode` new methods. 63 | - Official Documentation. 64 | 65 | ### Changed 66 | 67 | - Class Run `init` - Now you can pass _source code_, _input_ and _output_ to program as strings (limited to file paths in prior versions). 68 | 69 | 70 | ## [0.3] - Nov 9, 2019 71 | 72 | ### Added 73 | 74 | - Removed redundant imports 75 | - Added Module/Class docstrings for documentation 76 | - Formatted Code 77 | 78 | 79 | ## [0.2] - Oct 31, 2019 80 | 81 | ### Changed 82 | 83 | - Fix import requests problem. 84 | 85 | 86 | ## [0.1] - Oct 30, 2019 87 | - Initial Release -------------------------------------------------------------------------------- /docs/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## [1.0] - July 23 , 2020 6 | ⚠ **Major Update (Breaking Changes)** 7 | 8 | ### Added 9 | - Add API key authorizations 10 | - Custom API URL support 11 | 12 | ### Changed 13 | - Due to Judge0 API going [freemium](https://github.com/judge0/api/issues/171), the default API URL, [https://api.judge0.com] is no longer available. To use the API signup for a plan on [RapidAPI](https://rapidapi.com/hermanzdosilovic/api/judge0/pricing) & use the token to access the API through coderunner. 14 | 15 | 16 | ## [0.8] - May 27, 2020 17 | 18 | ### Fix 19 | - Fixed bug where compiling a Java program resulted in Compilation Error. 20 | 21 | 22 | ## [0.7] - Jan 19, 2020 23 | 24 | ### Changed 25 | - `code()` class now ignores `output`. i.e you can just provide source code & language to run a program. 26 | 27 | 28 | ## [0.6] - Jan 5, 2020 29 | 30 | ### Added 31 | 32 | - New optional argument, `number_of_runs` in `run()` method, use this to specify no.of times you want to run the code. Default is set to 1. 33 | - Ported NEW Languages. CodeRunner now supports all languages provided by Judge0. 34 | - `setFlags(options)` for setting options for the compiler (i.e. compiler flags). 35 | - `setArguments(arguments)` for setting Command line arguments for the program. 36 | 37 | ### Changed 38 | - Minor internal improvemets. 39 | 40 | 41 | ## [0.5] - Dec 20, 2019 42 | 43 | ### Added 44 | 45 | - New instance method - `run()`. 46 | - `run()` is now used to run the code i.e the code is submitted to Judge0 api using this method. 47 | - Support for *Bash 4.4*. 48 | 49 | ### Changed 50 | - Renamed Class `Run` to `code` for easier usage. 51 | - `getStatus()`, now only returns the status in comparison to earlier versions where it performed multiple tasks. 52 | This is effect fixes [#2](https://github.com/codeclassroom/CodeRunner/issues/2). 53 | 54 | ### Removed 55 | - `requests` as a dependency, Network requests are now 50% faster. 56 | 57 | 58 | ## [0.4] - Nov 11, 2019 59 | 60 | ### Added 61 | 62 | - `getSubmissionDate()`, `getExitCode` new methods. 63 | - Official Documentation. 64 | 65 | ### Changed 66 | 67 | - Class Run `init` - Now you can pass _source code_, _input_ and _output_ to program as strings (limited to file paths in prior versions). 68 | 69 | 70 | ## [0.3] - Nov 9, 2019 71 | 72 | ### Added 73 | 74 | - Removed redundant imports 75 | - Added Module/Class docstrings for documentation 76 | - Formatted Code 77 | 78 | 79 | ## [0.2] - Oct 31, 2019 80 | 81 | ### Changed 82 | 83 | - Fix import requests problem. 84 | 85 | 86 | ## [0.1] - Oct 30, 2019 87 | - Initial Release -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # CodeRunner 🏃 2 | 3 | > A judge 👨🏽‍⚖️ for your programs, run and test your programs using Python 4 | 5 | 6 | ![PyPI](https://img.shields.io/pypi/v/coderunner?color=blue) 7 | [![Build Status](https://travis-ci.org/codeclassroom/CodeRunner.svg?branch=master)](https://travis-ci.org/codeclassroom/CodeRunner) 8 | [![codecov](https://codecov.io/gh/codeclassroom/CodeRunner/branch/master/graph/badge.svg)](https://codecov.io/gh/codeclassroom/CodeRunner) 9 | ![PyPI - Format](https://img.shields.io/pypi/format/coderunner?color=orange) 10 | ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/coderunner) 11 | [![Documentation Status](https://readthedocs.org/projects/coderunner/badge/?version=latest)](https://coderunner.readthedocs.io/en/latest/?badge=latest) 12 | ![PyPI - Downloads](https://img.shields.io/pypi/dm/coderunner?color=blue) 13 | 14 | 15 | ## Installation 16 | 17 | Install using `pip` from PyPI 18 | 19 | ```bash 20 | pip install coderunner 21 | ``` 22 | 23 | or directly from GitHub if you cannot wait to test new features 24 | 25 | ```bash 26 | pip install git+https://github.com/codeclassroom/CodeRunner.git 27 | ``` 28 | 29 | ## Usage 30 | 31 | ```python 32 | 33 | from coderunner import coderunner 34 | import os 35 | 36 | from dotenv import load_dotenv 37 | load_dotenv() 38 | 39 | source_code = "testfiles/" + "test_python_input.py" 40 | language = "Python3" 41 | output = "testfiles/output/" + "output2.txt" 42 | Input = "testfiles/input/" + "input.txt" 43 | 44 | 45 | API_KEY = os.environ["API_KEY"] 46 | 47 | r = coderunner.code(source_code, language, output, Input) 48 | 49 | # Necessary step to initialize API keys & URL 50 | r.api(key=API_KEY) 51 | 52 | # run the code 53 | r.run() 54 | 55 | print("Running r :") 56 | print("Status : " + r.getStatus()) 57 | print("Output : " + r.getOutput()) 58 | ``` 59 | 60 | ## Documentation 61 | 62 | > [CodeRunner Documentation](https://coderunner.readthedocs.io/en/latest/) 63 | 64 | 65 | ## Development 66 | 67 | ##### Prerequisites 68 | - Python 3.6+ 69 | - virtualenv 70 | 71 | 1. Create virtual environment. 72 | ```bash 73 | virtualenv -p python3 venv && cd venv && source bin/activate 74 | ``` 75 | 2. Clone the repository. 76 | ```bash 77 | git https://github.com/codeclassroom/CodeRunner.git 78 | ``` 79 | 3. Install Dependencies. 80 | ```bash 81 | pip install -r requirements.txt 82 | ``` 83 | 4. Run tests. 84 | ```bash 85 | python tests.py 86 | ``` 87 | 5. Lint the project with 88 | ```bash 89 | flake8 coderunner --max-line-length=88 --ignore=F401 90 | black --check --diff coderunner 91 | ``` 92 | 93 | ## 📝 Changelog 94 | 95 | See the [CHANGELOG.md](CHANGELOG.md) file for details. 96 | 97 | 98 | ## Author 99 | 100 | 👥 **Bhupesh Varshney** 101 | 102 | - Twitter: [@bhupeshimself](https://twitter.com/bhupeshimself) 103 | - DEV: [bhupesh](https://dev.to/bhupesh) 104 | 105 | [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com) 106 | 107 | ## 📜 License 108 | 109 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 110 | 111 | ## 👋 Contributing 112 | 113 | Please read the [CONTRIBUTING](CONTRIBUTING.md) guidelines for the process of submitting pull requests to us. 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeRunner 🏃 2 | 3 | > A judge 👨🏽‍⚖️ for your programs, run and test your programs using Python 4 | 5 | 6 | ![PyPI](https://img.shields.io/pypi/v/coderunner?color=blue) 7 | [![Build Status](https://travis-ci.org/codeclassroom/CodeRunner.svg?branch=master)](https://travis-ci.org/codeclassroom/CodeRunner) 8 | [![codecov](https://codecov.io/gh/codeclassroom/CodeRunner/branch/master/graph/badge.svg)](https://codecov.io/gh/codeclassroom/CodeRunner) 9 | ![PyPI - Format](https://img.shields.io/pypi/format/coderunner?color=orange) 10 | ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/coderunner) 11 | [![Documentation Status](https://readthedocs.org/projects/coderunner/badge/?version=latest)](https://coderunner.readthedocs.io/en/latest/?badge=latest) 12 | ![PyPI - Downloads](https://img.shields.io/pypi/dm/coderunner?color=blue) 13 | 14 | 15 | ## Installation 16 | 17 | Install using `pip` from PyPI 18 | 19 | ```bash 20 | pip install coderunner 21 | ``` 22 | 23 | or directly from GitHub if you cannot wait to test new features 24 | 25 | ```bash 26 | pip install git+https://github.com/codeclassroom/CodeRunner.git 27 | ``` 28 | 29 | ## Usage 30 | 31 | ```python 32 | 33 | from coderunner import coderunner 34 | import os 35 | 36 | from dotenv import load_dotenv 37 | load_dotenv() 38 | 39 | source_code = "testfiles/" + "test_python_input.py" 40 | language = "Python3" 41 | output = "testfiles/output/" + "output2.txt" 42 | Input = "testfiles/input/" + "input.txt" 43 | 44 | 45 | API_KEY = os.environ["API_KEY"] 46 | 47 | r = coderunner.code(source_code, language, output, Input) 48 | 49 | # Necessary step to initialize API keys & URL 50 | r.api(key=API_KEY) 51 | 52 | # run the code 53 | r.run() 54 | 55 | print("Running r :") 56 | print("Status : " + r.getStatus()) 57 | print("Output : " + r.getOutput()) 58 | 59 | # See Documentation for more methods. 60 | ``` 61 | 62 | ## Documentation 63 | 64 | > [CodeRunner Documentation](https://coderunner.readthedocs.io/en/latest/) 65 | 66 | 67 | ## Development 68 | 69 | ##### Prerequisites 70 | - Python 3.6+ 71 | - virtualenv 72 | 73 | 1. Create virtual environment. 74 | ```bash 75 | virtualenv -p python3 venv && cd venv && source bin/activate 76 | ``` 77 | 2. Clone the repository. 78 | ```bash 79 | git https://github.com/codeclassroom/CodeRunner.git 80 | ``` 81 | 3. Install Dependencies. 82 | ```bash 83 | pip install -r requirements.txt 84 | ``` 85 | 4. Run tests. 86 | ```bash 87 | python tests.py 88 | ``` 89 | 5. Lint the project with 90 | ```bash 91 | flake8 coderunner --max-line-length=88 --ignore=F401 92 | black --check --diff coderunner 93 | ``` 94 | 95 | ## 📝 Changelog 96 | 97 | See the [CHANGELOG.md](CHANGELOG.md) file for details. 98 | 99 | ## :fire: Powered By 100 | **[Judge0 API](https://github.com/judge0/api) - Free, robust and scalable open-source online code execution system** 101 | 102 | ## Author 103 | 104 | 👥 **Bhupesh Varshney** 105 | 106 | - Twitter: [@bhupeshimself](https://twitter.com/bhupeshimself) 107 | - DEV: [bhupesh](https://dev.to/bhupesh) 108 | 109 | [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com) 110 | 111 | ## 📜 License 112 | 113 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 114 | 115 | ## 👋 Contributing 116 | 117 | Please read the [CONTRIBUTING](CONTRIBUTING.md) guidelines for the process of submitting pull requests to us. 118 | -------------------------------------------------------------------------------- /docs/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | coderunner provides the following class. 4 | 5 | ### code(source, lang, output, inp, path) 6 | 7 | * **Parameters(type)** : 8 | - source : The Source Code 9 | - lang : The Programming Language 10 | - output : Expected Output of the Program (optional). 11 | - inp : Standard Input to the program (optional). 12 | - path : specify mode of input. Set this to `False` if you are not using file paths (optional) 13 | 14 | **Demo**: 15 | ```python 16 | 17 | from coderunner.coderunner import code 18 | 19 | source_code = "path-to/test_python.py" 20 | language = "Python3" 21 | expected_output = "path-to/output.txt" 22 | standard_input = "path-to/input.txt" 23 | 24 | # use this if you have a standard input to Program 25 | r = code(source_code, language, expected_output, standard_input) 26 | 27 | # otherwise 28 | r = code(source_code, language, expected_output) 29 | 30 | # you can also ignore both fields 31 | r = code(source_code, language) 32 | 33 | # Use path=False if not using file paths 34 | r = code("Hello, World", language, "Hello, World", path=False) 35 | ``` 36 | 37 | See [demo.py](https://github.com/codeclassroom/CodeRunner/blob/master/demo.py) for a more descriptive usage. 38 | 39 | **Pointers ✏** 40 | 41 | - In a `Java` program the class name should always be ***`Main`***.
42 | - CodeRunner supports all languages provided by Judge0. See full list of supported languages [here](https://jsonpp.judge0.com/?https://api.judge0.com/languages). 43 | or you can use 44 | ```python 45 | print(r.languages) 46 | """ 47 | ['Assembly', 'Bash', 'Basic', 'C', 'C++', 'C#', 'Common Lisp', 'D', 'Elixir', 'Erlang', 'Executable', 'Fortran', 'Go', 'Haskell', 'Java', 'JavaScript', 'Lua', 'OCaml', 'Octave', 'Pascal', 'PHP', 'Plain Text', 'Prolog', 'Python2', 'Python3', 'Ruby', 'Rust', 'TypeScript'] 48 | """ 49 | ``` 50 | - Languages should be specified as string like "C++", "Java" etc. 51 | 52 | 53 | Methods available in class `code()`. 54 | 55 | ### api() 56 | 57 | Since v1.0, you need to provide a API Key & URL for using Judge0 through coderunner. 58 | 59 | Here is an example on how to do this. 60 | 61 | ```python 62 | from coderunner import coderunner 63 | import os 64 | from dotenv import load_dotenv 65 | 66 | load_dotenv() 67 | 68 | source_code = "testfiles/" + "test_python_input.py" 69 | language = "Python3" 70 | output = "testfiles/output/" + "output2.txt" 71 | Input = "testfiles/input/" + "input.txt" 72 | 73 | 74 | API_KEY = os.environ["API_KEY"] 75 | 76 | r = coderunner.code(source_code, language, output, Input) 77 | 78 | # Necessary step to initialize API keys & URL 79 | r.api(key=API_KEY) 80 | 81 | r.run() 82 | 83 | print("Run r :") 84 | print("Status : " + r.getStatus()) 85 | print("Output : " + r.getOutput()) 86 | ```` 87 | 88 | The default API URL is [https://judge0.p.rapidapi.com/]() 89 | 90 | ### 1. run() 91 | **Parameters(type)** : Number Of Runs (`int`), optional
92 | **Return Type** : None
93 | **Description**: Submits the program on Judge0's server.
94 | **Demo**: 95 | ```python 96 | 97 | # by default the program executes 1 time on server. 98 | r.run() 99 | 100 | # to execute program 2 times, use 101 | r.run(2) 102 | 103 | ``` 104 | 105 | ### 2. getStatus() 106 | 107 | **Parameters(type)** : None
108 | **Return Type** : `String`
109 | **Description**: Returns submission status.
110 | 111 | - List of Statuses : 112 | - In Queue 113 | - Processing 114 | - Accepted 115 | - Wrong Answer 116 | - Time Limit Exceeded 117 | - Compilation Error 118 | - Runtime Error (SIGSEGV) 119 | - Runtime Error (SIGXFSZ) 120 | - Runtime Error (SIGFPE) 121 | - Runtime Error (SIGABRT) 122 | - Runtime Error (NZEC) 123 | - Runtime Error (Other) 124 | - Internal Error 125 | - Exec Format Error 126 | 127 | **Demo**: 128 | ```python 129 | 130 | status = r.getStatus() 131 | # Accepted, Wrong Answet etc. 132 | ``` 133 | 134 | ### 3. getError() 135 | 136 | **Parameters(type)** : None
137 | **Return Type** : `String`
138 | **Description**: Returns any error occured during program execution. 139 | **Demo**: 140 | ```python 141 | 142 | error = r.getError() 143 | """ 144 | 'Error : File "main.py", line 2\n' 145 | ' print("Hello, " name)\n' 146 | ' ^\n' 147 | 'SyntaxError: invalid syntax\n' 148 | """ 149 | ``` 150 | 151 | ### 4. getOutput() 152 | 153 | **Parameters(type)** : None
154 | **Return Type** : `String`
155 | **Description**: Returns the standard output of the program.
156 | **Demo**: 157 | ```python 158 | 159 | stdout = r.getOutput() 160 | # 'Hello, World\n' 161 | ``` 162 | 163 | ### 5. getMemory() 164 | 165 | **Parameters(type)** : None
166 | **Return Type** : `String`
167 | **Description**: Returns the memory used by the program (in kilobytes).
168 | **Demo**: 169 | ```python 170 | 171 | memory = r.getMemory() 172 | # 3688 173 | ``` 174 | 175 | ### 6. getTime() 176 | 177 | **Parameters(type)** : `None`
178 | **Return Type** : `String`
179 | **Description**: Returns execution time of the program.
180 | **Demo**: 181 | ```python 182 | 183 | time_consumed = r.getTime() 184 | # 0.031 seconds 185 | ``` 186 | 187 | ### 7. getExitCode() 188 | 189 | **Parameters(type)** : None
190 | **Return Type** : `String`
191 | **Description**: Returns exit code of program.
192 | **Demo**: 193 | ```python 194 | 195 | exit_code = r.getExitCode() 196 | # 0 on Accepted and 1 on Run Time Error 197 | ``` 198 | 199 | ### 8. getSubmissionDate() 200 | 201 | **Parameters(type)** : None
202 | **Return Type** : `String`
203 | **Description**: Returns submission date/time of the program on Judge0's Server.
204 | **Demo**: 205 | ```python 206 | 207 | sub_date = r.getSubmissionDate() 208 | # 2019-11-11T13:27:15.909Z 209 | ``` 210 | 211 | ### 9. setFlags(options) 212 | 213 | **Parameters(type)** : Compiler flags (`String`)
214 | **Return Type** : `None`
215 | **Description**: Options for the compiler (i.e. compiler flags).
216 | **Demo**: 217 | ```python 218 | 219 | r.setFlags("-O2 -Wall") 220 | 221 | ``` 222 | 223 | ### 10. setArguments(arguments) 224 | 225 | **Parameter Type** : Command line arguments (`String`)
226 | **Return Type** : `None`
227 | **Description**: Command line arguments for the program.
228 | **Demo**: 229 | ```python 230 | 231 | r.setArguments() 232 | 233 | ``` 234 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from coderunner import coderunner 3 | from coderunner.coderunner import InvalidURL, ValueTooLargeError 4 | # # test for Java program 5 | 6 | # class TestRunA(unittest.TestCase): 7 | # def test_run(self): 8 | # source_code = "testfiles/" + "test_java.java" 9 | # language = "Java" 10 | # output = "testfiles/output/" + "output.txt" 11 | # r = coderunner.code(source_code, language, output) 12 | # r.api(key=API_KEY) 13 | # r.run() 14 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 15 | 16 | 17 | # # test for Java program with input 18 | 19 | 20 | # class TestRunB(unittest.TestCase): 21 | # def test_run(self): 22 | # source_code = "testfiles/" + "test_java_input.java" 23 | # language = "Java" 24 | # output = "testfiles/output/" + "output5.txt" 25 | # Input = "testfiles/input/" + "input4.txt" 26 | # r = coderunner.code(source_code, language, output, Input) 27 | # r.api(key=API_KEY) 28 | # r.run() 29 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 30 | 31 | 32 | # # test for Python3 program 33 | 34 | 35 | # class TestRunC(unittest.TestCase): 36 | # def test_run(self): 37 | # source_code = "testfiles/" + "test_python.py" 38 | # language = "Python3" 39 | # output = "testfiles/output/" + "output6.txt" 40 | # r = coderunner.code(source_code, language, output) 41 | # r.api(key=API_KEY) 42 | # r.run() 43 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 44 | 45 | 46 | # # test for Python3 program with input 47 | 48 | 49 | # class TestRunD(unittest.TestCase): 50 | # def test_run(self): 51 | # source_code = "testfiles/" + "test_python_input.py" 52 | # language = "Python3" 53 | # output = "testfiles/output/" + "output2.txt" 54 | # Input = "testfiles/input/" + "input.txt" 55 | # r = coderunner.code(source_code, language, output, Input) 56 | # r.api(key=API_KEY) 57 | # r.run() 58 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 59 | 60 | 61 | # # test for C program 62 | 63 | 64 | # class TestRunE(unittest.TestCase): 65 | # def test_run(self): 66 | # source_code = "testfiles/" + "test_c.c" 67 | # language = "C" 68 | # output = "testfiles/output/" + "output7.txt" 69 | # r = coderunner.code(source_code, language, output) 70 | # r.api(key=API_KEY) 71 | # r.run() 72 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 73 | 74 | 75 | # # test for C program with input 76 | 77 | 78 | # class TestRunF(unittest.TestCase): 79 | # def test_run(self): 80 | # source_code = "testfiles/" + "test_c_input.c" 81 | # language = "C" 82 | # output = "testfiles/output/" + "output3.txt" 83 | # Input = "testfiles/input/" + "input2.txt" 84 | # r = coderunner.code(source_code, language, output, Input) 85 | # r.api(key=API_KEY) 86 | # r.run() 87 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 88 | 89 | 90 | # # test for C++ program 91 | 92 | 93 | # class TestRunG(unittest.TestCase): 94 | # def test_run(self): 95 | # source_code = "testfiles/" + "test_c++.cpp" 96 | # language = "C++" 97 | # output = "testfiles/output/" + "output8.txt" 98 | # r = coderunner.code(source_code, language, output) 99 | # r.api(key=API_KEY) 100 | # r.run() 101 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 102 | 103 | 104 | # # test for C++ program with input 105 | 106 | 107 | # class TestRunH(unittest.TestCase): 108 | # def test_run(self): 109 | # source_code = "testfiles/" + "test_c++_input.cpp" 110 | # language = "C++" 111 | # output = "testfiles/output/" + "output4.txt" 112 | # Input = "testfiles/input/" + "input3.txt" 113 | # r = coderunner.code(source_code, language, output, Input) 114 | # r.api(key=API_KEY) 115 | # r.run() 116 | # self.assertEqual(r.getStatus(), "Accepted", "Something Wrong") 117 | 118 | 119 | # test to check ValueError exception 120 | 121 | 122 | class TestRunI(unittest.TestCase): 123 | def test_run(self): 124 | with self.assertRaises(ValueError): 125 | coderunner.code("Hello World", "fgbh", "Hello World", path=False) 126 | 127 | 128 | # test to check OSError exception 129 | 130 | 131 | class TestRunJ(unittest.TestCase): 132 | def test_run(self): 133 | with self.assertRaises(OSError): 134 | coderunner.code("Hello World", "C++", "Hello World") 135 | 136 | 137 | # test to check OSError exception 138 | 139 | 140 | class TestRunK(unittest.TestCase): 141 | def test_run(self): 142 | with self.assertRaises(OSError): 143 | coderunner.code("testfiles/" + "test_c++.cpp", "C++", "Hello World") 144 | 145 | 146 | # test to check OSError exception 147 | 148 | 149 | class TestRunL(unittest.TestCase): 150 | def test_run(self): 151 | with self.assertRaises(OSError): 152 | coderunner.code( 153 | "testfiles/" + "test_c++.cpp", 154 | "C++", 155 | "testfiles/output/" + "output4.txt", 156 | "my_input", 157 | ) 158 | 159 | 160 | # test to check Wrong Answer Status 161 | 162 | 163 | # class TestRunM(unittest.TestCase): 164 | # def test_run(self): 165 | # source_code = 'print("This will return Wrong Answer")' 166 | # language = "Python3" 167 | # output = "Wrong Answer" 168 | # r = coderunner.code(source_code, language, output, path=False) 169 | # r.api(key=API_KEY) 170 | # r.run() 171 | # self.assertEqual(r.getStatus(), "Wrong Answer", "Something Wrong") 172 | 173 | 174 | # test to check invalid API url 175 | class TestRunO(unittest.TestCase): 176 | def test_run(self): 177 | source_code = 'print("This will return Wrong Answer")' 178 | language = "Python3" 179 | output = "Wrong Answer" 180 | r = coderunner.code(source_code, language, output, path=False) 181 | with self.assertRaises(InvalidURL): 182 | r.api(key="ABCHE", url="ghthth") 183 | 184 | 185 | # test to check ValueTooLargeError for Flags 186 | class TestRunP(unittest.TestCase): 187 | def test_run(self): 188 | source_code = 'print("This will return Wrong Answer")' 189 | language = "Python3" 190 | output = "Wrong Answer" 191 | r = coderunner.code(source_code, language, output, path=False) 192 | with self.assertRaises(ValueTooLargeError): 193 | r.setFlags("qw"*70) 194 | 195 | 196 | # test to check ValueTooLargeError for Arguments 197 | class TestRunQ(unittest.TestCase): 198 | def test_run(self): 199 | source_code = 'print("This will return Wrong Answer")' 200 | language = "Python3" 201 | output = "Wrong Answer" 202 | r = coderunner.code(source_code, language, output, path=False) 203 | with self.assertRaises(ValueTooLargeError): 204 | r.setArguments("qw"*70) 205 | 206 | 207 | if __name__ == "__main__": 208 | unittest.main() 209 | -------------------------------------------------------------------------------- /coderunner/coderunner.py: -------------------------------------------------------------------------------- 1 | """ 2 | coderunner.py 3 | ==================================== 4 | The core module of CodeRunner 5 | """ 6 | import json 7 | import os 8 | import urllib.parse 9 | import urllib.request 10 | 11 | # language IDs on judge0, see Documentation 12 | languages = { 13 | "Assembly": 45, 14 | "Bash": 46, 15 | "Basic": 47, 16 | "C": 50, 17 | "C++": 54, 18 | "C#": 51, 19 | "Common Lisp": 55, 20 | "D": 56, 21 | "Elixir": 57, 22 | "Erlang": 58, 23 | "Executable": 44, 24 | "Fortran": 59, 25 | "Go": 60, 26 | "Haskell": 61, 27 | "Java": 62, 28 | "JavaScript": 63, 29 | "Lua": 64, 30 | "OCaml": 65, 31 | "Octave": 66, 32 | "Pascal": 67, 33 | "PHP": 68, 34 | "Plain Text": 43, 35 | "Prolog": 69, 36 | "Python2": 70, 37 | "Python3": 71, 38 | "Ruby": 72, 39 | "Rust": 73, 40 | "TypeScript": 74, 41 | } 42 | 43 | api_params = { 44 | "cpu_time_limit": "2", 45 | "cpu_extra_time": "0.5", 46 | "wall_time_limit": "5", 47 | "memory_limit": "128000", 48 | "stack_limit": "64000", 49 | "max_processes_and_or_threads": "30", 50 | "enable_per_process_and_thread_time_limit": "false", 51 | "enable_per_process_and_thread_memory_limit": "false", 52 | "max_file_size": "1024", 53 | } 54 | 55 | HEADERS = {"x-rapidapi-host": "judge0.p.rapidapi.com", "useQueryString": True} 56 | 57 | FIELDS = "?fields=stdout,memory,time,status,stderr,exit_code,created_at" 58 | 59 | 60 | class ValueTooLargeError(Exception): 61 | """Raised when the input value is too large""" 62 | 63 | 64 | class InvalidURL(Exception): 65 | """Raise when api_url is invalid""" 66 | 67 | 68 | class code: 69 | """ 70 | Args: 71 | - Source Code 72 | - Language 73 | - Expected Output 74 | - Standard Input (Optional) 75 | - path (optional) 76 | """ 77 | 78 | def __init__( 79 | self, 80 | source: str, 81 | lang: str, 82 | output: str = None, 83 | inp: str = None, 84 | path: bool = True, 85 | ): 86 | 87 | self.path = path 88 | if lang not in languages: 89 | raise ValueError(f"{lang} is not a supported language {languages.keys()}") 90 | self.lang = lang 91 | self.language_id = languages[lang] 92 | self.__response = None 93 | self.__memory = None 94 | self.__time = None 95 | self.__stdout = None 96 | self.languages = list(languages.keys()) 97 | 98 | if self.path: 99 | if not os.path.exists(source): 100 | raise OSError(f"{source} is not a valid file path") 101 | self.source = source 102 | 103 | if output is not None and not os.path.exists(output): 104 | raise OSError(f"{output} is not a valid file path") 105 | self.output = output 106 | 107 | if inp is not None and not os.path.exists(inp): 108 | raise OSError(f"{inp} is not a valid file path") 109 | self.inp = inp 110 | self.source = source 111 | self.output = output 112 | self.inp = inp 113 | 114 | def __readCode(self): 115 | try: 116 | with open(self.source, "r") as program_file: 117 | data = program_file.read() 118 | return data 119 | except FileNotFoundError as e: 120 | raise e 121 | 122 | def __readExpectedOutput(self): 123 | try: 124 | with open(self.output, "r") as exp_out: 125 | data = exp_out.read() 126 | return data 127 | except FileNotFoundError as e: 128 | raise e 129 | 130 | def __readStandardInput(self): 131 | try: 132 | with open(self.inp, "r") as standard_input: 133 | data = standard_input.read() 134 | return data 135 | except FileNotFoundError as e: 136 | raise e 137 | 138 | def __readStatus(self, token: str): 139 | """ 140 | Check Submission Status 141 | """ 142 | while True: 143 | req = urllib.request.Request( 144 | f'{self.API_URL}submissions/{token["token"]}{FIELDS}', headers=HEADERS 145 | ) 146 | with urllib.request.urlopen(req) as response: 147 | req = response.read() 148 | 149 | self.__response = json.loads(req.decode("utf-8")) 150 | self.__memory = self.__response["memory"] 151 | self.__time = self.__response["time"] 152 | status = self.__response["status"]["description"] 153 | if status not in ("Processing", "In Queue"): 154 | break 155 | 156 | if status == "Accepted": 157 | self.__stdout = self.__response["stdout"] 158 | return status 159 | return self.__response["status"]["description"] 160 | 161 | def __submit(self): 162 | if self.inp is not None: 163 | api_params["stdin"] = self.inp 164 | if self.output is not None: 165 | api_params["expected_output"] = self.output 166 | 167 | api_params["language_id"] = self.language_id 168 | api_params["source_code"] = self.source 169 | 170 | post_data = urllib.parse.urlencode(api_params).encode("ascii") 171 | req = urllib.request.Request( 172 | f"{self.API_URL}submissions/", post_data, headers=HEADERS 173 | ) 174 | with urllib.request.urlopen(req) as response: 175 | req = response.read() 176 | token = json.loads(req.decode("utf-8")) 177 | 178 | return token 179 | 180 | def api(self, key: str, url: str = None): 181 | """Setup API url and key""" 182 | HEADERS["x-rapidapi-key"] = key 183 | self.API_KEY = key 184 | if url is None: 185 | self.API_URL = "https://judge0.p.rapidapi.com/" 186 | else: 187 | user_api_url = urllib.parse.urlparse(url) 188 | if user_api_url.scheme and user_api_url.netloc: 189 | self.API_URL = url 190 | else: 191 | raise InvalidURL("Invalid API URL") 192 | 193 | def getSubmissionDate(self): 194 | """Submission date/time of program""" 195 | return self.__response["created_at"] 196 | 197 | def getExitCode(self): 198 | """Exitcode of program (0 or 1)""" 199 | return self.__response["exit_code"] 200 | 201 | def getOutput(self): 202 | """Standard output of the program""" 203 | return self.__stdout 204 | 205 | def getMemory(self): 206 | """Memory used by the program""" 207 | return self.__memory 208 | 209 | def getError(self): 210 | """Error occured during execution of program""" 211 | if self.__response["stderr"] != "": 212 | return self.__response["stderr"] 213 | return None 214 | 215 | def getTime(self): 216 | """Execution time of program""" 217 | return self.__time 218 | 219 | def setFlags(self, options: str): 220 | """Options for the compiler (i.e. compiler flags)""" 221 | if len(options) > 128: 222 | raise ValueTooLargeError("Maximum 128 characters allowed") 223 | api_params["compiler_options"] = options 224 | 225 | def setArguments(self, arguments: str): 226 | """Command line arguments for the program""" 227 | if len(arguments) > 128: 228 | raise ValueTooLargeError("Maximum 128 characters allowed") 229 | api_params["command_line_arguments"] = arguments 230 | 231 | def run(self, number_of_runs: int = 1): 232 | """Submit the source code on judge0's server & return status""" 233 | api_params["number_of_runs"] = number_of_runs 234 | 235 | if os.path.exists(self.source): 236 | if self.path: 237 | if self.inp is not None: 238 | self.inp = self.__readStandardInput() 239 | if self.output is not None: 240 | self.output = self.__readExpectedOutput() 241 | self.source = self.__readCode() 242 | 243 | token = self.__submit() 244 | self.__token = token 245 | 246 | def getStatus(self): 247 | """Submission status""" 248 | status = self.__readStatus(self.__token) 249 | 250 | return status 251 | --------------------------------------------------------------------------------