Compare commits

...

31 Commits

Author SHA1 Message Date
Iuri de Silvio 6afe716d64 Version bump: 0.11.4 2017-01-23 19:10:36 -02:00
Iuri de Silvio 3d44bdec40 Merge pull request #269 from kammala/master
Fixed classifiers in setup.py
2017-01-10 10:14:11 -02:00
kammala 319505817a Fixed classifiers in setup.py
moved classifiers from tuple to list(this allow to use setup.py upload command in python >= 3.5)
2017-01-10 12:20:08 +03:00
kennethreitz 6cb9a69746 Merge pull request #266 from wenzhihong2003/master
remove file must be close it.
2017-01-05 12:51:01 -05:00
tomwen bb1354b61f remove file must be close it.
in windows if you don't close template file, remove it will raise

WindowsError: [Error 32]
2016-12-30 10:21:43 +08:00
Iuri de Silvio ddc4bd30f2 Merge pull request #234 from BrianPainter/master
if the object is a decimal, return the string representation of it.
2016-12-18 19:10:18 -02:00
Iuri de Silvio 52e547daf9 Merge pull request #259 from dyve/master
Fix #260 date and datetime export to JSON
2016-12-18 19:09:26 -02:00
Iuri de Silvio 7f0b7a0a22 Merge pull request #263 from andriisoldatenko/develop
Remove LOCALE from str regular expression
2016-12-18 19:08:41 -02:00
Andrii Soldatenko ddac443732 Added py36 to tox.ini 2016-12-18 17:04:28 +02:00
Andrii Soldatenko e13f4d0aba Added py35 to tox.ini 2016-12-18 16:54:22 +02:00
Andrii Soldatenko 54f9041f2c Remove LOCALE from str regular expression 2016-12-18 16:44:18 +02:00
Dylan Verheul 91d3299280 Fix date and datetime export to JSON in Python versions with a json package
Python without a json package will use omnijson and fail on date and datetime objects.
Added unit tests.
2016-11-30 12:32:47 +01:00
kennethreitz f59abe84be Merge pull request #239 from ErwinJunge/dataset-title-in-docs
Put Dataset.title in the documentation
2016-05-21 15:13:30 -04:00
Erwin Junge cf23f2344f Put Dataset.title in the documentation 2016-05-20 16:13:22 +02:00
kennethreitz e16bb38c48 Merge pull request #238 from sushrutrathi/code_changes
changes in code refactoring
2016-05-03 21:30:25 -04:00
Sushrut Rathi 71ca275dd1 changes in code refactoring 2016-05-03 13:47:25 +05:30
kennethreitz 75bbfbbaf4 Merge pull request #233 from ScorpionResponse/html_book_test
Add HTML format to the book_export test and fix the format to work properly
2016-04-10 18:12:37 -04:00
Iuri de Silvio b35d505621 Merge pull request #236 from candy0427/master
Update README.rst
2016-03-24 10:18:34 -03:00
CandyLikeSmile cd491c062c Update README.rst 2016-03-24 14:19:59 +08:00
Brian Painter 9fdb72cc5c if the object is a decimal, return the string representation of it. 2016-03-23 08:21:36 -04:00
kennethreitz a5b1f7987e Merge pull request #232 from chimeno/patch-1
[docs] Update variable name in tuto
2016-03-18 14:37:19 -04:00
Paul Moss 8cf6770a76 Add HTML format to the book_export test and fix the format to work properly 2016-03-18 18:17:19 +00:00
Daniel Chimeno 5fa3d2f886 [docs] Update variable name in tuto
The tutorial has been using the 'data' variable, but in this case it's using 'd'.
This change that.
2016-03-18 09:22:59 +01:00
kennethreitz d4c66c7a4e Merge pull request #229 from pmlandwehr/patch-1
python 3 fix: map filter to ifilter
2016-02-28 00:20:37 -05:00
Peter M. Landwehr af17586581 python 3 fix: map filter to ifilter 2016-02-27 21:14:13 -08:00
kennethreitz 23d21f00f3 Update HISTORY.rst 2016-02-25 12:59:18 -05:00
kennethreitz 7ee924b5a6 Merge pull request #228 from tomchristie/print-dataset-with-no-headers
Fixed textual representation for Dataset with no headers
2016-02-25 12:58:35 -05:00
Tom Christie d720beadac Fixed __unicode__/__str__ for dataset with no headers 2016-02-25 13:28:29 +00:00
kennethreitz ee9666a146 Merge pull request #225 from tusharmakkar08/master
PEP-8 standards followed
2016-02-22 09:17:34 -05:00
tusharmakkar08 77a9e25795 Reverted back yaml3 for ci failure 2016-02-22 17:05:06 +05:30
tusharmakkar08 d515724817 PEP-8 standards followed 2016-02-22 16:36:26 +05:30
25 changed files with 344 additions and 321 deletions
+3
View File
@@ -26,3 +26,6 @@ junit-py27.xml
# tox noise # tox noise
.tox .tox
# pyenv noise
.python-version
+2
View File
@@ -32,3 +32,5 @@ Patches and Suggestions
- Rabin Nankhwa - Rabin Nankhwa
- Marco Dallagiacoma - Marco Dallagiacoma
- Mathias Loesch - Mathias Loesch
- Tushar Makkar
- Andrii Soldatenko
+11
View File
@@ -1,6 +1,17 @@
History History
------- -------
0.11.4 (2017-01-23)
+++++++++++++++++++
- Use built-in `json` package if available
- Support Python 3.5+ in classifiers
** Bugfixes **
- Fixed textual representation for Dataset with no headers
- Handle decimal types
0.11.3 (2016-02-16) 0.11.3 (2016-02-16)
+++++++++++++++++++ +++++++++++++++++++
+1 -1
View File
@@ -1,7 +1,7 @@
Tablib: format-agnostic tabular dataset library Tablib: format-agnostic tabular dataset library
=============================================== ===============================================
.. image:: https://travis-ci.org/kennethreitz/tablib.svg?branch=develop .. image:: https://travis-ci.org/kennethreitz/tablib.svg?branch=master
:target: https://travis-ci.org/kennethreitz/tablib :target: https://travis-ci.org/kennethreitz/tablib
:: ::
+2 -2
View File
@@ -158,9 +158,9 @@ To do so, we access the :class:`Dataset` as if it were a standard Python diction
You can also access the column using its index. :: You can also access the column using its index. ::
>>> d.headers >>> data.headers
['Last Name', 'First Name', 'Age'] ['Last Name', 'First Name', 'Age']
>>> d.get_col(1) >>> data.get_col(1)
['Kenneth', 'Bessie'] ['Kenneth', 'Bessie']
Let's find the average age. :: Let's find the average age. ::
+4 -2
View File
@@ -73,7 +73,7 @@ setup(
url='http://python-tablib.org', url='http://python-tablib.org',
packages=packages, packages=packages,
license='MIT', license='MIT',
classifiers=( classifiers=[
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'Natural Language :: English', 'Natural Language :: English',
@@ -87,6 +87,8 @@ setup(
'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.4',
), 'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],
tests_require=['pytest'], tests_require=['pytest'],
) )
+1
View File
@@ -34,6 +34,7 @@ if is_py3:
from io import StringIO from io import StringIO
# py3 mappings # py3 mappings
ifilter = filter
unicode = str unicode = str
bytes = bytes bytes = bytes
basestring = str basestring = str
+7 -4
View File
@@ -18,8 +18,8 @@ from tablib.compat import OrderedDict, unicode
__title__ = 'tablib' __title__ = 'tablib'
__version__ = '0.11.3' __version__ = '0.11.4'
__build__ = 0x001103 __build__ = 0x001104
__author__ = 'Kenneth Reitz' __author__ = 'Kenneth Reitz'
__license__ = 'MIT' __license__ = 'MIT'
__copyright__ = 'Copyright 2016 Kenneth Reitz' __copyright__ = 'Copyright 2016 Kenneth Reitz'
@@ -143,6 +143,7 @@ class Dataset(object):
:param \*args: (optional) list of rows to populate Dataset :param \*args: (optional) list of rows to populate Dataset
:param headers: (optional) list strings for Dataset header row :param headers: (optional) list strings for Dataset header row
:param title: (optional) string to use as title of the Dataset
.. admonition:: Format Attributes Definition .. admonition:: Format Attributes Definition
@@ -223,7 +224,8 @@ class Dataset(object):
result = [] result = []
# Add unicode representation of headers. # Add unicode representation of headers.
result.append([unicode(h) for h in self.__headers]) if self.__headers:
result.append([unicode(h) for h in self.__headers])
# Add unicode representation of rows. # Add unicode representation of rows.
result.extend(list(map(unicode, row)) for row in self._data) result.extend(list(map(unicode, row)) for row in self._data)
@@ -232,7 +234,8 @@ class Dataset(object):
field_lens = list(map(max, zip(*lens))) field_lens = list(map(max, zip(*lens)))
# delimiter between header and data # delimiter between header and data
result.insert(1, ['-' * length for length in field_lens]) if self.__headers:
result.insert(1, ['-' * length for length in field_lens])
format_string = '|'.join('{%s:%s}' % item for item in enumerate(field_lens)) format_string = '|'.join('{%s:%s}' % item for item in enumerate(field_lens))
+1
View File
@@ -55,6 +55,7 @@ def export_set(dataset):
else: else:
stream = StringIO(dbf_stream.read()) stream = StringIO(dbf_stream.read())
dbf_stream.close() dbf_stream.close()
os.close(temp_file)
os.remove(temp_uri) os.remove(temp_uri)
return stream.getvalue() return stream.getvalue()
+9 -6
View File
@@ -31,7 +31,7 @@ def export_set(dataset):
page.table.open() page.table.open()
if dataset.headers is not None: if dataset.headers is not None:
new_header = [item if item is not None else '' for item in dataset.headers] new_header = [item if item is not None else '' for item in dataset.headers]
page.thead.open() page.thead.open()
headers = markup.oneliner.th(new_header) headers = markup.oneliner.th(new_header)
@@ -39,7 +39,7 @@ def export_set(dataset):
page.thead.close() page.thead.close()
for row in dataset: for row in dataset:
new_row = [item if item is not None else '' for item in row] new_row = [item if item is not None else '' for item in row]
html_row = markup.oneliner.td(new_row) html_row = markup.oneliner.td(new_row)
page.tr(html_row) page.tr(html_row)
@@ -58,10 +58,13 @@ def export_book(databook):
stream = StringIO() stream = StringIO()
# Allow unicode characters in output
wrapper = codecs.getwriter("utf8")(stream)
for i, dset in enumerate(databook._datasets): for i, dset in enumerate(databook._datasets):
title = (dset.title if dset.title else 'Set %s' % (i)) title = (dset.title if dset.title else 'Set %s' % (i))
stream.write('<%s>%s</%s>\n' % (BOOK_ENDINGS, title, BOOK_ENDINGS)) wrapper.write('<%s>%s</%s>\n' % (BOOK_ENDINGS, title, BOOK_ENDINGS))
stream.write(dset.html) wrapper.write(dset.html)
stream.write('\n') wrapper.write('\n')
return stream.getvalue() return stream.getvalue().decode('utf-8')
+12 -3
View File
@@ -2,11 +2,14 @@
""" Tablib - JSON Support """ Tablib - JSON Support
""" """
import decimal
import tablib import tablib
import sys try:
from tablib.packages import omnijson as json import json
except ImportError:
from tablib.packages import omnijson as json
title = 'json' title = 'json'
@@ -14,7 +17,13 @@ extensions = ('json', 'jsn')
def date_handler(obj): def date_handler(obj):
return obj.isoformat() if hasattr(obj, 'isoformat') else obj if isinstance(obj, decimal.Decimal):
return str(obj)
elif hasattr(obj, 'isoformat'):
return obj.isoformat()
else:
return obj
# return obj.isoformat() if hasattr(obj, 'isoformat') else obj
def export_set(dataset): def export_set(dataset):
+1 -4
View File
@@ -13,16 +13,12 @@ except ImportError:
else: else:
import tablib.packages.yaml as yaml import tablib.packages.yaml as yaml
import tablib import tablib
title = 'yaml' title = 'yaml'
extensions = ('yaml', 'yml') extensions = ('yaml', 'yml')
def export_set(dataset): def export_set(dataset):
"""Returns YAML representation of Dataset.""" """Returns YAML representation of Dataset."""
@@ -52,6 +48,7 @@ def import_book(dbook, in_stream):
data.dict = sheet['data'] data.dict = sheet['data']
dbook.add_sheet(data) dbook.add_sheet(data)
def detect(stream): def detect(stream):
"""Returns True if given stream is valid YAML.""" """Returns True if given stream is valid YAML."""
try: try:
+28 -23
View File
@@ -63,9 +63,10 @@ __author__ = "Jeff Kunce <kuncej@mail.conservation.state.mo.us>"
__all__ = ["Dbf"] __all__ = ["Dbf"]
from . import header from . import header
from .import record from . import record
from utils import INVALID_VALUE from utils import INVALID_VALUE
class Dbf(object): class Dbf(object):
"""DBF accessor. """DBF accessor.
@@ -82,13 +83,13 @@ class Dbf(object):
""" """
__slots__ = ("name", "header", "stream", __slots__ = ("name", "header", "stream",
"_changed", "_new", "_ignore_errors") "_changed", "_new", "_ignore_errors")
HeaderClass = header.DbfHeader HeaderClass = header.DbfHeader
RecordClass = record.DbfRecord RecordClass = record.DbfRecord
INVALID_VALUE = INVALID_VALUE INVALID_VALUE = INVALID_VALUE
## initialization and creation helpers # initialization and creation helpers
def __init__(self, f, readOnly=False, new=False, ignoreErrors=False): def __init__(self, f, readOnly=False, new=False, ignoreErrors=False):
"""Initialize instance. """Initialize instance.
@@ -137,7 +138,7 @@ class Dbf(object):
self._new = bool(new) self._new = bool(new)
self._changed = False self._changed = False
## properties # properties
closed = property(lambda self: self.stream.closed) closed = property(lambda self: self.stream.closed)
recordCount = property(lambda self: self.header.recordCount) recordCount = property(lambda self: self.header.recordCount)
@@ -149,6 +150,7 @@ class Dbf(object):
def ignoreErrors(self, value): def ignoreErrors(self, value):
"""Update `ignoreErrors` flag on the header object and self""" """Update `ignoreErrors` flag on the header object and self"""
self.header.ignoreErrors = self._ignore_errors = bool(value) self.header.ignoreErrors = self._ignore_errors = bool(value)
ignoreErrors = property( ignoreErrors = property(
lambda self: self._ignore_errors, lambda self: self._ignore_errors,
ignoreErrors, ignoreErrors,
@@ -159,7 +161,7 @@ class Dbf(object):
""") """)
## protected methods # protected methods
def _fixIndex(self, index): def _fixIndex(self, index):
"""Return fixed index. """Return fixed index.
@@ -185,7 +187,7 @@ class Dbf(object):
raise IndexError("Record index out of range") raise IndexError("Record index out of range")
return index return index
## iterface methods # iterface methods
def close(self): def close(self):
self.flush() self.flush()
@@ -226,9 +228,9 @@ class Dbf(object):
self.header.addField(*defs) self.header.addField(*defs)
else: else:
raise TypeError("At least one record was added, " raise TypeError("At least one record was added, "
"structure can't be changed") "structure can't be changed")
## 'magic' methods (representation and sequence interface) # 'magic' methods (representation and sequence interface)
def __repr__(self): def __repr__(self):
return "Dbf stream '%s'\n" % self.stream + repr(self.header) return "Dbf stream '%s'\n" % self.stream + repr(self.header)
@@ -248,19 +250,20 @@ class Dbf(object):
self._changed = True self._changed = True
self._new = False self._new = False
#def __del__(self): # def __del__(self):
# """Flush stream upon deletion of the object.""" # """Flush stream upon deletion of the object."""
# self.flush() # self.flush()
def demoRead(filename): def demo_read(filename):
_dbf = Dbf(filename, True) _dbf = Dbf(filename, True)
for _rec in _dbf: for _rec in _dbf:
print print
print(repr(_rec)) print(repr(_rec))
_dbf.close() _dbf.close()
def demoCreate(filename):
def demo_create(filename):
_dbf = Dbf(filename, new=True) _dbf = Dbf(filename, new=True)
_dbf.addField( _dbf.addField(
("NAME", "C", 15), ("NAME", "C", 15),
@@ -269,10 +272,10 @@ def demoCreate(filename):
("BIRTHDATE", "D"), ("BIRTHDATE", "D"),
) )
for (_n, _s, _i, _b) in ( for (_n, _s, _i, _b) in (
("John", "Miller", "YC", (1981, 1, 2)), ("John", "Miller", "YC", (1981, 1, 2)),
("Andy", "Larkin", "AL", (1982, 3, 4)), ("Andy", "Larkin", "AL", (1982, 3, 4)),
("Bill", "Clinth", "", (1983, 5, 6)), ("Bill", "Clinth", "", (1983, 5, 6)),
("Bobb", "McNail", "", (1984, 7, 8)), ("Bobb", "McNail", "", (1984, 7, 8)),
): ):
_rec = _dbf.newRecord() _rec = _dbf.newRecord()
_rec["NAME"] = _n _rec["NAME"] = _n
@@ -283,10 +286,12 @@ def demoCreate(filename):
print(repr(_dbf)) print(repr(_dbf))
_dbf.close() _dbf.close()
if (__name__=='__main__'):
import sys
_name = len(sys.argv) > 1 and sys.argv[1] or "county.dbf"
demoCreate(_name)
demoRead(_name)
# vim: set et sw=4 sts=4 : if __name__ == '__main__':
import sys
_name = len(sys.argv) > 1 and sys.argv[1] or "county.dbf"
demo_create(_name)
demo_read(_name)
# vim: set et sw=4 sts=4 :
+16 -15
View File
@@ -29,6 +29,7 @@ from fields import *
from header import * from header import *
from record import * from record import *
class _FieldDefinition(object): class _FieldDefinition(object):
"""Field definition. """Field definition.
@@ -151,28 +152,28 @@ class dbf_new(object):
_dbfh.write(stream) _dbfh.write(stream)
if (__name__=='__main__'): if __name__ == '__main__':
# create a new DBF-File # create a new DBF-File
dbfn=dbf_new() dbfn = dbf_new()
dbfn.add_field("name",'C',80) dbfn.add_field("name", 'C', 80)
dbfn.add_field("price",'N',10,2) dbfn.add_field("price", 'N', 10, 2)
dbfn.add_field("date",'D',8) dbfn.add_field("date", 'D', 8)
dbfn.write("tst.dbf") dbfn.write("tst.dbf")
# test new dbf # test new dbf
print "*** created tst.dbf: ***" print "*** created tst.dbf: ***"
dbft = Dbf('tst.dbf', readOnly=0) dbft = Dbf('tst.dbf', readOnly=0)
print repr(dbft) print repr(dbft)
# add a record # add a record
rec=DbfRecord(dbft) rec = DbfRecord(dbft)
rec['name']='something' rec['name'] = 'something'
rec['price']=10.5 rec['price'] = 10.5
rec['date']=(2000,1,12) rec['date'] = (2000, 1, 12)
rec.store() rec.store()
# add another record # add another record
rec=DbfRecord(dbft) rec = DbfRecord(dbft)
rec['name']='foo and bar' rec['name'] = 'foo and bar'
rec['price']=12234 rec['price'] = 12234
rec['date']=(1992,7,15) rec['date'] = (1992, 7, 15)
rec.store() rec.store()
# show the records # show the records
@@ -181,8 +182,8 @@ if (__name__=='__main__'):
for i1 in range(len(dbft)): for i1 in range(len(dbft)):
rec = dbft[i1] rec = dbft[i1]
for fldName in dbft.fieldNames: for fldName in dbft.fieldNames:
print '%s:\t %s'%(fldName, rec[fldName]) print '%s:\t %s' % (fldName, rec[fldName])
print print
dbft.close() dbft.close()
# vim: set et sts=4 sw=4 : # vim: set et sts=4 sw=4 :
+24 -19
View File
@@ -66,6 +66,7 @@ from . import header
from . import record from . import record
from .utils import INVALID_VALUE from .utils import INVALID_VALUE
class Dbf(object): class Dbf(object):
"""DBF accessor. """DBF accessor.
@@ -82,13 +83,13 @@ class Dbf(object):
""" """
__slots__ = ("name", "header", "stream", __slots__ = ("name", "header", "stream",
"_changed", "_new", "_ignore_errors") "_changed", "_new", "_ignore_errors")
HeaderClass = header.DbfHeader HeaderClass = header.DbfHeader
RecordClass = record.DbfRecord RecordClass = record.DbfRecord
INVALID_VALUE = INVALID_VALUE INVALID_VALUE = INVALID_VALUE
## initialization and creation helpers # initialization and creation helpers
def __init__(self, f, readOnly=False, new=False, ignoreErrors=False): def __init__(self, f, readOnly=False, new=False, ignoreErrors=False):
"""Initialize instance. """Initialize instance.
@@ -137,7 +138,7 @@ class Dbf(object):
self._new = bool(new) self._new = bool(new)
self._changed = False self._changed = False
## properties # properties
closed = property(lambda self: self.stream.closed) closed = property(lambda self: self.stream.closed)
recordCount = property(lambda self: self.header.recordCount) recordCount = property(lambda self: self.header.recordCount)
@@ -149,6 +150,7 @@ class Dbf(object):
def ignoreErrors(self, value): def ignoreErrors(self, value):
"""Update `ignoreErrors` flag on the header object and self""" """Update `ignoreErrors` flag on the header object and self"""
self.header.ignoreErrors = self._ignore_errors = bool(value) self.header.ignoreErrors = self._ignore_errors = bool(value)
ignoreErrors = property( ignoreErrors = property(
lambda self: self._ignore_errors, lambda self: self._ignore_errors,
ignoreErrors, ignoreErrors,
@@ -159,7 +161,7 @@ class Dbf(object):
""") """)
## protected methods # protected methods
def _fixIndex(self, index): def _fixIndex(self, index):
"""Return fixed index. """Return fixed index.
@@ -185,7 +187,7 @@ class Dbf(object):
raise IndexError("Record index out of range") raise IndexError("Record index out of range")
return index return index
## iterface methods # iterface methods
def close(self): def close(self):
self.flush() self.flush()
@@ -227,9 +229,9 @@ class Dbf(object):
self.header.addField(*defs) self.header.addField(*defs)
else: else:
raise TypeError("At least one record was added, " raise TypeError("At least one record was added, "
"structure can't be changed") "structure can't be changed")
## 'magic' methods (representation and sequence interface) # 'magic' methods (representation and sequence interface)
def __repr__(self): def __repr__(self):
return "Dbf stream '%s'\n" % self.stream + repr(self.header) return "Dbf stream '%s'\n" % self.stream + repr(self.header)
@@ -249,19 +251,20 @@ class Dbf(object):
self._changed = True self._changed = True
self._new = False self._new = False
#def __del__(self): # def __del__(self):
# """Flush stream upon deletion of the object.""" # """Flush stream upon deletion of the object."""
# self.flush() # self.flush()
def demoRead(filename): def demo_read(filename):
_dbf = Dbf(filename, True) _dbf = Dbf(filename, True)
for _rec in _dbf: for _rec in _dbf:
print() print()
print(repr(_rec)) print(repr(_rec))
_dbf.close() _dbf.close()
def demoCreate(filename):
def demo_create(filename):
_dbf = Dbf(filename, new=True) _dbf = Dbf(filename, new=True)
_dbf.addField( _dbf.addField(
("NAME", "C", 15), ("NAME", "C", 15),
@@ -270,10 +273,10 @@ def demoCreate(filename):
("BIRTHDATE", "D"), ("BIRTHDATE", "D"),
) )
for (_n, _s, _i, _b) in ( for (_n, _s, _i, _b) in (
("John", "Miller", "YC", (1981, 1, 2)), ("John", "Miller", "YC", (1981, 1, 2)),
("Andy", "Larkin", "AL", (1982, 3, 4)), ("Andy", "Larkin", "AL", (1982, 3, 4)),
("Bill", "Clinth", "", (1983, 5, 6)), ("Bill", "Clinth", "", (1983, 5, 6)),
("Bobb", "McNail", "", (1984, 7, 8)), ("Bobb", "McNail", "", (1984, 7, 8)),
): ):
_rec = _dbf.newRecord() _rec = _dbf.newRecord()
_rec["NAME"] = _n _rec["NAME"] = _n
@@ -284,10 +287,12 @@ def demoCreate(filename):
print(repr(_dbf)) print(repr(_dbf))
_dbf.close() _dbf.close()
if (__name__=='__main__'):
if __name__ == '__main__':
import sys import sys
_name = len(sys.argv) > 1 and sys.argv[1] or "county.dbf" _name = len(sys.argv) > 1 and sys.argv[1] or "county.dbf"
demoCreate(_name) demo_create(_name)
demoRead(_name) demo_read(_name)
# vim: set et sw=4 sts=4 : # vim: set et sw=4 sts=4 :
+15 -14
View File
@@ -29,6 +29,7 @@ from .fields import *
from .header import * from .header import *
from .record import * from .record import *
class _FieldDefinition(object): class _FieldDefinition(object):
"""Field definition. """Field definition.
@@ -145,28 +146,28 @@ class dbf_new(object):
_dbfStream.close() _dbfStream.close()
if (__name__=='__main__'): if __name__ == '__main__':
# create a new DBF-File # create a new DBF-File
dbfn=dbf_new() dbfn = dbf_new()
dbfn.add_field("name",'C',80) dbfn.add_field("name", 'C', 80)
dbfn.add_field("price",'N',10,2) dbfn.add_field("price", 'N', 10, 2)
dbfn.add_field("date",'D',8) dbfn.add_field("date", 'D', 8)
dbfn.write("tst.dbf") dbfn.write("tst.dbf")
# test new dbf # test new dbf
print("*** created tst.dbf: ***") print("*** created tst.dbf: ***")
dbft = Dbf('tst.dbf', readOnly=0) dbft = Dbf('tst.dbf', readOnly=0)
print(repr(dbft)) print(repr(dbft))
# add a record # add a record
rec=DbfRecord(dbft) rec = DbfRecord(dbft)
rec['name']='something' rec['name'] = 'something'
rec['price']=10.5 rec['price'] = 10.5
rec['date']=(2000,1,12) rec['date'] = (2000, 1, 12)
rec.store() rec.store()
# add another record # add another record
rec=DbfRecord(dbft) rec = DbfRecord(dbft)
rec['name']='foo and bar' rec['name'] = 'foo and bar'
rec['price']=12234 rec['price'] = 12234
rec['date']=(1992,7,15) rec['date'] = (1992, 7, 15)
rec.store() rec.store()
# show the records # show the records
@@ -175,7 +176,7 @@ if (__name__=='__main__'):
for i1 in range(len(dbft)): for i1 in range(len(dbft)):
rec = dbft[i1] rec = dbft[i1]
for fldName in dbft.fieldNames: for fldName in dbft.fieldNames:
print('%s:\t %s'%(fldName, rec[fldName])) print('%s:\t %s' % (fldName, rec[fldName]))
print() print()
dbft.close() dbft.close()
+2 -4
View File
@@ -71,10 +71,8 @@ class element:
for key, value in kwargs.iteritems( ): for key, value in kwargs.iteritems( ):
if value is not None: # when value is None that means stuff like <... checked> if value is not None: # when value is None that means stuff like <... checked>
key = key.strip('_') # strip this so class_ will mean class, etc. key = key.strip('_') # strip this so class_ will mean class, etc.
if key == 'http_equiv': # special cases, maybe change _ to - overall? if key in ['http_equiv', 'accept_charset']:
key = 'http-equiv' key.replace('_','-')
elif key == 'accept_charset':
key = 'accept-charset'
out = u"%s %s=\"%s\"" % ( out, key, escape( value ) ) out = u"%s %s=\"%s\"" % ( out, key, escape( value ) )
else: else:
out = u"%s %s" % ( out, key ) out = u"%s %s" % ( out, key )
+2 -2
View File
@@ -4,7 +4,7 @@ import sys
from antlr import EOF, CommonToken as Tok, TokenStream, TokenStreamException from antlr import EOF, CommonToken as Tok, TokenStream, TokenStreamException
import struct import struct
import ExcelFormulaParser import ExcelFormulaParser
from re import compile as recompile, match, LOCALE, UNICODE, IGNORECASE, VERBOSE from re import compile as recompile, match, UNICODE, IGNORECASE, VERBOSE
int_const_pattern = r"\d+\b" int_const_pattern = r"\d+\b"
@@ -51,7 +51,7 @@ pattern_type_tuples = (
_re = recompile( _re = recompile(
'(' + ')|('.join([i[0] for i in pattern_type_tuples]) + ')', '(' + ')|('.join([i[0] for i in pattern_type_tuples]) + ')',
VERBOSE+LOCALE+IGNORECASE) VERBOSE+IGNORECASE)
_toktype = [None] + [i[1] for i in pattern_type_tuples] _toktype = [None] + [i[1] for i in pattern_type_tuples]
# need dummy at start because re.MatchObject.lastindex counts from 1 # need dummy at start because re.MatchObject.lastindex counts from 1
+2 -2
View File
@@ -2,7 +2,7 @@ import sys
from .antlr import EOF, CommonToken as Tok, TokenStream, TokenStreamException from .antlr import EOF, CommonToken as Tok, TokenStream, TokenStreamException
import struct import struct
from . import ExcelFormulaParser from . import ExcelFormulaParser
from re import compile as recompile, match, LOCALE, UNICODE, IGNORECASE, VERBOSE from re import compile as recompile, match, UNICODE, IGNORECASE, VERBOSE
int_const_pattern = r"\d+\b" int_const_pattern = r"\d+\b"
@@ -49,7 +49,7 @@ pattern_type_tuples = (
_re = recompile( _re = recompile(
'(' + ')|('.join([i[0] for i in pattern_type_tuples]) + ')', '(' + ')|('.join([i[0] for i in pattern_type_tuples]) + ')',
VERBOSE+LOCALE+IGNORECASE) VERBOSE+IGNORECASE)
_toktype = [None] + [i[1] for i in pattern_type_tuples] _toktype = [None] + [i[1] for i in pattern_type_tuples]
# need dummy at start because re.MatchObject.lastindex counts from 1 # need dummy at start because re.MatchObject.lastindex counts from 1
+19 -20
View File
@@ -1,15 +1,16 @@
__all__ = ['Composer', 'ComposerError'] __all__ = ['Composer', 'ComposerError']
from error import MarkedYAMLError from error import MarkedYAMLError
from events import * from events import StreamEndEvent, StreamStartEvent, AliasEvent, SequenceEndEvent, SequenceStartEvent, MappingEndEvent,\
from nodes import * MappingStartEvent, ScalarEvent
from nodes import MappingNode, ScalarNode, SequenceNode
class ComposerError(MarkedYAMLError): class ComposerError(MarkedYAMLError):
pass pass
class Composer(object):
class Composer(object):
def __init__(self): def __init__(self):
self.anchors = {} self.anchors = {}
@@ -39,8 +40,8 @@ class Composer(object):
if not self.check_event(StreamEndEvent): if not self.check_event(StreamEndEvent):
event = self.get_event() event = self.get_event()
raise ComposerError("expected a single document in the stream", raise ComposerError("expected a single document in the stream",
document.start_mark, "but found another document", document.start_mark, "but found another document",
event.start_mark) event.start_mark)
# Drop the STREAM-END event. # Drop the STREAM-END event.
self.get_event() self.get_event()
@@ -66,15 +67,14 @@ class Composer(object):
anchor = event.anchor anchor = event.anchor
if anchor not in self.anchors: if anchor not in self.anchors:
raise ComposerError(None, None, "found undefined alias %r" raise ComposerError(None, None, "found undefined alias %r"
% anchor.encode('utf-8'), event.start_mark) % anchor.encode('utf-8'), event.start_mark)
return self.anchors[anchor] return self.anchors[anchor]
event = self.peek_event() event = self.peek_event()
anchor = event.anchor anchor = event.anchor
if anchor is not None: if anchor is not None and anchor in self.anchors:
if anchor in self.anchors:
raise ComposerError("found duplicate anchor %r; first occurence" raise ComposerError("found duplicate anchor %r; first occurence"
% anchor.encode('utf-8'), self.anchors[anchor].start_mark, % anchor.encode('utf-8'), self.anchors[anchor].start_mark,
"second occurence", event.start_mark) "second occurence", event.start_mark)
self.descend_resolver(parent, index) self.descend_resolver(parent, index)
if self.check_event(ScalarEvent): if self.check_event(ScalarEvent):
node = self.compose_scalar_node(anchor) node = self.compose_scalar_node(anchor)
@@ -91,7 +91,7 @@ class Composer(object):
if tag is None or tag == u'!': if tag is None or tag == u'!':
tag = self.resolve(ScalarNode, event.value, event.implicit) tag = self.resolve(ScalarNode, event.value, event.implicit)
node = ScalarNode(tag, event.value, node = ScalarNode(tag, event.value,
event.start_mark, event.end_mark, style=event.style) event.start_mark, event.end_mark, style=event.style)
if anchor is not None: if anchor is not None:
self.anchors[anchor] = node self.anchors[anchor] = node
return node return node
@@ -102,8 +102,8 @@ class Composer(object):
if tag is None or tag == u'!': if tag is None or tag == u'!':
tag = self.resolve(SequenceNode, None, start_event.implicit) tag = self.resolve(SequenceNode, None, start_event.implicit)
node = SequenceNode(tag, [], node = SequenceNode(tag, [],
start_event.start_mark, None, start_event.start_mark, None,
flow_style=start_event.flow_style) flow_style=start_event.flow_style)
if anchor is not None: if anchor is not None:
self.anchors[anchor] = node self.anchors[anchor] = node
index = 0 index = 0
@@ -120,20 +120,19 @@ class Composer(object):
if tag is None or tag == u'!': if tag is None or tag == u'!':
tag = self.resolve(MappingNode, None, start_event.implicit) tag = self.resolve(MappingNode, None, start_event.implicit)
node = MappingNode(tag, [], node = MappingNode(tag, [],
start_event.start_mark, None, start_event.start_mark, None,
flow_style=start_event.flow_style) flow_style=start_event.flow_style)
if anchor is not None: if anchor is not None:
self.anchors[anchor] = node self.anchors[anchor] = node
while not self.check_event(MappingEndEvent): while not self.check_event(MappingEndEvent):
#key_event = self.peek_event() # key_event = self.peek_event()
item_key = self.compose_node(node, None) item_key = self.compose_node(node, None)
#if item_key in node.value: # if item_key in node.value:
# raise ComposerError("while composing a mapping", start_event.start_mark, # raise ComposerError("while composing a mapping", start_event.start_mark,
# "found duplicate key", key_event.start_mark) # "found duplicate key", key_event.start_mark)
item_value = self.compose_node(node, item_key) item_value = self.compose_node(node, item_key)
#node.value[item_key] = item_value # node.value[item_key] = item_value
node.value.append((item_key, item_value)) node.value.append((item_key, item_value))
end_event = self.get_event() end_event = self.get_event()
node.end_mark = end_event.end_mark node.end_mark = end_event.end_mark
return node return node
+101 -94
View File
@@ -1,6 +1,5 @@
__all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor', __all__ = ['BaseConstructor', 'SafeConstructor', 'Constructor',
'ConstructorError'] 'ConstructorError']
from error import * from error import *
from nodes import * from nodes import *
@@ -12,13 +11,17 @@ try:
except NameError: except NameError:
from sets import Set as set from sets import Set as set
import binascii, re, sys, types import binascii
import re
import sys
import types
class ConstructorError(MarkedYAMLError): class ConstructorError(MarkedYAMLError):
pass pass
class BaseConstructor(object):
class BaseConstructor(object):
yaml_constructors = {} yaml_constructors = {}
yaml_multi_constructors = {} yaml_multi_constructors = {}
@@ -65,7 +68,7 @@ class BaseConstructor(object):
return self.constructed_objects[node] return self.constructed_objects[node]
if node in self.recursive_objects: if node in self.recursive_objects:
raise ConstructorError(None, None, raise ConstructorError(None, None,
"found unconstructable recursive node", node.start_mark) "found unconstructable recursive node", node.start_mark)
self.recursive_objects[node] = None self.recursive_objects[node] = None
constructor = None constructor = None
tag_suffix = None tag_suffix = None
@@ -110,23 +113,23 @@ class BaseConstructor(object):
def construct_scalar(self, node): def construct_scalar(self, node):
if not isinstance(node, ScalarNode): if not isinstance(node, ScalarNode):
raise ConstructorError(None, None, raise ConstructorError(None, None,
"expected a scalar node, but found %s" % node.id, "expected a scalar node, but found %s" % node.id,
node.start_mark) node.start_mark)
return node.value return node.value
def construct_sequence(self, node, deep=False): def construct_sequence(self, node, deep=False):
if not isinstance(node, SequenceNode): if not isinstance(node, SequenceNode):
raise ConstructorError(None, None, raise ConstructorError(None, None,
"expected a sequence node, but found %s" % node.id, "expected a sequence node, but found %s" % node.id,
node.start_mark) node.start_mark)
return [self.construct_object(child, deep=deep) return [self.construct_object(child, deep=deep)
for child in node.value] for child in node.value]
def construct_mapping(self, node, deep=False): def construct_mapping(self, node, deep=False):
if not isinstance(node, MappingNode): if not isinstance(node, MappingNode):
raise ConstructorError(None, None, raise ConstructorError(None, None,
"expected a mapping node, but found %s" % node.id, "expected a mapping node, but found %s" % node.id,
node.start_mark) node.start_mark)
mapping = {} mapping = {}
for key_node, value_node in node.value: for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep) key = self.construct_object(key_node, deep=deep)
@@ -134,7 +137,7 @@ class BaseConstructor(object):
hash(key) hash(key)
except TypeError, exc: except TypeError, exc:
raise ConstructorError("while constructing a mapping", node.start_mark, raise ConstructorError("while constructing a mapping", node.start_mark,
"found unacceptable key (%s)" % exc, key_node.start_mark) "found unacceptable key (%s)" % exc, key_node.start_mark)
value = self.construct_object(value_node, deep=deep) value = self.construct_object(value_node, deep=deep)
mapping[key] = value mapping[key] = value
return mapping return mapping
@@ -142,8 +145,8 @@ class BaseConstructor(object):
def construct_pairs(self, node, deep=False): def construct_pairs(self, node, deep=False):
if not isinstance(node, MappingNode): if not isinstance(node, MappingNode):
raise ConstructorError(None, None, raise ConstructorError(None, None,
"expected a mapping node, but found %s" % node.id, "expected a mapping node, but found %s" % node.id,
node.start_mark) node.start_mark)
pairs = [] pairs = []
for key_node, value_node in node.value: for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep) key = self.construct_object(key_node, deep=deep)
@@ -155,16 +158,18 @@ class BaseConstructor(object):
if not 'yaml_constructors' in cls.__dict__: if not 'yaml_constructors' in cls.__dict__:
cls.yaml_constructors = cls.yaml_constructors.copy() cls.yaml_constructors = cls.yaml_constructors.copy()
cls.yaml_constructors[tag] = constructor cls.yaml_constructors[tag] = constructor
add_constructor = classmethod(add_constructor) add_constructor = classmethod(add_constructor)
def add_multi_constructor(cls, tag_prefix, multi_constructor): def add_multi_constructor(cls, tag_prefix, multi_constructor):
if not 'yaml_multi_constructors' in cls.__dict__: if not 'yaml_multi_constructors' in cls.__dict__:
cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy() cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy()
cls.yaml_multi_constructors[tag_prefix] = multi_constructor cls.yaml_multi_constructors[tag_prefix] = multi_constructor
add_multi_constructor = classmethod(add_multi_constructor) add_multi_constructor = classmethod(add_multi_constructor)
class SafeConstructor(BaseConstructor):
class SafeConstructor(BaseConstructor):
def construct_scalar(self, node): def construct_scalar(self, node):
if isinstance(node, MappingNode): if isinstance(node, MappingNode):
for key_node, value_node in node.value: for key_node, value_node in node.value:
@@ -187,9 +192,9 @@ class SafeConstructor(BaseConstructor):
for subnode in value_node.value: for subnode in value_node.value:
if not isinstance(subnode, MappingNode): if not isinstance(subnode, MappingNode):
raise ConstructorError("while constructing a mapping", raise ConstructorError("while constructing a mapping",
node.start_mark, node.start_mark,
"expected a mapping for merging, but found %s" "expected a mapping for merging, but found %s"
% subnode.id, subnode.start_mark) % subnode.id, subnode.start_mark)
self.flatten_mapping(subnode) self.flatten_mapping(subnode)
submerge.append(subnode.value) submerge.append(subnode.value)
submerge.reverse() submerge.reverse()
@@ -197,8 +202,8 @@ class SafeConstructor(BaseConstructor):
merge.extend(value) merge.extend(value)
else: else:
raise ConstructorError("while constructing a mapping", node.start_mark, raise ConstructorError("while constructing a mapping", node.start_mark,
"expected a mapping or list of mappings for merging, but found %s" "expected a mapping or list of mappings for merging, but found %s"
% value_node.id, value_node.start_mark) % value_node.id, value_node.start_mark)
elif key_node.tag == u'tag:yaml.org,2002:value': elif key_node.tag == u'tag:yaml.org,2002:value':
key_node.tag = u'tag:yaml.org,2002:str' key_node.tag = u'tag:yaml.org,2002:str'
index += 1 index += 1
@@ -217,12 +222,12 @@ class SafeConstructor(BaseConstructor):
return None return None
bool_values = { bool_values = {
u'yes': True, u'yes': True,
u'no': False, u'no': False,
u'true': True, u'true': True,
u'false': False, u'false': False,
u'on': True, u'on': True,
u'off': False, u'off': False,
} }
def construct_yaml_bool(self, node): def construct_yaml_bool(self, node):
@@ -240,27 +245,27 @@ class SafeConstructor(BaseConstructor):
if value == '0': if value == '0':
return 0 return 0
elif value.startswith('0b'): elif value.startswith('0b'):
return sign*int(value[2:], 2) return sign * int(value[2:], 2)
elif value.startswith('0x'): elif value.startswith('0x'):
return sign*int(value[2:], 16) return sign * int(value[2:], 16)
elif value[0] == '0': elif value[0] == '0':
return sign*int(value, 8) return sign * int(value, 8)
elif ':' in value: elif ':' in value:
digits = [int(part) for part in value.split(':')] digits = [int(part) for part in value.split(':')]
digits.reverse() digits.reverse()
base = 1 base = 1
value = 0 value = 0
for digit in digits: for digit in digits:
value += digit*base value += digit * base
base *= 60 base *= 60
return sign*value return sign * value
else: else:
return sign*int(value) return sign * int(value)
inf_value = 1e300 inf_value = 1e300
while inf_value != inf_value*inf_value: while inf_value != inf_value * inf_value:
inf_value *= inf_value inf_value *= inf_value
nan_value = -inf_value/inf_value # Trying to make a quiet NaN (like C99). nan_value = -inf_value / inf_value # Trying to make a quiet NaN (like C99).
def construct_yaml_float(self, node): def construct_yaml_float(self, node):
value = str(self.construct_scalar(node)) value = str(self.construct_scalar(node))
@@ -271,7 +276,7 @@ class SafeConstructor(BaseConstructor):
if value[0] in '+-': if value[0] in '+-':
value = value[1:] value = value[1:]
if value == '.inf': if value == '.inf':
return sign*self.inf_value return sign * self.inf_value
elif value == '.nan': elif value == '.nan':
return self.nan_value return self.nan_value
elif ':' in value: elif ':' in value:
@@ -280,11 +285,11 @@ class SafeConstructor(BaseConstructor):
base = 1 base = 1
value = 0.0 value = 0.0
for digit in digits: for digit in digits:
value += digit*base value += digit * base
base *= 60 base *= 60
return sign*value return sign * value
else: else:
return sign*float(value) return sign * float(value)
def construct_yaml_binary(self, node): def construct_yaml_binary(self, node):
value = self.construct_scalar(node) value = self.construct_scalar(node)
@@ -292,10 +297,10 @@ class SafeConstructor(BaseConstructor):
return str(value).decode('base64') return str(value).decode('base64')
except (binascii.Error, UnicodeEncodeError), exc: except (binascii.Error, UnicodeEncodeError), exc:
raise ConstructorError(None, None, raise ConstructorError(None, None,
"failed to decode base64 data: %s" % exc, node.start_mark) "failed to decode base64 data: %s" % exc, node.start_mark)
timestamp_regexp = re.compile( timestamp_regexp = re.compile(
ur'''^(?P<year>[0-9][0-9][0-9][0-9]) ur'''^(?P<year>[0-9][0-9][0-9][0-9])
-(?P<month>[0-9][0-9]?) -(?P<month>[0-9][0-9]?)
-(?P<day>[0-9][0-9]?) -(?P<day>[0-9][0-9]?)
(?:(?:[Tt]|[ \t]+) (?:(?:[Tt]|[ \t]+)
@@ -343,16 +348,16 @@ class SafeConstructor(BaseConstructor):
yield omap yield omap
if not isinstance(node, SequenceNode): if not isinstance(node, SequenceNode):
raise ConstructorError("while constructing an ordered map", node.start_mark, raise ConstructorError("while constructing an ordered map", node.start_mark,
"expected a sequence, but found %s" % node.id, node.start_mark) "expected a sequence, but found %s" % node.id, node.start_mark)
for subnode in node.value: for subnode in node.value:
if not isinstance(subnode, MappingNode): if not isinstance(subnode, MappingNode):
raise ConstructorError("while constructing an ordered map", node.start_mark, raise ConstructorError("while constructing an ordered map", node.start_mark,
"expected a mapping of length 1, but found %s" % subnode.id, "expected a mapping of length 1, but found %s" % subnode.id,
subnode.start_mark) subnode.start_mark)
if len(subnode.value) != 1: if len(subnode.value) != 1:
raise ConstructorError("while constructing an ordered map", node.start_mark, raise ConstructorError("while constructing an ordered map", node.start_mark,
"expected a single mapping item, but found %d items" % len(subnode.value), "expected a single mapping item, but found %d items" % len(subnode.value),
subnode.start_mark) subnode.start_mark)
key_node, value_node = subnode.value[0] key_node, value_node = subnode.value[0]
key = self.construct_object(key_node) key = self.construct_object(key_node)
value = self.construct_object(value_node) value = self.construct_object(value_node)
@@ -364,16 +369,16 @@ class SafeConstructor(BaseConstructor):
yield pairs yield pairs
if not isinstance(node, SequenceNode): if not isinstance(node, SequenceNode):
raise ConstructorError("while constructing pairs", node.start_mark, raise ConstructorError("while constructing pairs", node.start_mark,
"expected a sequence, but found %s" % node.id, node.start_mark) "expected a sequence, but found %s" % node.id, node.start_mark)
for subnode in node.value: for subnode in node.value:
if not isinstance(subnode, MappingNode): if not isinstance(subnode, MappingNode):
raise ConstructorError("while constructing pairs", node.start_mark, raise ConstructorError("while constructing pairs", node.start_mark,
"expected a mapping of length 1, but found %s" % subnode.id, "expected a mapping of length 1, but found %s" % subnode.id,
subnode.start_mark) subnode.start_mark)
if len(subnode.value) != 1: if len(subnode.value) != 1:
raise ConstructorError("while constructing pairs", node.start_mark, raise ConstructorError("while constructing pairs", node.start_mark,
"expected a single mapping item, but found %d items" % len(subnode.value), "expected a single mapping item, but found %d items" % len(subnode.value),
subnode.start_mark) subnode.start_mark)
key_node, value_node = subnode.value[0] key_node, value_node = subnode.value[0]
key = self.construct_object(key_node) key = self.construct_object(key_node)
value = self.construct_object(value_node) value = self.construct_object(value_node)
@@ -415,62 +420,63 @@ class SafeConstructor(BaseConstructor):
def construct_undefined(self, node): def construct_undefined(self, node):
raise ConstructorError(None, None, raise ConstructorError(None, None,
"could not determine a constructor for the tag %r" % node.tag.encode('utf-8'), "could not determine a constructor for the tag %r" % node.tag.encode('utf-8'),
node.start_mark) node.start_mark)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:null', u'tag:yaml.org,2002:null',
SafeConstructor.construct_yaml_null) SafeConstructor.construct_yaml_null)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:bool', u'tag:yaml.org,2002:bool',
SafeConstructor.construct_yaml_bool) SafeConstructor.construct_yaml_bool)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:int', u'tag:yaml.org,2002:int',
SafeConstructor.construct_yaml_int) SafeConstructor.construct_yaml_int)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:float', u'tag:yaml.org,2002:float',
SafeConstructor.construct_yaml_float) SafeConstructor.construct_yaml_float)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:binary', u'tag:yaml.org,2002:binary',
SafeConstructor.construct_yaml_binary) SafeConstructor.construct_yaml_binary)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:timestamp', u'tag:yaml.org,2002:timestamp',
SafeConstructor.construct_yaml_timestamp) SafeConstructor.construct_yaml_timestamp)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:omap', u'tag:yaml.org,2002:omap',
SafeConstructor.construct_yaml_omap) SafeConstructor.construct_yaml_omap)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:pairs', u'tag:yaml.org,2002:pairs',
SafeConstructor.construct_yaml_pairs) SafeConstructor.construct_yaml_pairs)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:set', u'tag:yaml.org,2002:set',
SafeConstructor.construct_yaml_set) SafeConstructor.construct_yaml_set)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:str', u'tag:yaml.org,2002:str',
SafeConstructor.construct_yaml_str) SafeConstructor.construct_yaml_str)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:seq', u'tag:yaml.org,2002:seq',
SafeConstructor.construct_yaml_seq) SafeConstructor.construct_yaml_seq)
SafeConstructor.add_constructor( SafeConstructor.add_constructor(
u'tag:yaml.org,2002:map', u'tag:yaml.org,2002:map',
SafeConstructor.construct_yaml_map) SafeConstructor.construct_yaml_map)
SafeConstructor.add_constructor(None, SafeConstructor.add_constructor(None,
SafeConstructor.construct_undefined) SafeConstructor.construct_undefined)
class Constructor(SafeConstructor): class Constructor(SafeConstructor):
def construct_python_str(self, node): def construct_python_str(self, node):
return self.construct_scalar(node).encode('utf-8') return self.construct_scalar(node).encode('utf-8')
@@ -481,7 +487,7 @@ class Constructor(SafeConstructor):
return long(self.construct_yaml_int(node)) return long(self.construct_yaml_int(node))
def construct_python_complex(self, node): def construct_python_complex(self, node):
return complex(self.construct_scalar(node)) return complex(self.construct_scalar(node))
def construct_python_tuple(self, node): def construct_python_tuple(self, node):
return tuple(self.construct_sequence(node)) return tuple(self.construct_sequence(node))
@@ -489,21 +495,21 @@ class Constructor(SafeConstructor):
def find_python_module(self, name, mark): def find_python_module(self, name, mark):
if not name: if not name:
raise ConstructorError("while constructing a Python module", mark, raise ConstructorError("while constructing a Python module", mark,
"expected non-empty name appended to the tag", mark) "expected non-empty name appended to the tag", mark)
try: try:
__import__(name) __import__(name)
except ImportError, exc: except ImportError, exc:
raise ConstructorError("while constructing a Python module", mark, raise ConstructorError("while constructing a Python module", mark,
"cannot find module %r (%s)" % (name.encode('utf-8'), exc), mark) "cannot find module %r (%s)" % (name.encode('utf-8'), exc), mark)
return sys.modules[name] return sys.modules[name]
def find_python_name(self, name, mark): def find_python_name(self, name, mark):
if not name: if not name:
raise ConstructorError("while constructing a Python object", mark, raise ConstructorError("while constructing a Python object", mark,
"expected non-empty name appended to the tag", mark) "expected non-empty name appended to the tag", mark)
if u'.' in name: if u'.' in name:
# Python 2.4 only # Python 2.4 only
#module_name, object_name = name.rsplit('.', 1) # module_name, object_name = name.rsplit('.', 1)
items = name.split('.') items = name.split('.')
object_name = items.pop() object_name = items.pop()
module_name = '.'.join(items) module_name = '.'.join(items)
@@ -514,40 +520,41 @@ class Constructor(SafeConstructor):
__import__(module_name) __import__(module_name)
except ImportError, exc: except ImportError, exc:
raise ConstructorError("while constructing a Python object", mark, raise ConstructorError("while constructing a Python object", mark,
"cannot find module %r (%s)" % (module_name.encode('utf-8'), exc), mark) "cannot find module %r (%s)" % (module_name.encode('utf-8'), exc), mark)
module = sys.modules[module_name] module = sys.modules[module_name]
if not hasattr(module, object_name): if not hasattr(module, object_name):
raise ConstructorError("while constructing a Python object", mark, raise ConstructorError("while constructing a Python object", mark,
"cannot find %r in the module %r" % (object_name.encode('utf-8'), "cannot find %r in the module %r" % (object_name.encode('utf-8'),
module.__name__), mark) module.__name__), mark)
return getattr(module, object_name) return getattr(module, object_name)
def construct_python_name(self, suffix, node): def construct_python_name(self, suffix, node):
value = self.construct_scalar(node) value = self.construct_scalar(node)
if value: if value:
raise ConstructorError("while constructing a Python name", node.start_mark, raise ConstructorError("while constructing a Python name", node.start_mark,
"expected the empty value, but found %r" % value.encode('utf-8'), "expected the empty value, but found %r" % value.encode('utf-8'),
node.start_mark) node.start_mark)
return self.find_python_name(suffix, node.start_mark) return self.find_python_name(suffix, node.start_mark)
def construct_python_module(self, suffix, node): def construct_python_module(self, suffix, node):
value = self.construct_scalar(node) value = self.construct_scalar(node)
if value: if value:
raise ConstructorError("while constructing a Python module", node.start_mark, raise ConstructorError("while constructing a Python module", node.start_mark,
"expected the empty value, but found %r" % value.encode('utf-8'), "expected the empty value, but found %r" % value.encode('utf-8'),
node.start_mark) node.start_mark)
return self.find_python_module(suffix, node.start_mark) return self.find_python_module(suffix, node.start_mark)
class classobj: pass class classobj:
pass
def make_python_instance(self, suffix, node, def make_python_instance(self, suffix, node,
args=None, kwds=None, newobj=False): args=None, kwds=None, newobj=False):
if not args: if not args:
args = [] args = []
if not kwds: if not kwds:
kwds = {} kwds = {}
cls = self.find_python_name(suffix, node.start_mark) cls = self.find_python_name(suffix, node.start_mark)
if newobj and isinstance(cls, type(self.classobj)) \ if newobj and isinstance(cls, type(self.classobj)) \
and not args and not kwds: and not args and not kwds:
instance = self.classobj() instance = self.classobj()
instance.__class__ = cls instance.__class__ = cls
@@ -618,6 +625,7 @@ class Constructor(SafeConstructor):
def construct_python_object_new(self, suffix, node): def construct_python_object_new(self, suffix, node):
return self.construct_python_object_apply(suffix, node, newobj=True) return self.construct_python_object_apply(suffix, node, newobj=True)
Constructor.add_constructor( Constructor.add_constructor(
u'tag:yaml.org,2002:python/none', u'tag:yaml.org,2002:python/none',
Constructor.construct_yaml_null) Constructor.construct_yaml_null)
@@ -681,4 +689,3 @@ Constructor.add_multi_constructor(
Constructor.add_multi_constructor( Constructor.add_multi_constructor(
u'tag:yaml.org,2002:python/object/new:', u'tag:yaml.org,2002:python/object/new:',
Constructor.construct_python_object_new) Constructor.construct_python_object_new)
+15 -16
View File
@@ -1,15 +1,15 @@
__all__ = ['Composer', 'ComposerError'] __all__ = ['Composer', 'ComposerError']
from .error import MarkedYAMLError from .error import MarkedYAMLError
from .events import * from .events import *
from .nodes import * from .nodes import *
class ComposerError(MarkedYAMLError): class ComposerError(MarkedYAMLError):
pass pass
class Composer:
class Composer:
def __init__(self): def __init__(self):
self.anchors = {} self.anchors = {}
@@ -39,8 +39,8 @@ class Composer:
if not self.check_event(StreamEndEvent): if not self.check_event(StreamEndEvent):
event = self.get_event() event = self.get_event()
raise ComposerError("expected a single document in the stream", raise ComposerError("expected a single document in the stream",
document.start_mark, "but found another document", document.start_mark, "but found another document",
event.start_mark) event.start_mark)
# Drop the STREAM-END event. # Drop the STREAM-END event.
self.get_event() self.get_event()
@@ -66,15 +66,15 @@ class Composer:
anchor = event.anchor anchor = event.anchor
if anchor not in self.anchors: if anchor not in self.anchors:
raise ComposerError(None, None, "found undefined alias %r" raise ComposerError(None, None, "found undefined alias %r"
% anchor, event.start_mark) % anchor, event.start_mark)
return self.anchors[anchor] return self.anchors[anchor]
event = self.peek_event() event = self.peek_event()
anchor = event.anchor anchor = event.anchor
if anchor is not None: if anchor is not None:
if anchor in self.anchors: if anchor in self.anchors:
raise ComposerError("found duplicate anchor %r; first occurence" raise ComposerError("found duplicate anchor %r; first occurence"
% anchor, self.anchors[anchor].start_mark, % anchor, self.anchors[anchor].start_mark,
"second occurence", event.start_mark) "second occurence", event.start_mark)
self.descend_resolver(parent, index) self.descend_resolver(parent, index)
if self.check_event(ScalarEvent): if self.check_event(ScalarEvent):
node = self.compose_scalar_node(anchor) node = self.compose_scalar_node(anchor)
@@ -91,7 +91,7 @@ class Composer:
if tag is None or tag == '!': if tag is None or tag == '!':
tag = self.resolve(ScalarNode, event.value, event.implicit) tag = self.resolve(ScalarNode, event.value, event.implicit)
node = ScalarNode(tag, event.value, node = ScalarNode(tag, event.value,
event.start_mark, event.end_mark, style=event.style) event.start_mark, event.end_mark, style=event.style)
if anchor is not None: if anchor is not None:
self.anchors[anchor] = node self.anchors[anchor] = node
return node return node
@@ -102,8 +102,8 @@ class Composer:
if tag is None or tag == '!': if tag is None or tag == '!':
tag = self.resolve(SequenceNode, None, start_event.implicit) tag = self.resolve(SequenceNode, None, start_event.implicit)
node = SequenceNode(tag, [], node = SequenceNode(tag, [],
start_event.start_mark, None, start_event.start_mark, None,
flow_style=start_event.flow_style) flow_style=start_event.flow_style)
if anchor is not None: if anchor is not None:
self.anchors[anchor] = node self.anchors[anchor] = node
index = 0 index = 0
@@ -120,20 +120,19 @@ class Composer:
if tag is None or tag == '!': if tag is None or tag == '!':
tag = self.resolve(MappingNode, None, start_event.implicit) tag = self.resolve(MappingNode, None, start_event.implicit)
node = MappingNode(tag, [], node = MappingNode(tag, [],
start_event.start_mark, None, start_event.start_mark, None,
flow_style=start_event.flow_style) flow_style=start_event.flow_style)
if anchor is not None: if anchor is not None:
self.anchors[anchor] = node self.anchors[anchor] = node
while not self.check_event(MappingEndEvent): while not self.check_event(MappingEndEvent):
#key_event = self.peek_event() # key_event = self.peek_event()
item_key = self.compose_node(node, None) item_key = self.compose_node(node, None)
#if item_key in node.value: # if item_key in node.value:
# raise ComposerError("while composing a mapping", start_event.start_mark, # raise ComposerError("while composing a mapping", start_event.start_mark,
# "found duplicate key", key_event.start_mark) # "found duplicate key", key_event.start_mark)
item_value = self.compose_node(node, item_key) item_value = self.compose_node(node, item_key)
#node.value[item_key] = item_value # node.value[item_key] = item_value
node.value.append((item_key, item_value)) node.value.append((item_key, item_value))
end_event = self.get_event() end_event = self.get_event()
node.end_mark = end_event.end_mark node.end_mark = end_event.end_mark
return node return node
-1
View File
@@ -683,4 +683,3 @@ Constructor.add_multi_constructor(
Constructor.add_multi_constructor( Constructor.add_multi_constructor(
'tag:yaml.org,2002:python/object/new:', 'tag:yaml.org,2002:python/object/new:',
Constructor.construct_python_object_new) Constructor.construct_python_object_new)
+65 -88
View File
@@ -6,14 +6,14 @@ import json
import unittest import unittest
import sys import sys
import os import os
import datetime
import tablib import tablib
from tablib.compat import markup, unicode, is_py3 from tablib.compat import markup, unicode, is_py3
from tablib.core import Row from tablib.core import Row
class TablibTestCase(unittest.TestCase): class TablibTestCase(unittest.TestCase):
"""Tablib test cases.""" """Tablib test cases."""
@@ -35,12 +35,10 @@ class TablibTestCase(unittest.TestCase):
self.founders.append(self.george) self.founders.append(self.george)
self.founders.append(self.tom) self.founders.append(self.tom)
def tearDown(self): def tearDown(self):
"""Teardown.""" """Teardown."""
pass pass
def test_empty_append(self): def test_empty_append(self):
"""Verify append() correctly adds tuple with no headers.""" """Verify append() correctly adds tuple with no headers."""
new_row = (1, 2, 3) new_row = (1, 2, 3)
@@ -50,7 +48,6 @@ class TablibTestCase(unittest.TestCase):
self.assertTrue(data.width == len(new_row)) self.assertTrue(data.width == len(new_row))
self.assertTrue(data[0] == new_row) self.assertTrue(data[0] == new_row)
def test_empty_append_with_headers(self): def test_empty_append_with_headers(self):
"""Verify append() correctly detects mismatch of number of """Verify append() correctly detects mismatch of number of
headers and data. headers and data.
@@ -72,7 +69,6 @@ class TablibTestCase(unittest.TestCase):
self.assertRaises(tablib.InvalidDimensions, set_header_callable) self.assertRaises(tablib.InvalidDimensions, set_header_callable)
def test_add_column(self): def test_add_column(self):
"""Verify adding column works with/without headers.""" """Verify adding column works with/without headers."""
@@ -93,7 +89,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(data['age'], new_col) self.assertEqual(data['age'], new_col)
def test_add_column_no_data_no_headers(self): def test_add_column_no_data_no_headers(self):
"""Verify adding new column with no headers.""" """Verify adding new column with no headers."""
@@ -105,7 +100,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(data.width, 1) self.assertEqual(data.width, 1)
self.assertEqual(data.height, len(new_col)) self.assertEqual(data.height, len(new_col))
def test_add_column_with_header_ignored(self): def test_add_column_with_header_ignored(self):
"""Verify append_col() ignores the header if data.headers has """Verify append_col() ignores the header if data.headers has
not previously been set not previously been set
@@ -120,14 +114,13 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(data.height, len(new_col)) self.assertEqual(data.height, len(new_col))
self.assertEqual(data.headers, None) self.assertEqual(data.headers, None)
def test_add_column_with_header_and_headers_only_exist(self): def test_add_column_with_header_and_headers_only_exist(self):
"""Verify append_col() with header correctly detects mismatch when """Verify append_col() with header correctly detects mismatch when
headers exist but there is no existing row data headers exist but there is no existing row data
""" """
data.headers = ['first_name'] data.headers = ['first_name']
#no data # no data
new_col = ('allen') new_col = ('allen')
@@ -136,7 +129,6 @@ class TablibTestCase(unittest.TestCase):
self.assertRaises(tablib.InvalidDimensions, append_col_callable) self.assertRaises(tablib.InvalidDimensions, append_col_callable)
def test_add_column_with_header_and_data_exists(self): def test_add_column_with_header_and_data_exists(self):
"""Verify append_col() works when headers and rows exists""" """Verify append_col() works when headers and rows exists"""
@@ -152,7 +144,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(data['age'], new_col) self.assertEqual(data['age'], new_col)
self.assertEqual(len(data.headers), len(self.headers) + 1) self.assertEqual(len(data.headers), len(self.headers) + 1)
def test_add_callable_column(self): def test_add_callable_column(self):
"""Verify adding column with values specified as callable.""" """Verify adding column with values specified as callable."""
@@ -160,19 +151,17 @@ class TablibTestCase(unittest.TestCase):
self.founders.append_col(new_col, header='first_again') self.founders.append_col(new_col, header='first_again')
def test_header_slicing(self): def test_header_slicing(self):
"""Verify slicing by headers.""" """Verify slicing by headers."""
self.assertEqual(self.founders['first_name'], self.assertEqual(self.founders['first_name'],
[self.john[0], self.george[0], self.tom[0]]) [self.john[0], self.george[0], self.tom[0]])
self.assertEqual(self.founders['last_name'], self.assertEqual(self.founders['last_name'],
[self.john[1], self.george[1], self.tom[1]]) [self.john[1], self.george[1], self.tom[1]])
self.assertEqual(self.founders['gpa'], self.assertEqual(self.founders['gpa'],
[self.john[2], self.george[2], self.tom[2]]) [self.john[2], self.george[2], self.tom[2]])
def test_get_col(self): def test_get_col(self):
"""Verify getting columns by index""" """Verify getting columns by index"""
@@ -189,7 +178,6 @@ class TablibTestCase(unittest.TestCase):
self.founders.get_col(list(self.headers).index('gpa')), self.founders.get_col(list(self.headers).index('gpa')),
[self.john[2], self.george[2], self.tom[2]]) [self.john[2], self.george[2], self.tom[2]])
def test_data_slicing(self): def test_data_slicing(self):
"""Verify slicing by data.""" """Verify slicing by data."""
@@ -206,7 +194,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(self.founders[1:3], [self.george, self.tom]) self.assertEqual(self.founders[1:3], [self.george, self.tom])
self.assertEqual(self.founders[2:], [self.tom]) self.assertEqual(self.founders[2:], [self.tom])
def test_row_slicing(self): def test_row_slicing(self):
"""Verify Row's __getslice__ method. Issue #184.""" """Verify Row's __getslice__ method. Issue #184."""
@@ -218,7 +205,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(john[0:2], list(self.john[0:2])) self.assertEqual(john[0:2], list(self.john[0:2]))
self.assertEqual(john[0:-1], list(self.john[0:-1])) self.assertEqual(john[0:-1], list(self.john[0:-1]))
def test_delete(self): def test_delete(self):
"""Verify deleting from dataset works.""" """Verify deleting from dataset works."""
@@ -258,7 +244,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(csv, self.founders.csv) self.assertEqual(csv, self.founders.csv)
def test_tsv_export(self): def test_tsv_export(self):
"""Verify exporting dataset object as TSV.""" """Verify exporting dataset object as TSV."""
@@ -276,7 +261,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(tsv, self.founders.tsv) self.assertEqual(tsv, self.founders.tsv)
def test_html_export(self): def test_html_export(self):
"""HTML export""" """HTML export"""
@@ -288,7 +272,6 @@ class TablibTestCase(unittest.TestCase):
html.thead.close() html.thead.close()
for founder in self.founders: for founder in self.founders:
html.tr(markup.oneliner.td(founder)) html.tr(markup.oneliner.td(founder))
html.table.close() html.table.close()
@@ -296,7 +279,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(html, self.founders.html) self.assertEqual(html, self.founders.html)
def test_html_export_none_value(self): def test_html_export_none_value(self):
"""HTML export""" """HTML export"""
@@ -304,10 +286,10 @@ class TablibTestCase(unittest.TestCase):
html.table.open() html.table.open()
html.thead.open() html.thead.open()
html.tr(markup.oneliner.th(['foo','', 'bar'])) html.tr(markup.oneliner.th(['foo', '', 'bar']))
html.thead.close() html.thead.close()
html.tr(markup.oneliner.td(['foo','', 'bar'])) html.tr(markup.oneliner.td(['foo', '', 'bar']))
html.table.close() html.table.close()
html = str(html) html = str(html)
@@ -317,7 +299,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(html, d.html) self.assertEqual(html, d.html)
def test_latex_export(self): def test_latex_export(self):
"""LaTeX export""" """LaTeX export"""
@@ -341,17 +322,14 @@ class TablibTestCase(unittest.TestCase):
output = self.founders.latex output = self.founders.latex
self.assertEqual(output, expected) self.assertEqual(output, expected)
def test_latex_export_empty_dataset(self): def test_latex_export_empty_dataset(self):
self.assertTrue(tablib.Dataset().latex is not None) self.assertTrue(tablib.Dataset().latex is not None)
def test_latex_export_no_headers(self): def test_latex_export_no_headers(self):
d = tablib.Dataset() d = tablib.Dataset()
d.append(('one', 'two', 'three')) d.append(('one', 'two', 'three'))
self.assertTrue('one' in d.latex) self.assertTrue('one' in d.latex)
def test_latex_export_caption(self): def test_latex_export_caption(self):
d = tablib.Dataset() d = tablib.Dataset()
d.append(('one', 'two', 'three')) d.append(('one', 'two', 'three'))
@@ -360,7 +338,6 @@ class TablibTestCase(unittest.TestCase):
d.title = 'Title' d.title = 'Title'
self.assertTrue('\\caption{Title}' in d.latex) self.assertTrue('\\caption{Title}' in d.latex)
def test_latex_export_none_values(self): def test_latex_export_none_values(self):
headers = ['foo', None, 'bar'] headers = ['foo', None, 'bar']
d = tablib.Dataset(['foo', None, 'bar'], headers=headers) d = tablib.Dataset(['foo', None, 'bar'], headers=headers)
@@ -368,7 +345,6 @@ class TablibTestCase(unittest.TestCase):
self.assertTrue('foo' in output) self.assertTrue('foo' in output)
self.assertFalse('None' in output) self.assertFalse('None' in output)
def test_latex_escaping(self): def test_latex_escaping(self):
d = tablib.Dataset(['~', '^']) d = tablib.Dataset(['~', '^'])
output = d.latex output = d.latex
@@ -378,6 +354,15 @@ class TablibTestCase(unittest.TestCase):
self.assertFalse('^' in output) self.assertFalse('^' in output)
self.assertTrue('textasciicircum' in output) self.assertTrue('textasciicircum' in output)
def test_str_no_columns(self):
d = tablib.Dataset(['a', 1], ['b', 2], ['c', 3])
output = '%s' % d
self.assertEqual(output.splitlines(), [
'a|1',
'b|2',
'c|3'
])
def test_unicode_append(self): def test_unicode_append(self):
"""Passes in a single unicode character and exports.""" """Passes in a single unicode character and exports."""
@@ -385,8 +370,7 @@ class TablibTestCase(unittest.TestCase):
if is_py3: if is_py3:
new_row = ('å', 'é') new_row = ('å', 'é')
else: else:
exec("new_row = (u'å', u'é')") exec ("new_row = (u'å', u'é')")
data.append(new_row) data.append(new_row)
@@ -400,6 +384,25 @@ class TablibTestCase(unittest.TestCase):
data.html data.html
data.latex data.latex
def test_datetime_append(self):
"""Passes in a single datetime and a single date and exports."""
new_row = (
datetime.datetime.now(),
datetime.datetime.today(),
)
data.append(new_row)
data.json
data.yaml
data.csv
data.tsv
data.xls
data.xlsx
data.ods
data.html
data.latex
def test_book_export_no_exceptions(self): def test_book_export_no_exceptions(self):
"""Test that various exports don't error out.""" """Test that various exports don't error out."""
@@ -412,7 +415,7 @@ class TablibTestCase(unittest.TestCase):
book.xls book.xls
book.xlsx book.xlsx
book.ods book.ods
book.html
def test_json_import_set(self): def test_json_import_set(self):
"""Generate and import JSON set serialization.""" """Generate and import JSON set serialization."""
@@ -426,7 +429,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(json.loads(_json), json.loads(data.json)) self.assertEqual(json.loads(_json), json.loads(data.json))
def test_json_import_book(self): def test_json_import_book(self):
"""Generate and import JSON book serialization.""" """Generate and import JSON book serialization."""
data.append(self.john) data.append(self.john)
@@ -440,7 +442,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(json.loads(_json), json.loads(book.json)) self.assertEqual(json.loads(_json), json.loads(book.json))
def test_yaml_import_set(self): def test_yaml_import_set(self):
"""Generate and import YAML set serialization.""" """Generate and import YAML set serialization."""
data.append(self.john) data.append(self.john)
@@ -453,7 +454,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(_yaml, data.yaml) self.assertEqual(_yaml, data.yaml)
def test_yaml_import_book(self): def test_yaml_import_book(self):
"""Generate and import YAML book serialization.""" """Generate and import YAML book serialization."""
data.append(self.john) data.append(self.john)
@@ -467,7 +467,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(_yaml, book.yaml) self.assertEqual(_yaml, book.yaml)
def test_csv_import_set(self): def test_csv_import_set(self):
"""Generate and import CSV set serialization.""" """Generate and import CSV set serialization."""
data.append(self.john) data.append(self.john)
@@ -518,7 +517,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(_csv, data.get_csv(delimiter=';')) self.assertEqual(_csv, data.get_csv(delimiter=';'))
def test_csv_import_set_with_newlines(self): def test_csv_import_set_with_newlines(self):
"""Generate and import CSV set serialization when row values have """Generate and import CSV set serialization when row values have
newlines.""" newlines."""
@@ -533,7 +531,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(_csv, data.csv) self.assertEqual(_csv, data.csv)
def test_tsv_import_set(self): def test_tsv_import_set(self):
"""Generate and import TSV set serialization.""" """Generate and import TSV set serialization."""
data.append(self.john) data.append(self.john)
@@ -546,7 +543,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(_tsv, data.tsv) self.assertEqual(_tsv, data.tsv)
def test_dbf_import_set(self): def test_dbf_import_set(self):
data.append(self.john) data.append(self.john)
data.append(self.george) data.append(self.george)
@@ -555,7 +551,7 @@ class TablibTestCase(unittest.TestCase):
_dbf = data.dbf _dbf = data.dbf
data.dbf = _dbf data.dbf = _dbf
#self.assertEqual(_dbf, data.dbf) # self.assertEqual(_dbf, data.dbf)
try: try:
self.assertEqual(_dbf, data.dbf) self.assertEqual(_dbf, data.dbf)
except AssertionError: except AssertionError:
@@ -576,13 +572,13 @@ class TablibTestCase(unittest.TestCase):
data.headers = self.headers data.headers = self.headers
_regression_dbf = (b'\x03r\x06\x06\x03\x00\x00\x00\x81\x00\xab\x00\x00' _regression_dbf = (b'\x03r\x06\x06\x03\x00\x00\x00\x81\x00\xab\x00\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00\x00FIRST_NAME\x00C\x00\x00\x00\x00P\x00\x00\x00\x00\x00' b'\x00\x00\x00FIRST_NAME\x00C\x00\x00\x00\x00P\x00\x00\x00\x00\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LAST_NAME\x00\x00C\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LAST_NAME\x00\x00C\x00'
b'\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00GPA\x00\x00\x00\x00\x00\x00\x00\x00N\x00\x00\x00\x00\n' b'\x00\x00GPA\x00\x00\x00\x00\x00\x00\x00\x00N\x00\x00\x00\x00\n'
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r' b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r'
) )
_regression_dbf += b' John' + (b' ' * 75) _regression_dbf += b' John' + (b' ' * 75)
_regression_dbf += b' Adams' + (b' ' * 74) _regression_dbf += b' Adams' + (b' ' * 74)
_regression_dbf += b' 90.0000000' _regression_dbf += b' 90.0000000'
@@ -596,8 +592,8 @@ class TablibTestCase(unittest.TestCase):
if is_py3: if is_py3:
# If in python3, decode regression string to binary. # If in python3, decode regression string to binary.
#_regression_dbf = bytes(_regression_dbf, 'utf-8') # _regression_dbf = bytes(_regression_dbf, 'utf-8')
#_regression_dbf = _regression_dbf.replace(b'\n', b'\r') # _regression_dbf = _regression_dbf.replace(b'\n', b'\r')
pass pass
try: try:
@@ -606,23 +602,23 @@ class TablibTestCase(unittest.TestCase):
index = 0 index = 0
found_so_far = '' found_so_far = ''
for reg_char, data_char in zip(_regression_dbf, data.dbf): for reg_char, data_char in zip(_regression_dbf, data.dbf):
#found_so_far += chr(data_char) # found_so_far += chr(data_char)
if reg_char != data_char and index not in [1, 2, 3]: if reg_char != data_char and index not in [1, 2, 3]:
raise AssertionError( raise AssertionError(
'Failing at char %s: %s vs %s (found %s)' % ( 'Failing at char %s: %s vs %s (found %s)' % (
index, reg_char, data_char, found_so_far)) index, reg_char, data_char, found_so_far))
index += 1 index += 1
def test_dbf_format_detect(self): def test_dbf_format_detect(self):
"""Test the DBF format detection.""" """Test the DBF format detection."""
_dbf = (b'\x03r\x06\x03\x03\x00\x00\x00\x81\x00\xab\x00\x00' _dbf = (b'\x03r\x06\x03\x03\x00\x00\x00\x81\x00\xab\x00\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00\x00FIRST_NAME\x00C\x00\x00\x00\x00P\x00\x00\x00\x00\x00' b'\x00\x00\x00FIRST_NAME\x00C\x00\x00\x00\x00P\x00\x00\x00\x00\x00'
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LAST_NAME\x00\x00C\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00LAST_NAME\x00\x00C\x00'
b'\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00GPA\x00\x00\x00\x00\x00\x00\x00\x00N\x00\x00\x00\x00\n' b'\x00\x00GPA\x00\x00\x00\x00\x00\x00\x00\x00N\x00\x00\x00\x00\n'
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r' b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r'
) )
_dbf += b' John' + (b' ' * 75) _dbf += b' John' + (b' ' * 75)
_dbf += b' Adams' + (b' ' * 74) _dbf += b' Adams' + (b' ' * 74)
_dbf += b' 90.0000000' _dbf += b' 90.0000000'
@@ -664,7 +660,6 @@ class TablibTestCase(unittest.TestCase):
self.assertTrue(tablib.formats.csv.detect(_csv)) self.assertTrue(tablib.formats.csv.detect(_csv))
self.assertFalse(tablib.formats.csv.detect(_bunk)) self.assertFalse(tablib.formats.csv.detect(_bunk))
def test_tsv_format_detect(self): def test_tsv_format_detect(self):
"""Test TSV format detection.""" """Test TSV format detection."""
@@ -680,7 +675,6 @@ class TablibTestCase(unittest.TestCase):
self.assertTrue(tablib.formats.tsv.detect(_tsv)) self.assertTrue(tablib.formats.tsv.detect(_tsv))
self.assertFalse(tablib.formats.tsv.detect(_bunk)) self.assertFalse(tablib.formats.tsv.detect(_bunk))
def test_json_format_detect(self): def test_json_format_detect(self):
"""Test JSON format detection.""" """Test JSON format detection."""
@@ -692,7 +686,6 @@ class TablibTestCase(unittest.TestCase):
self.assertTrue(tablib.formats.json.detect(_json)) self.assertTrue(tablib.formats.json.detect(_json))
self.assertFalse(tablib.formats.json.detect(_bunk)) self.assertFalse(tablib.formats.json.detect(_bunk))
def test_yaml_format_detect(self): def test_yaml_format_detect(self):
"""Test YAML format detection.""" """Test YAML format detection."""
@@ -706,7 +699,6 @@ class TablibTestCase(unittest.TestCase):
self.assertFalse(tablib.formats.yaml.detect(_bunk)) self.assertFalse(tablib.formats.yaml.detect(_bunk))
self.assertFalse(tablib.formats.yaml.detect(_tsv)) self.assertFalse(tablib.formats.yaml.detect(_tsv))
def test_auto_format_detect(self): def test_auto_format_detect(self):
"""Test auto format detection.""" """Test auto format detection."""
@@ -722,7 +714,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(tablib.detect_format(_json), 'json') self.assertEqual(tablib.detect_format(_json), 'json')
self.assertEqual(tablib.detect_format(_bunk), None) self.assertEqual(tablib.detect_format(_bunk), None)
def test_transpose(self): def test_transpose(self):
"""Transpose a dataset.""" """Transpose a dataset."""
@@ -731,11 +722,11 @@ class TablibTestCase(unittest.TestCase):
second_row = transposed_founders[1] second_row = transposed_founders[1]
self.assertEqual(transposed_founders.headers, self.assertEqual(transposed_founders.headers,
["first_name","John", "George", "Thomas"]) ["first_name", "John", "George", "Thomas"])
self.assertEqual(first_row, self.assertEqual(first_row,
("last_name","Adams", "Washington", "Jefferson")) ("last_name", "Adams", "Washington", "Jefferson"))
self.assertEqual(second_row, self.assertEqual(second_row,
("gpa",90, 67, 50)) ("gpa", 90, 67, 50))
def test_transpose_multiple_headers(self): def test_transpose_multiple_headers(self):
@@ -746,7 +737,6 @@ class TablibTestCase(unittest.TestCase):
data.append(('John', 'Tyler', 71)) data.append(('John', 'Tyler', 71))
self.assertEqual(data.transpose().transpose().dict, data.dict) self.assertEqual(data.transpose().transpose().dict, data.dict)
def test_row_stacking(self): def test_row_stacking(self):
"""Row stacking.""" """Row stacking."""
@@ -758,12 +748,10 @@ class TablibTestCase(unittest.TestCase):
row_stacked = self.founders.stack(to_join) row_stacked = self.founders.stack(to_join)
for column in row_stacked.headers: for column in row_stacked.headers:
original_data = self.founders[column] original_data = self.founders[column]
expected_data = original_data + original_data expected_data = original_data + original_data
self.assertEqual(row_stacked[column], expected_data) self.assertEqual(row_stacked[column], expected_data)
def test_column_stacking(self): def test_column_stacking(self):
"""Column stacking""" """Column stacking"""
@@ -775,14 +763,12 @@ class TablibTestCase(unittest.TestCase):
column_stacked = self.founders.stack_cols(to_join) column_stacked = self.founders.stack_cols(to_join)
for index, row in enumerate(column_stacked): for index, row in enumerate(column_stacked):
original_data = self.founders[index] original_data = self.founders[index]
expected_data = original_data + original_data expected_data = original_data + original_data
self.assertEqual(row, expected_data) self.assertEqual(row, expected_data)
self.assertEqual(column_stacked[0], self.assertEqual(column_stacked[0],
("John", "Adams", 90, "John", "Adams", 90)) ("John", "Adams", 90, "John", "Adams", 90))
def test_sorting(self): def test_sorting(self):
"""Sort columns.""" """Sort columns."""
@@ -801,7 +787,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(second_row, expected_second) self.assertEqual(second_row, expected_second)
self.assertEqual(third_row, expected_third) self.assertEqual(third_row, expected_third)
def test_remove_duplicates(self): def test_remove_duplicates(self):
"""Unique Rows.""" """Unique Rows."""
@@ -820,7 +805,6 @@ class TablibTestCase(unittest.TestCase):
self.assertEqual(self.founders[2], self.tom) self.assertEqual(self.founders[2], self.tom)
self.assertEqual(self.founders.height, 3) self.assertEqual(self.founders.height, 3)
def test_wipe(self): def test_wipe(self):
"""Purge a dataset.""" """Purge a dataset."""
@@ -837,12 +821,11 @@ class TablibTestCase(unittest.TestCase):
self.assertTrue(data.width == len(new_row)) self.assertTrue(data.width == len(new_row))
self.assertTrue(data[0] == new_row) self.assertTrue(data[0] == new_row)
def test_subset(self): def test_subset(self):
"""Create a subset of a dataset""" """Create a subset of a dataset"""
rows = (0, 2) rows = (0, 2)
columns = ('first_name','gpa') columns = ('first_name', 'gpa')
data.headers = self.headers data.headers = self.headers
@@ -850,14 +833,13 @@ class TablibTestCase(unittest.TestCase):
data.append(self.george) data.append(self.george)
data.append(self.tom) data.append(self.tom)
#Verify data is truncated # Verify data is truncated
subset = data.subset(rows=rows, cols=columns) subset = data.subset(rows=rows, cols=columns)
self.assertEqual(type(subset), tablib.Dataset) self.assertEqual(type(subset), tablib.Dataset)
self.assertEqual(subset.headers, list(columns)) self.assertEqual(subset.headers, list(columns))
self.assertEqual(subset._data[0].list, ['John', 90]) self.assertEqual(subset._data[0].list, ['John', 90])
self.assertEqual(subset._data[1].list, ['Thomas', 50]) self.assertEqual(subset._data[1].list, ['Thomas', 50])
def test_formatters(self): def test_formatters(self):
"""Confirm formatters are being triggered.""" """Confirm formatters are being triggered."""
@@ -877,8 +859,7 @@ class TablibTestCase(unittest.TestCase):
if sys.version_info[0] > 2: if sys.version_info[0] > 2:
data.append(['\xfc', '\xfd']) data.append(['\xfc', '\xfd'])
else: else:
exec("data.append([u'\xfc', u'\xfd'])") exec ("data.append([u'\xfc', u'\xfd'])")
data.csv data.csv
@@ -895,7 +876,6 @@ class TablibTestCase(unittest.TestCase):
csv_first_name = data[headers[0]] csv_first_name = data[headers[0]]
self.assertEqual(orig_first_name, csv_first_name) self.assertEqual(orig_first_name, csv_first_name)
def test_csv_column_delete(self): def test_csv_column_delete(self):
"""Build up a CSV and test deleting a column""" """Build up a CSV and test deleting a column"""
@@ -929,7 +909,6 @@ class TablibTestCase(unittest.TestCase):
self.founders.append(('Old', 'Man', 100500)) self.founders.append(('Old', 'Man', 100500))
self.assertEqual('first_name|last_name |gpa ', unicode(self.founders).split('\n')[0]) self.assertEqual('first_name|last_name |gpa ', unicode(self.founders).split('\n')[0])
def test_databook_add_sheet_accepts_only_dataset_instances(self): def test_databook_add_sheet_accepts_only_dataset_instances(self):
class NotDataset(object): class NotDataset(object):
def append(self, item): def append(self, item):
@@ -940,7 +919,6 @@ class TablibTestCase(unittest.TestCase):
self.assertRaises(tablib.InvalidDatasetType, book.add_sheet, dataset) self.assertRaises(tablib.InvalidDatasetType, book.add_sheet, dataset)
def test_databook_add_sheet_accepts_dataset_subclasses(self): def test_databook_add_sheet_accepts_dataset_subclasses(self):
class DatasetSubclass(tablib.Dataset): class DatasetSubclass(tablib.Dataset):
pass pass
@@ -955,7 +933,6 @@ class TablibTestCase(unittest.TestCase):
except tablib.InvalidDatasetType: except tablib.InvalidDatasetType:
self.fail("Subclass of tablib.Dataset should be accepted by Databook.add_sheet") self.fail("Subclass of tablib.Dataset should be accepted by Databook.add_sheet")
def test_csv_formatter_support_kwargs(self): def test_csv_formatter_support_kwargs(self):
"""Test CSV import and export with formatter configuration.""" """Test CSV import and export with formatter configuration."""
data.append(self.john) data.append(self.john)
+1 -1
View File
@@ -4,7 +4,7 @@
# and then run "tox" from this directory. # and then run "tox" from this directory.
[tox] [tox]
envlist = py26, py27, py32, py33, py34, pypy envlist = py26, py27, py32, py33, py34, py35, py36, pypy
[testenv] [testenv]
commands = python setup.py test commands = python setup.py test