add csv module

This commit is contained in:
blueloveTH 2023-11-28 22:40:37 +08:00
parent 7b9c7d926d
commit a62943568f
7 changed files with 130 additions and 1 deletions

View File

@ -9,7 +9,7 @@ pipeline = [
["config.h", "export.h", "common.h", "memory.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"],
["obj.h", "dict.h", "codeobject.h", "frame.h"],
["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"],
["_generated.h", "cffi.h", "bindings.h", "iter.h", "base64.h", "collections.h", "random.h", "re.h", "linalg.h", "easing.h", "io.h"],
["_generated.h", "cffi.h", "bindings.h", "iter.h", "base64.h", "csv.h", "collections.h", "random.h", "re.h", "linalg.h", "easing.h", "io.h"],
["pocketpy.h", "pocketpy_c.h"]
]

25
docs/modules/csv.md Normal file
View File

@ -0,0 +1,25 @@
---
icon: package
label: csv
---
### `csv.reader(csvfile: list[str]) -> list`
Parse a CSV file into a list of lists.
## Example
```python
import csv
data = """a,b,c
1,2,3
"""
print(csv.reader(data.splitlines()))
# [
# ['a', 'b', 'c'],
# ['1', '2', '3']
# ]
```

9
include/pocketpy/csv.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include "cffi.h"
namespace pkpy {
void add_module_csv(VM* vm);
} // namespace pkpy

View File

@ -14,6 +14,7 @@
#include "random.h"
#include "bindings.h"
#include "collections.h"
#include "csv.h"
namespace pkpy {

56
src/csv.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "pocketpy/csv.h"
#include "pocketpy/config.h"
namespace pkpy{
void add_module_csv(VM *vm){
PyObject* mod = vm->new_module("csv");
vm->bind(mod, "reader(csvfile: list[str]) -> list", [](VM* vm, ArgsView args){
const List& csvfile = CAST(List&, args[0]);
List ret;
for(int i=0; i<csvfile.size(); i++){
std::string_view line = CAST(Str&, csvfile[i]).sv();
List row;
int j = 0;
bool in_quote = false;
std::string buffer;
while(j < line.size()){
switch(line[j]){
case '"':
if(in_quote){
if(j+1 < line.size() && line[j+1] == '"'){
buffer += '"';
j++;
}else{
in_quote = false;
}
}else{
in_quote = true;
}
break;
case ',':
if(in_quote){
buffer += line[j];
}else{
row.push_back(VAR(buffer));
buffer.clear();
}
break;
default:
buffer += line[j];
break;
}
j++;
}
if(in_quote){
vm->ValueError("unterminated quote");
}
row.push_back(VAR(buffer));
ret.push_back(VAR(std::move(row)));
}
return VAR(std::move(ret));
});
}
} // namespace pkpy

View File

@ -549,6 +549,15 @@ void init_builtins(VM* _vm) {
return VAR(std::move(ret));
});
_vm->bind(_vm->_t(_vm->tp_str), "splitlines(self)", [](VM* vm, ArgsView args) {
const Str& self = _CAST(Str&, args[0]);
std::vector<std::string_view> parts;
parts = self.split('\n');
List ret(parts.size());
for(int i=0; i<parts.size(); i++) ret[i] = VAR(Str(parts[i]));
return VAR(std::move(ret));
});
_vm->bind(_vm->_t(_vm->tp_str), "count(self, s: str)", [](VM* vm, ArgsView args) {
const Str& self = _CAST(Str&, args[0]);
const Str& s = CAST(Str&, args[1]);
@ -1646,6 +1655,7 @@ void VM::post_init(){
add_module_base64(this);
add_module_timeit(this);
add_module_operator(this);
add_module_csv(this);
for(const char* name: {"this", "functools", "heapq", "bisect", "pickle", "_long", "colorsys", "typing", "datetime"}){
_lazy_modules[name] = kPythonLibs[name];

28
tests/80_csv.py Normal file
View File

@ -0,0 +1,28 @@
import csv
def test(data: str, expected):
ret = list(csv.reader(data.splitlines()))
assert ret==expected, f"Expected {expected}, got {ret}"
test("""a,b,c
1,2,3
""", [['a', 'b', 'c'], ['1', '2', '3']])
test("""a,b,c
1,2,"3"
""", [['a', 'b', 'c'], ['1', '2', '3']])
test("""a,b,c
1,2,'3'
""", [['a', 'b', 'c'], ['1', '2', '\'3\'']])
test('''a,b,c
1,2,"123"""
''', [['a', 'b', 'c'], ['1', '2', '123"']])
test("""a,b,c,
1,2,3,
""", [['a', 'b', 'c', ''], ['1', '2', '3', '']])
test("""a,b ,c,
1,"22""33",3
""", [['a', 'b ', 'c', ''], ['1', '22"33', '3']])