1- import os
1+ """
2+ CodeBox API Wrapper
3+ ~~~~~~~~~~~~~~~~~~~
4+
5+ A basic wrapper for the CodeBox API.
6+
7+ Usage
8+ -----
9+
10+ .. code-block:: python
11+
12+ from codeboxapi import CodeBox
13+
14+ with CodeBox() as codebox:
15+ codebox.status()
16+ codebox.run(code="print('Hello World!')")
17+ codebox.install("python-package")
18+ codebox.upload("test.txt", b"Hello World!")
19+ codebox.list_files()
20+ codebox.download("test.txt")
21+
22+ .. code-block:: python
23+
24+ from codeboxapi import CodeBox
25+
26+ async with CodeBox() as codebox:
27+ await codebox.astatus()
28+ await codebox.arun(code="print('Hello World!')")
29+ await codebox.ainstall("python-package")
30+ await codebox.aupload("test.txt", b"Hello World!")
31+ await codebox.alist_files()
32+ await codebox.adownload("test.txt")
33+
34+ """
35+
36+ from os import PathLike
237from typing import Any , Optional
3- from codeboxapi import settings
4- from codeboxapi .box import BaseBox
5- from codeboxapi .utils import base_request , abase_request
6- from codeboxapi .schema import CodeBoxStatus , CodeBoxOutput , CodeBoxFile
38+ from uuid import UUID
39+
740from aiohttp import ClientSession
841
42+ from codeboxapi .box .basebox import BaseBox
43+ from codeboxapi .config import settings
44+ from codeboxapi .schema import CodeBoxFile , CodeBoxOutput , CodeBoxStatus
45+ from codeboxapi .utils import abase_request , base_request
46+
947
1048class CodeBox (BaseBox ):
1149 """
@@ -17,39 +55,47 @@ def __new__(cls, *args, **kwargs):
1755 from .localbox import LocalBox
1856
1957 return LocalBox (* args , ** kwargs )
20- else :
21- return super ().__new__ (cls , * args , ** kwargs )
58+ return super ().__new__ (cls , * args , ** kwargs )
2259
2360 def __init__ (self , * args , ** kwargs ) -> None :
2461 super ().__init__ (* args , ** kwargs )
25- self .session : Optional [ClientSession ] = None
62+ self .session_id : Optional [UUID ] = kwargs .get ("id" , None )
63+ self .aiohttp_session : Optional [ClientSession ] = None
2664
2765 def codebox_request (self , method , endpoint , * args , ** kwargs ) -> dict [str , Any ]:
66+ """Basic request to the CodeBox API"""
2867 self ._update ()
29- return base_request (method , f"/codebox/{ self .id } " + endpoint , * args , ** kwargs )
68+ return base_request (
69+ method , f"/codebox/{ self .session_id } " + endpoint , * args , ** kwargs
70+ )
3071
3172 async def acodebox_request (
3273 self , method , endpoint , * args , ** kwargs
3374 ) -> dict [str , Any ]:
75+ """Basic async request to the CodeBox API"""
3476 self ._update ()
35- if self .session is None :
77+ if self .aiohttp_session is None :
3678 raise RuntimeError ("CodeBox session not started" )
3779 return await abase_request (
38- self .session , method , f"/codebox/{ self .id } " + endpoint , * args , ** kwargs
80+ self .aiohttp_session ,
81+ method ,
82+ f"/codebox/{ self .session_id } " + endpoint ,
83+ * args ,
84+ ** kwargs ,
3985 )
4086
4187 def start (self ) -> CodeBoxStatus :
42- self .id = base_request (
88+ self .session_id = base_request (
4389 method = "GET" ,
4490 endpoint = "/codebox/start" ,
4591 )["id" ]
4692 return CodeBoxStatus (status = "started" )
4793
4894 async def astart (self ) -> CodeBoxStatus :
49- self .session = ClientSession ()
50- self .id = (
95+ self .aiohttp_session = ClientSession ()
96+ self .session_id = (
5197 await abase_request (
52- self .session ,
98+ self .aiohttp_session ,
5399 method = "GET" ,
54100 endpoint = "/codebox/start" ,
55101 )
@@ -72,34 +118,30 @@ async def astatus(self):
72118 )
73119 )
74120
75- def run (self , code : Optional [str ] = None , file_path : Optional [os .PathLike ] = None ):
76- if not code and not file_path :
121+ def run (
122+ self , code : Optional [str ] = None , file_path : Optional [PathLike ] = None
123+ ) -> CodeBoxOutput :
124+ if not code and not file_path : # R0801
77125 raise ValueError ("Code or file_path must be specified!" )
78126
79127 if code and file_path :
80128 raise ValueError ("Can only specify code or the file to read_from!" )
81129
82130 if file_path :
83- with open (file_path , "r" ) as f :
131+ with open (file_path , "r" , encoding = "utf-8" ) as f :
84132 code = f .read ()
85133
86134 return CodeBoxOutput (
87135 ** self .codebox_request (
88136 method = "POST" ,
89- endpoint = f "/run" ,
137+ endpoint = "/run" ,
90138 body = {"code" : code },
91139 )
92140 )
93141
94142 async def arun (
95- self , code : Optional [str ] = None , file_path : Optional [os .PathLike ] = None
96- ):
97- if not code and not file_path :
98- raise ValueError ("Code or file_path must be specified!" )
99-
100- if code and file_path :
101- raise ValueError ("Can only specify code or the file to read_from!" )
102-
143+ self , code : str , file_path : Optional [PathLike ] = None
144+ ) -> CodeBoxOutput :
103145 if file_path : # TODO: Implement this
104146 raise NotImplementedError (
105147 "Reading from FilePath is not supported in async mode yet!"
@@ -108,7 +150,7 @@ async def arun(
108150 return CodeBoxOutput (
109151 ** await self .acodebox_request (
110152 method = "POST" ,
111- endpoint = f "/run" ,
153+ endpoint = "/run" ,
112154 body = {"code" : code },
113155 )
114156 )
@@ -193,6 +235,22 @@ async def alist_files(self) -> list[CodeBoxFile]:
193235 )["files" ]
194236 ]
195237
238+ def restart (self ) -> CodeBoxStatus :
239+ return CodeBoxStatus (
240+ ** self .codebox_request (
241+ method = "POST" ,
242+ endpoint = "/restart" ,
243+ )
244+ )
245+
246+ async def arestart (self ) -> CodeBoxStatus :
247+ return CodeBoxStatus (
248+ ** await self .acodebox_request (
249+ method = "POST" ,
250+ endpoint = "/restart" ,
251+ )
252+ )
253+
196254 def stop (self ) -> CodeBoxStatus :
197255 return CodeBoxStatus (
198256 ** self .codebox_request (
@@ -208,7 +266,7 @@ async def astop(self) -> CodeBoxStatus:
208266 endpoint = "/stop" ,
209267 )
210268 )
211- if self .session :
212- await self .session .close ()
213- self .session = None
269+ if self .aiohttp_session :
270+ await self .aiohttp_session .close ()
271+ self .aiohttp_session = None
214272 return status
0 commit comments