Skip to content

Commit 8699cc9

Browse files
authored
Merge pull request #16 from coder-inbox/code-execution
implement code execution using rapid api judge0 api
2 parents 5a85a88 + def640d commit 8699cc9

File tree

7 files changed

+101
-1
lines changed

7 files changed

+101
-1
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ DETA_PROJECT_KEY=
2121

2222
# OpenAI
2323
OPENAI_API_KEY=
24+
25+
# RAPIDAPI JUDGE0 API Key
26+
RAPIDAPI_KEY=

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ deta = "^1.1.0"
3232
nylas = "^5.14.1"
3333
openai = "^0.28.1"
3434
apscheduler = "^3.10.4"
35+
httpx = "^0.25.0"
3536

3637
[tool.poetry.group.dev.dependencies]
3738
pytest = "^7.2.0"

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ fastapi==0.103.2
1616
frozenlist==1.3.3
1717
h11==0.14.0
1818
httptools==0.6.0
19+
httpx==0.25.0
20+
httpcore==0.18.0
1921
idna==3.4
2022
motor==3.1.2
2123
multidict==6.0.4

src/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class Settings(BaseSettings):
2929
DETA_PROJECT_KEY (str) : A Deta project key.
3030
NYLAS_SYSTEM_TOKEN (str) : A Nylas access token for sending email as system.
3131
OPENAI_API_KEY (str) : An openai api key for generating emails.
32+
RAPIDAPI_KEY (str): Rapid api key
3233
3334
Example:
3435
>>> MONGODB_HOST=svc-123456789.svc.MONGODB.com
@@ -40,6 +41,7 @@ class Settings(BaseSettings):
4041
>>> DETA_PROJECT_KEY=12312dSDJHJSBA
4142
>>> NYLAS_SYSTEM_TOKEN=12312dSDJHJSBA
4243
>>> OPENAI_API_KEY=12312dSDJHJSBA
44+
>>> RAPIDAPI_KEY=12312dSDJHJSBA
4345
"""
4446

4547
MONGODB_HOST: str = os.getenv("MONGODB_HOST") # type: ignore
@@ -55,6 +57,7 @@ class Settings(BaseSettings):
5557
CLIENT_URI: str = os.getenv("CLIENT_URI") # type: ignore
5658
NYLAS_SYSTEM_TOKEN: str = os.getenv("NYLAS_SYSTEM_TOKEN") # type: ignore
5759
OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY") # type: ignore
60+
RAPIDAPI_KEY: str = os.getenv("RAPIDAPI_KEY") # type: ignore
5861

5962
class Config: # pylint: disable=R0903
6063
"""

src/nylas/router.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
"""Nylas router module."""
22

3+
import asyncio
34
from fastapi import (
45
APIRouter,
56
Depends,
7+
HTTPException,
68
)
9+
import httpx
710
from odmantic.session import (
811
AIOSession,
912
)
@@ -29,6 +32,15 @@
2932

3033
router = APIRouter(prefix="/api/v1")
3134

35+
JUDGE0_API_URL = "https://judge0-ce.p.rapidapi.com/submissions"
36+
37+
headers = {
38+
"X-RapidAPI-Key": settings().RAPIDAPI_KEY,
39+
"Content-Type": "application/json",
40+
}
41+
42+
submission_status_dict = {}
43+
3244

3345
@router.post(
3446
"/nylas/generate-auth-url",
@@ -334,3 +346,77 @@ async def search_emails(
334346
item.as_json(enforce_read_only=False) for item in threads_with_messages
335347
]
336348
return res_json
349+
350+
351+
@router.post(
352+
"/nylas/execute-code",
353+
response_model=None,
354+
status_code=200,
355+
name="nylas:execute-code",
356+
)
357+
async def execute_code(
358+
request_body: nylas_schemas.CodeExecutionSchema,
359+
current_user: users_schemas.UserObjectSchema = Depends(
360+
dependencies.get_current_user
361+
),
362+
) -> Any:
363+
try:
364+
payload = {
365+
"source_code": request_body.code,
366+
"language_id": int(request_body.language_id),
367+
"stdin": "",
368+
"expected_output": "",
369+
"cpu_time_limit": 2,
370+
"cpu_extra_time": 0.5,
371+
"wall_time_limit": 5,
372+
"memory_limit": 512000,
373+
}
374+
375+
async with httpx.AsyncClient() as client:
376+
response = await client.post(
377+
JUDGE0_API_URL,
378+
json=payload,
379+
headers=headers,
380+
)
381+
382+
if response.status_code == 201:
383+
submission_token = response.json()["token"]
384+
submission_status_dict[submission_token] = "Running"
385+
timeout = 60
386+
start_time = asyncio.get_event_loop().time()
387+
result = None
388+
while submission_status_dict.get(submission_token) == "Running":
389+
await asyncio.sleep(1)
390+
391+
if asyncio.get_event_loop().time() - start_time > timeout:
392+
print("Timeout")
393+
submission_status_dict[submission_token] = "Timeout"
394+
break
395+
396+
async with httpx.AsyncClient() as client:
397+
new_response = await client.get(
398+
f"{JUDGE0_API_URL}/{submission_token}",
399+
headers=headers,
400+
)
401+
402+
if new_response.status_code == 200:
403+
print(new_response.json())
404+
submission_stdout = new_response.json()["stdout"]
405+
if submission_stdout:
406+
print("Finished")
407+
submission_status_dict[submission_token] = "Finished"
408+
result = new_response.json()
409+
break
410+
else:
411+
return HTTPException(
412+
status_code=500, detail="Failed to retrieve result"
413+
)
414+
return result
415+
else:
416+
return HTTPException(
417+
status_code=500, detail="Code execution failed"
418+
)
419+
420+
except Exception as e:
421+
print(e)
422+
return HTTPException(status_code=500, detail=str(e))

src/nylas/schemas.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,8 @@ class ReplyEmailSchema(BaseModel):
8484
..., description="thread id", example="6gq33fhrgpts8wmb2sl98jdvo"
8585
)
8686
body: str = Field(..., description="email body", example="Hello there!")
87+
88+
89+
class CodeExecutionSchema(BaseModel):
90+
code: str = Field(..., description="code", example="print('hi')")
91+
language_id: str = Field(..., description="language id", example="71")

0 commit comments

Comments
 (0)