diff --git a/amalgamate.py b/amalgamate.py index 3aa7992b..76b4fac2 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -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"] ] diff --git a/docs/modules/csv.md b/docs/modules/csv.md new file mode 100644 index 00000000..ec930809 --- /dev/null +++ b/docs/modules/csv.md @@ -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'] +# ] +``` \ No newline at end of file diff --git a/include/pocketpy/csv.h b/include/pocketpy/csv.h new file mode 100644 index 00000000..8149fd09 --- /dev/null +++ b/include/pocketpy/csv.h @@ -0,0 +1,9 @@ +#pragma once + +#include "cffi.h" + +namespace pkpy { + +void add_module_csv(VM* vm); + +} // namespace pkpy \ No newline at end of file diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 1748b0c3..871860e3 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -14,6 +14,7 @@ #include "random.h" #include "bindings.h" #include "collections.h" +#include "csv.h" namespace pkpy { diff --git a/src/csv.cpp b/src/csv.cpp new file mode 100644 index 00000000..5aefe80f --- /dev/null +++ b/src/csv.cpp @@ -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; iValueError("unterminated quote"); + } + row.push_back(VAR(buffer)); + ret.push_back(VAR(std::move(row))); + } + return VAR(std::move(ret)); + }); +} + +} // namespace pkpy \ No newline at end of file diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index c4b7400b..e17fdda0 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -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 parts; + parts = self.split('\n'); + List ret(parts.size()); + for(int i=0; ibind(_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]; diff --git a/tests/80_csv.py b/tests/80_csv.py new file mode 100644 index 00000000..acc14113 --- /dev/null +++ b/tests/80_csv.py @@ -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']])