Commits

Anonymous committed 3fb8285

Add writer class which passes all tests.

Comments (0)

Files changed (1)

         # internal state?
         return self.fields
 
+#
+# WRITER
+#
+
+def _is_number(num):
+    try:
+        float(num)
+        return True
+    except ValueError:
+        return False
+
+class writer:    
+    def __init__(self, output_file, dialect="excel", **kwargs):
+        self.rec = ""
+        self.num_fields = 0
+        self.output_file = output_file
+        
+        try:
+            self.writeline = output_file.write
+        except AttributeError:
+            raise TypeError("argument 1 must have a 'write' method")
+        
+        self.dialect = _call_dialect(dialect, **kwargs)
+                
+    def join_reset(self):
+        self.rec_len = 0
+        self.rec = ""
+        self.num_fields = 0
+
+    def join_append_data(self, field, quote_empty, copy_phase):
+        def addch(c):
+            if copy_phase: self.rec += c
+        
+        dialect = self.dialect
+        if not dialect.lineterminator:
+            return -1
+        
+        # If this is not the first field we need a field separator
+        if self.num_fields > 0:
+            addch(dialect.delimiter)
+            
+        # Handle preceding quote
+        if copy_phase and self.quoted:
+            addch(dialect.quotechar)
+            
+        # Copy field data
+        for c in field:
+            want_escape = False
+            if (c == dialect.delimiter or
+                c == dialect.escapechar or
+                c == dialect.quotechar or
+                c in dialect.lineterminator):
+                if dialect.quoting == QUOTE_NONE:
+                    want_escape = True
+                else:
+                    if c == dialect.quotechar:
+                        if dialect.doublequote:
+                            addch(dialect.quotechar)
+                        else:
+                            want_escape = True
+                    if not want_escape:
+                        self.quoted = True
+                if want_escape:
+                    if not dialect.escapechar:
+                        raise Error("need to escape, but no escapechar set")
+                    addch(dialect.escapechar)
+            addch(c)
+        
+        # If field is empty check if it needs to be quoted
+        if len(field) == 0 and quote_empty:
+            if dialect.quoting == QUOTE_NONE:
+                raise Error("simgle empty field record must be quoted")
+            else:
+                self.quoted = True
+        
+        if self.quoted and copy_phase:
+            addch(dialect.quotechar)
+        
+        return 1 # HACK: should be rec_len but we don't need rec_len
+
+    def join_append(self, field, quote_empty):
+        # Scanning pass - will the field need to be quoted etc?
+        self.join_append_data(field, quote_empty, False)
+        
+        # Writing pass - actually write to rec.
+        self.rec_len = self.join_append_data(field, quote_empty, True)
+        self.num_fields += 1        
+        return 1
+        
+
+    def join_append_lineterminator(self):
+        if not self.dialect.lineterminator:
+            return 0        
+        self.rec += self.dialect.lineterminator
+        return 1
+
+    def writerow(self, seq):
+        dialect = self.dialect
+        
+        # 1143 sequence typecheck?
+        self.join_reset()
+        
+        for field in seq:
+            if dialect.quoting == QUOTE_NONNUMERIC:
+                self.quoted = not _is_number(field)
+            elif dialect.quoting == QUOTE_ALL:
+                self.quoted = True
+            else:
+                self.quoted = False
+            
+            # 1181 quoted could be modified?
+            if isinstance(field, basestring):
+                append_ok = self.join_append(field, len(seq) == 1)
+            elif field is None:
+                append_ok = self.join_append("", len(seq) == 1)
+            
+            else:
+                try:
+                    str_field = str(field)
+                except:
+                    return 0 # 1187 TODO error handling? 
+                append_ok = self.join_append(str_field, len == 1)            
+
+            if not append_ok:
+                return 0
+        
+        # Add line terminator
+        if not self.join_append_lineterminator():
+            return 0
+        
+        self.writeline(self.rec)
+        return 1
+
+    def writerows(self, seqseq):
+        for row in seqseq:
+            result = self.writerow(row)
+            if not result:
+                return None # 1231 error handling?
+        
+            
+            
 if __name__ == '__main__':
     r = reader(["1, 2, 3", "4, 5, 6"])
     result = list(r)