mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
add requests
module
This commit is contained in:
parent
e5d5f09d83
commit
a04cdb4cad
1
.gitignore
vendored
1
.gitignore
vendored
@ -24,3 +24,4 @@ src/_generated.h
|
||||
profile.sh
|
||||
test
|
||||
tmp.rar
|
||||
src/httplib.h
|
||||
|
@ -9,7 +9,7 @@ pipeline = [
|
||||
["common.h", "memory.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"],
|
||||
["obj.h", "codeobject.h", "frame.h"],
|
||||
["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"],
|
||||
["iter.h", "cffi.h", "io.h", "_generated.h", "pocketpy.h"]
|
||||
["iter.h", "cffi.h", "requests.h", "io.h", "_generated.h", "pocketpy.h"]
|
||||
]
|
||||
|
||||
copied = set()
|
||||
|
@ -74,7 +74,7 @@ class dict:
|
||||
def items(self):
|
||||
for kv in self._a:
|
||||
if kv is not None:
|
||||
yield kv
|
||||
yield kv[0], kv[1]
|
||||
|
||||
def clear(self):
|
||||
self._a = [None] * self._capacity
|
||||
|
40
python/requests.py
Normal file
40
python/requests.py
Normal file
@ -0,0 +1,40 @@
|
||||
class Response:
|
||||
def __init__(self, status_code, reason, content):
|
||||
self.status_code = status_code
|
||||
self.reason = reason
|
||||
self.content = content
|
||||
|
||||
assert type(self.status_code) is int
|
||||
assert type(self.reason) is str
|
||||
assert type(self.content) is bytes
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
return self.content.decode()
|
||||
|
||||
def __repr__(self):
|
||||
code = self.status_code
|
||||
return f'<Response [{code}]>'
|
||||
|
||||
def _parse_h(headers):
|
||||
if headers is None:
|
||||
return []
|
||||
if type(headers) is dict:
|
||||
return list(headers.items())
|
||||
raise ValueError('headers must be dict or None')
|
||||
|
||||
def get(url, headers=None):
|
||||
headers = _parse_h(headers)
|
||||
return _request('GET', url, headers, None)
|
||||
|
||||
def post(url, data: bytes, headers=None):
|
||||
headers = _parse_h(headers)
|
||||
return _request('POST', url, headers, data)
|
||||
|
||||
def put(url, data: bytes, headers=None):
|
||||
headers = _parse_h(headers)
|
||||
return _request('PUT', url, headers, data)
|
||||
|
||||
def delete(url, headers=None):
|
||||
headers = _parse_h(headers)
|
||||
return _request('DELETE', url, headers, None)
|
@ -6,6 +6,7 @@
|
||||
#include "repl.h"
|
||||
#include "iter.h"
|
||||
#include "cffi.h"
|
||||
#include "requests.h"
|
||||
#include "io.h"
|
||||
#include "_generated.h"
|
||||
|
||||
@ -920,11 +921,6 @@ inline void VM::post_init(){
|
||||
add_module_gc(this);
|
||||
add_module_random(this);
|
||||
|
||||
if(enable_os){
|
||||
add_module_io(this);
|
||||
add_module_os(this);
|
||||
}
|
||||
|
||||
for(const char* name: {"this", "functools", "collections", "heapq", "bisect"}){
|
||||
_lazy_modules[name] = kPythonLibs[name];
|
||||
}
|
||||
@ -969,6 +965,12 @@ inline void VM::post_init(){
|
||||
}
|
||||
return VAR(MappingProxy(args[0]));
|
||||
}));
|
||||
|
||||
if(enable_os){
|
||||
add_module_io(this);
|
||||
add_module_os(this);
|
||||
add_module_requests(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
105
src/requests.h
Normal file
105
src/requests.h
Normal file
@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "obj.h"
|
||||
#include "vm.h"
|
||||
#include "_generated.h"
|
||||
|
||||
#if __has_include("httplib.h")
|
||||
#include "httplib.h"
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
inline void add_module_requests(VM* vm){
|
||||
static StrName m_requests("requests");
|
||||
static StrName m_Response("Response");
|
||||
PyObject* mod = vm->new_module(m_requests);
|
||||
CodeObject_ code = vm->compile(kPythonLibs["requests"], "requests.py", EXEC_MODE);
|
||||
vm->_exec(code, mod);
|
||||
|
||||
vm->bind_func<4>(mod, "_request", [](VM* vm, ArgsView args){
|
||||
Str method = CAST(Str&, args[0]);
|
||||
Str url = CAST(Str&, args[1]);
|
||||
PyObject* headers = args[2]; // a dict object
|
||||
PyObject* body = args[3]; // a bytes object
|
||||
|
||||
if(url.index("http://") != 0){
|
||||
vm->ValueError("url must start with http://");
|
||||
}
|
||||
|
||||
for(char c: url){
|
||||
switch(c){
|
||||
case '.':
|
||||
case '-':
|
||||
case '_':
|
||||
case '~':
|
||||
case ':':
|
||||
case '/':
|
||||
break;
|
||||
default:
|
||||
if(!isalnum(c)){
|
||||
vm->ValueError(fmt("invalid character in url: '", c, "'"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int slash = url.index("/", 7);
|
||||
Str path = "/";
|
||||
if(slash != -1){
|
||||
path = url.substr(slash);
|
||||
url = url.substr(0, slash);
|
||||
if(path.empty()) path = "/";
|
||||
}
|
||||
|
||||
httplib::Client client(url.str());
|
||||
|
||||
httplib::Headers h;
|
||||
if(headers != vm->None){
|
||||
List list = CAST(List&, headers);
|
||||
for(auto& item : list){
|
||||
Tuple t = CAST(Tuple&, item);
|
||||
Str key = CAST(Str&, t[0]);
|
||||
Str value = CAST(Str&, t[1]);
|
||||
h.emplace(key.str(), value.str());
|
||||
}
|
||||
}
|
||||
|
||||
auto _to_resp = [=](const httplib::Result& res){
|
||||
std::vector<char> buf(res->body.size());
|
||||
for(int i=0; i<res->body.size(); i++) buf[i] = res->body[i];
|
||||
return vm->call(
|
||||
vm->_modules[m_requests]->attr(m_Response),
|
||||
VAR(res->status),
|
||||
VAR(res->reason),
|
||||
VAR(Bytes(std::move(buf)))
|
||||
);
|
||||
};
|
||||
|
||||
if(method == "GET"){
|
||||
httplib::Result res = client.Get(path.str(), h);
|
||||
return _to_resp(res);
|
||||
}else if(method == "POST"){
|
||||
Bytes b = CAST(Bytes&, body);
|
||||
httplib::Result res = client.Post(path.str(), h, b.data(), b.size(), "application/octet-stream");
|
||||
return _to_resp(res);
|
||||
}else if(method == "PUT"){
|
||||
Bytes b = CAST(Bytes&, body);
|
||||
httplib::Result res = client.Put(path.str(), h, b.data(), b.size(), "application/octet-stream");
|
||||
return _to_resp(res);
|
||||
}else if(method == "DELETE"){
|
||||
httplib::Result res = client.Delete(path.str(), h);
|
||||
return _to_resp(res);
|
||||
}else{
|
||||
vm->ValueError("invalid method");
|
||||
}
|
||||
UNREACHABLE();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
||||
|
||||
#else
|
||||
|
||||
inline void add_module_requests(VM* vm){ }
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user