diff options
| author | Kenneth Reitz <me@kennethreitz.org> | 2016-02-07 07:00:55 -0500 |
|---|---|---|
| committer | Kenneth Reitz <me@kennethreitz.org> | 2016-02-07 07:00:55 -0500 |
| commit | 8debeb26aca7cc9ef427c70ee9d577eb169f9560 (patch) | |
| tree | 58316fe5669e86cbea9a1044e4978ffd3b4cc308 /tablib/formats/_dbf.py | |
| parent | 66d9e50984e7c66fd36fd86f2b469c2dae3636ba (diff) | |
| parent | a774789252d41522d4ec8b0e2c212aff4a33904d (diff) | |
| download | tablib-8debeb26aca7cc9ef427c70ee9d577eb169f9560.tar.gz | |
Merge branch 'develop' into import_export
# Conflicts:
# tablib/core.py
# tablib/formats/_csv.py
# tablib/formats/_xlsx.py
Diffstat (limited to 'tablib/formats/_dbf.py')
| -rw-r--r-- | tablib/formats/_dbf.py | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/tablib/formats/_dbf.py b/tablib/formats/_dbf.py new file mode 100644 index 0000000..41c2ef4 --- /dev/null +++ b/tablib/formats/_dbf.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- + +""" Tablib - DBF Support. +""" +import tempfile +import struct +import os + +from tablib.compat import StringIO +from tablib.compat import dbfpy +from tablib.compat import is_py3 + +if is_py3: + from tablib.packages.dbfpy3 import dbf + from tablib.packages.dbfpy3 import dbfnew + from tablib.packages.dbfpy3 import record as dbfrecord + import io +else: + from tablib.packages.dbfpy import dbf + from tablib.packages.dbfpy import dbfnew + from tablib.packages.dbfpy import record as dbfrecord + + +title = 'dbf' +extensions = ('csv',) + +DEFAULT_ENCODING = 'utf-8' + +def export_set(dataset): + """Returns DBF representation of a Dataset""" + new_dbf = dbfnew.dbf_new() + temp_file, temp_uri = tempfile.mkstemp() + + # create the appropriate fields based on the contents of the first row + first_row = dataset[0] + for fieldname, field_value in zip(dataset.headers, first_row): + if type(field_value) in [int, float]: + new_dbf.add_field(fieldname, 'N', 10, 8) + else: + new_dbf.add_field(fieldname, 'C', 80) + + new_dbf.write(temp_uri) + + dbf_file = dbf.Dbf(temp_uri, readOnly=0) + for row in dataset: + record = dbfrecord.DbfRecord(dbf_file) + for fieldname, field_value in zip(dataset.headers, row): + record[fieldname] = field_value + record.store() + + dbf_file.close() + dbf_stream = open(temp_uri, 'rb') + if is_py3: + stream = io.BytesIO(dbf_stream.read()) + else: + stream = StringIO(dbf_stream.read()) + dbf_stream.close() + os.remove(temp_uri) + return stream.getvalue() + +def import_set(dset, in_stream, headers=True): + """Returns a dataset from a DBF stream.""" + + dset.wipe() + if is_py3: + _dbf = dbf.Dbf(io.BytesIO(in_stream)) + else: + _dbf = dbf.Dbf(StringIO(in_stream)) + dset.headers = _dbf.fieldNames + for record in range(_dbf.recordCount): + row = [_dbf[record][f] for f in _dbf.fieldNames] + dset.append(row) + +def detect(stream): + """Returns True if the given stream is valid DBF""" + #_dbf = dbf.Table(StringIO(stream)) + try: + if is_py3: + if type(stream) is not bytes: + stream = bytes(stream, 'utf-8') + _dbf = dbf.Dbf(io.BytesIO(stream), readOnly=True) + else: + _dbf = dbf.Dbf(StringIO(stream), readOnly=True) + return True + except (ValueError, struct.error): + # When we try to open up a file that's not a DBF, dbfpy raises a + # ValueError. + # When unpacking a string argument with less than 8 chars, struct.error is + # raised. + return False + + + |
