pistonapp.py

← Back to explorer
src/pistonpy/pistonapp.py
# Coding=UTF8
# !python
# !/usr/bin/env python3
import requests, json
from typing import Optional
from .exceptions import CodeNotFound, LanguageNotFound, CodeFormatNotFound, NotAFile, MultipleLanguagesFound
from .models import GetOutput, Extensions

__all__ = ('PistonApp',)

class PistonApp():
    """The class to use while working with other code or creating applications or discord bots."""

    def __init__(self, embed: str = 'app') -> None:
        """
        :param embed: app - work as integrated.
            Default is set to app
        """
        self.embed = embed
        self._endpoint = "https://emkc.org/api/v2/piston"

    def __repr__(self) -> str:
        return "<pistonpy.PistonApp>"

    @property
    def raw(self) -> dict:
        url = self._endpoint + "/runtimes"
        response = requests.request("GET", url)
        data = response.json()
        return data


    @property
    def languages(self) -> dict:
        url = self._endpoint + "/runtimes"
        response = requests.request("GET", url)
        data = response.json()
        language = []
        version = []

        for i in data:
            language.append(i['language'])
            version.append(i['version'])

        dic = dict(zip(language, version))
        return dic

    @property
    def aliases(self) -> dict:
        url = self._endpoint + "/runtimes"
        response = requests.request("GET", url)
        data = response.json()
        language = []
        alias = []

        for i in data:
            language.append(i['language'])
            alias.append(i['aliases'])

        dic = dict(zip(language, alias))
        return dic

    def run(
        self,
        language: str,
        version: str = "*",
        files: Optional[list] = [],
        code: Optional[str] = "",
        args: Optional[list] = [],
        input: Optional[str] = "",
        compile_timeout: Optional[int] = 10_000,
        run_timeout: Optional[int] = 3_000,
        compile_memory_limit: Optional[int] = -1,
        run_memory_limit: Optional[int] = -1,
    ) -> list:
        """Main Code Execution"""

        main_code = ''
        formattedfiles = [i.split('.')[0] for i in files]
        file_extensions = [i.split('.')[1] for i in files]
        bool, message = Extensions(language=language, payload=files).check_files

        if files:
            if bool:
                pass
            else:
                raise MultipleLanguagesFound(f"Files of multiple languages found: {message}")

        if not code and not files:
            print('running CodeNotFound')
            raise CodeNotFound("No code provided to run")

        elif code and files:
            print('running CodeFormatNotFound')
            raise CodeFormatNotFound("Cannot choose whether to run raw code or code from file/s")

        else:
            if code:

                main_code = [{"name" : '', "content" : code}]

            if files and len(files) == 1:
                files_content = []

                for file in files:
                    try:
                        with open(file, mode="r") as f:
                            content = f.read()
                            files_content.append({"name": file, "content": content})
                    except FileNotFoundError:
                        raise FileNotFoundError(f"{file} not found.")
                main_code = files_content

            if files and 1 < len(files) < 5 and 'py' in file_extensions:
                files_content = []

                for file in files:
                    files_content.append({"name" : "main.py", "content" : f"import {', '.join(formattedfiles)}"})
                    try:
                        with open(file, mode="r") as f:
                            content = f.read()
                            files_content.append({"name" : file, "content" : content})
                    except FileNotFoundError:
                        raise FileNotFoundError(f"{file} not found.")

                main_code = files_content
                # print(f"main_code = {main_code}")

            if files and 1 < len(files) <= 5:
                files_content = []
                response = []

                for file in files:
                    try:
                        with open(file, mode="r") as f:
                            content = f.read()
                            files_content.append({"name" : file, "content" : content})
                    except FileNotFoundError:
                        raise FileNotFoundError(f"{file} not found.")

                for data in files_content:
                    temp = []
                    temp.append(json.dumps(data))
                    multiple_files = {
                        'language' : language,
                        'version' : version,
                        'files' : json.dumps(temp),
                        'args' : args,
                        'stdin' : input,
                        'compile_timeout' : compile_timeout,
                        'run_timeout' : run_timeout,
                        'compile_memory_limit' : compile_memory_limit,
                        'run_memory_limit' : run_memory_limit
                    }
                    print(f"Multiple Files - {multiple_files}")
                    response.append(GetOutput(multiple_files).parse_output())
                return response

        payload = {
            'language' : language,
            'version' : version,
            'files' : main_code,
            'args' : args,
            'stdin' : input,
            'compile_timeout' : compile_timeout,
            'run_timeout' : run_timeout,
            'compile_memory_limit' : compile_memory_limit,
            'run_memory_limit' : run_memory_limit
        }

        return GetOutput(payload).parse_output()