diff options
Diffstat (limited to 'modules/language/python/module/_csv.scm')
-rw-r--r-- | modules/language/python/module/_csv.scm | 78 |
1 files changed, 57 insertions, 21 deletions
diff --git a/modules/language/python/module/_csv.scm b/modules/language/python/module/_csv.scm index 56e08da..5ac6159 100644 --- a/modules/language/python/module/_csv.scm +++ b/modules/language/python/module/_csv.scm @@ -10,7 +10,9 @@ #:export (QUOTE_ALL QUOTE_MINIMAL QUOTE_NONNUMERIC QUOTE_NONE reader writer Error field_size_limit get_dialect register_dialect unregister_dialect - list_dialects __doc__ Dialect)) + list_dialects __doc__ Dialect __version__)) + +(define __version__ "1.0") (define-syntax-rule (aif it p . l) (let ((it p)) (if it . l))) @@ -136,12 +138,15 @@ SETTINGS: a))) (define-syntax-rule (chr a b c) - (string-ref - (bif it a - it - (bif it b - it - c)) 0)) + (let ((x + (bif it a + it + (bif it b + it + c)))) + (if (string? x) + (string-ref x 0) + #f))) (define-syntax-rule (oor a b c) (bif it a @@ -187,9 +192,9 @@ SETTINGS: (strict (oor (py-get fmtparams "strict" e) (ref dialect 'strict e) #f))) - (make-generator () + ((make-generator () (lambda (yield) - (let/ec ret + (let/ec ret (let ((iter (wrap-in csvfile))) (let lp0 ((state 'start) (r '()) (l '())) (define-syntax-rule (raise- s) (if strict (raise s))) @@ -205,10 +210,12 @@ SETTINGS: (lambda x (cond ((or (eq? state 'line-end) - (eq? state 'start) - (eq? state 'field-end)) + (eq? state 'start)) (ret (reverse l))) + ((eq? state 'field-end) + (ret (reverse (cons (wrap1 r) l)))) + ((or (eq? state 'numeric) (eq? state 'normal)) (ret (reverse (cons (wrap1 r) l)))) @@ -217,8 +224,9 @@ SETTINGS: (raise- (Error "missing quote")) (ret (reverse (cons (wrap1 r) l))))))))) - (let ((n (len s))) - (let lp ((i 0) (state state) (r '()) (l l)) + (let* ((n (len s)) + (? (= n 1))) + (let lp ((i 0) (state state) (r r) (l l)) (mk-wrap wrap state) (define-syntax-rule (raise- s) (if strict @@ -227,12 +235,34 @@ SETTINGS: (define (end j ch) (if (eq? ch #\newline) - (if (eq? state 'start) + (cond + ((eq? state 'start) + (begin + (yield (py-list (reverse l))) + (if (= n j) + (lp0 'start '() '()) + (lp (+ j 1) 'line-end '() '())))) + + ((eq? state 'quote) + (if strict + (raise (Error "newline in quote")) + (lp j 'normal r l))) + + ((eq? state 'line-end) + (if (= n j) + (lp0 'start r l) + (lp (+ j 1) state r l))) + + (else + (yield (reverse (cons (wrap r) l))) + (if (= n j) + (lp0 'start '() '()) + (lp (+ j 1) 'line-end '() '())))) + (if (= j n) (begin - (yield (py-list (reverse l))) - (lp (+ j 1) 'line-end '() '())) - (lp (+ j 1) state r l)) - (lp (+ j 1) 'start '() (cons (wrap r) l)))) + (yield (reverse (cons* "" (wrap r) l))) + (lp0 'start '() '())) + (lp (+ j 1) 'start '() (cons (wrap r) l))))) (define (do-quotechar ch) (cond @@ -347,6 +377,9 @@ SETTINGS: ((eq? state 'normal) (end i ch)) + ((eq? state 'doublequote) + (lp (+ i 1) 'start '() (cons (wrap r) l))) + ((eq? state 'numeric) (end i ch)))) @@ -366,7 +399,6 @@ SETTINGS: (else (end i #\newline)))) - (if (< i n) (let ((ch (string-ref s i))) (cond @@ -427,7 +459,9 @@ SETTINGS: (else (error "Bug in csv reader")))) - (lp0 state r l)))))))))))) + (if ? + (lp0 state r l) + (end i #\newline)))))))))))))) (define-python-class writer () (define __init__ @@ -528,7 +562,9 @@ SETTINGS: ((eq? a quotechar) (if doublequote (lp (+ i 1) (cons* a a r)) - (lp (+ i 1) (cons* a escapechar r)))) + (if escapechar + (lp (+ i 1) (cons* a escapechar r)) + (raise (Error "no escapechar defined"))))) ((eq? a escapechar) (lp (+ i 1) (cons* a a r))) (else |