diff --git a/fabfile.py b/fabfile.py index e2b0f8d..1e25b13 100644 --- a/fabfile.py +++ b/fabfile.py @@ -3,15 +3,15 @@ from fabric.api import * def scrub(): - """ Death to the bytecode! """ - local('rm -fr dist build') - local("find . -name \"*.pyc\" -exec rm '{}' ';'") + """ Death to the bytecode! """ + local('rm -fr dist build') + local("find . -name \"*.pyc\" -exec rm '{}' ';'") def docs(): - """Build docs.""" - os.system('make dirhtml') - os.chdir('_build/dirhtml') - os.system('sphinxtogithub .') - os.system('git add -A') - os.system('git commit -m \'documentation update\'') - os.system('git push origin gh-pages') \ No newline at end of file + """Build docs.""" + os.system('make dirhtml') + os.chdir('_build/dirhtml') + os.system('sphinxtogithub .') + os.system('git add -A') + os.system('git commit -m \'documentation update\'') + os.system('git push origin gh-pages') \ No newline at end of file diff --git a/setup.py b/setup.py index c851751..57cee3c 100644 --- a/setup.py +++ b/setup.py @@ -8,43 +8,43 @@ from distutils.core import setup def publish(): - """Publish to PyPi""" - os.system("python setup.py sdist upload") + """Publish to PyPi""" + os.system("python setup.py sdist upload") if sys.argv[-1] == "publish": - publish() - sys.exit() + publish() + sys.exit() required = [] setup( - name='tablib', - version='0.9.3', - description='Format agnostic tabular data library (XLS, JSON, YAML, CSV)', - long_description=open('README.rst').read() + '\n\n' + - open('HISTORY.rst').read(), - author='Kenneth Reitz', - author_email='me@kennethreitz.com', - url='http://tablib.org', - packages= [ - 'tablib', 'tablib.formats', - 'tablib.packages', - 'tablib.packages.simplejson', - 'tablib.packages.xlwt', - 'tablib.packages.yaml', - ], - install_requires=required, - license='MIT', - classifiers=( - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Natural Language :: English', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python', + name='tablib', + version='0.9.3', + description='Format agnostic tabular data library (XLS, JSON, YAML, CSV)', + long_description=open('README.rst').read() + '\n\n' + + open('HISTORY.rst').read(), + author='Kenneth Reitz', + author_email='me@kennethreitz.com', + url='http://tablib.org', + packages= [ + 'tablib', 'tablib.formats', + 'tablib.packages', + 'tablib.packages.simplejson', + 'tablib.packages.xlwt', + 'tablib.packages.yaml', + ], + install_requires=required, + license='MIT', + classifiers=( + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Natural Language :: English', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python', # 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - # 'Programming Language :: Python :: 3.0', - # 'Programming Language :: Python :: 3.1', - ), + 'Programming Language :: Python :: 2.7', + # 'Programming Language :: Python :: 3.0', + # 'Programming Language :: Python :: 3.1', + ), ) diff --git a/tablib/__init__.py b/tablib/__init__.py index 3f23850..c2205b6 100644 --- a/tablib/__init__.py +++ b/tablib/__init__.py @@ -2,7 +2,7 @@ """ from tablib.core import ( - Databook, Dataset, detect, import_set, - InvalidDatasetType, InvalidDimensions, UnsupportedFormat + Databook, Dataset, detect, import_set, + InvalidDatasetType, InvalidDimensions, UnsupportedFormat ) diff --git a/tablib/core.py b/tablib/core.py index a42f1f8..78c7481 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -24,73 +24,73 @@ __copyright__ = 'Copyright 2011 Kenneth Reitz' class Row(object): - """Internal Row object. Mainly used for filtering.""" + """Internal Row object. Mainly used for filtering.""" - __slots__ = ['tuple', '_row', 'tags'] + __slots__ = ['tuple', '_row', 'tags'] - def __init__(self, row=list(), tags=list()): - self._row = list(row) - self.tags = list(tags) + def __init__(self, row=list(), tags=list()): + self._row = list(row) + self.tags = list(tags) - def __iter__(self): - return (col for col in self._row) + def __iter__(self): + return (col for col in self._row) - def __len__(self): - return len(self._row) + def __len__(self): + return len(self._row) - def __repr__(self): - return repr(self._row) + def __repr__(self): + return repr(self._row) - def __getslice__(self, i, j): - return self._row[i,j] + def __getslice__(self, i, j): + return self._row[i,j] - def __getitem__(self, i): - return self._row[i] + def __getitem__(self, i): + return self._row[i] - def __setitem__(self, i, value): - self._row[i] = value + def __setitem__(self, i, value): + self._row[i] = value - def __delitem__(self, i): - del self._row[i] + def __delitem__(self, i): + del self._row[i] - def __getstate__(self): - return {slot: [getattr(self, slot) for slot in self.__slots__]} + def __getstate__(self): + return {slot: [getattr(self, slot) for slot in self.__slots__]} - def __setstate__(self, state): - for (k, v) in state.items(): setattr(self, k, v) + def __setstate__(self, state): + for (k, v) in state.items(): setattr(self, k, v) - def append(self, value): - self._row.append(value) + def append(self, value): + self._row.append(value) - def insert(self, index, value): - self._row.insert(index, value) + def insert(self, index, value): + self._row.insert(index, value) - def __contains__(self, item): - return (item in self._row) + def __contains__(self, item): + return (item in self._row) - @property - def tuple(self): - '''Tuple representation of :class:`Row`.''' - return tuple(self._row) + @property + def tuple(self): + '''Tuple representation of :class:`Row`.''' + return tuple(self._row) - @property - def list(self): - '''List representation of :class:`Row`.''' - return list(self._row) + @property + def list(self): + '''List representation of :class:`Row`.''' + return list(self._row) - def has_tag(self, tag): - """Returns true if current row contains tag.""" + def has_tag(self, tag): + """Returns true if current row contains tag.""" - if tag == None: - return False - elif isinstance(tag, basestring): - return (tag in self.tags) - else: - return True if len(set(tag) & set(self.tags)) else False + if tag == None: + return False + elif isinstance(tag, basestring): + return (tag in self.tags) + else: + return True if len(set(tag) & set(self.tags)) else False class Dataset(object): - """The :class:`Dataset` object is the heart of Tablib. It provides all core + """The :class:`Dataset` object is the heart of Tablib. It provides all core functionality. Usually you create a :class:`Dataset` instance in your main module, and append @@ -121,189 +121,189 @@ class Dataset(object): defined within the :class:`Dataset` object. To add support for a new format, see :ref:`Adding New Formats `. - """ + """ - def __init__(self, *args, **kwargs): - self._data = list(Row(arg) for arg in args) - self.__headers = None + def __init__(self, *args, **kwargs): + self._data = list(Row(arg) for arg in args) + self.__headers = None - # ('title', index) tuples - self._separators = [] + # ('title', index) tuples + self._separators = [] - try: - self.headers = kwargs['headers'] - except KeyError: - self.headers = None + try: + self.headers = kwargs['headers'] + except KeyError: + self.headers = None - try: - self.title = kwargs['title'] - except KeyError: - self.title = None + try: + self.title = kwargs['title'] + except KeyError: + self.title = None - self._register_formats() + self._register_formats() - def __len__(self): - return self.height + def __len__(self): + return self.height - def __getitem__(self, key): - if isinstance(key, basestring): - if key in self.headers: - pos = self.headers.index(key) # get 'key' index from each data - return [row[pos] for row in self._data] - else: - raise KeyError - else: - _results = self._data[key] - if isinstance(_results, Row): - return _results.tuple - else: - return [result.tuple for result in _results] + def __getitem__(self, key): + if isinstance(key, basestring): + if key in self.headers: + pos = self.headers.index(key) # get 'key' index from each data + return [row[pos] for row in self._data] + else: + raise KeyError + else: + _results = self._data[key] + if isinstance(_results, Row): + return _results.tuple + else: + return [result.tuple for result in _results] - def __setitem__(self, key, value): - self._validate(value) - self._data[key] = Row(value) + def __setitem__(self, key, value): + self._validate(value) + self._data[key] = Row(value) - def __delitem__(self, key): - if isinstance(key, basestring): + def __delitem__(self, key): + if isinstance(key, basestring): - if key in self.headers: + if key in self.headers: - pos = self.headers.index(key) - del self.headers[pos] + pos = self.headers.index(key) + del self.headers[pos] - for i, row in enumerate(self._data): + for i, row in enumerate(self._data): - del row[pos] - self._data[i] = row - else: - raise KeyError - else: - del self._data[key] + del row[pos] + self._data[i] = row + else: + raise KeyError + else: + del self._data[key] - def __repr__(self): - try: - return '<%s dataset>' % (self.title.lower()) - except AttributeError: - return '' + def __repr__(self): + try: + return '<%s dataset>' % (self.title.lower()) + except AttributeError: + return '' - @classmethod - def _register_formats(cls): - """Adds format properties.""" - for fmt in formats.available: - try: - try: - setattr(cls, fmt.title, property(fmt.export_set, fmt.import_set)) - except AttributeError: - setattr(cls, fmt.title, property(fmt.export_set)) + @classmethod + def _register_formats(cls): + """Adds format properties.""" + for fmt in formats.available: + try: + try: + setattr(cls, fmt.title, property(fmt.export_set, fmt.import_set)) + except AttributeError: + setattr(cls, fmt.title, property(fmt.export_set)) - except AttributeError: - pass + except AttributeError: + pass - def _validate(self, row=None, col=None, safety=False): - """Assures size of every row in dataset is of proper proportions.""" - if row: - is_valid = (len(row) == self.width) if self.width else True - elif col: - if len(col) < 1: - is_valid = True - else: - is_valid = (len(col) == self.height) if self.height else True - else: - is_valid = all((len(x) == self.width for x in self._data)) + def _validate(self, row=None, col=None, safety=False): + """Assures size of every row in dataset is of proper proportions.""" + if row: + is_valid = (len(row) == self.width) if self.width else True + elif col: + if len(col) < 1: + is_valid = True + else: + is_valid = (len(col) == self.height) if self.height else True + else: + is_valid = all((len(x) == self.width for x in self._data)) - if is_valid: - return True - else: - if not safety: - raise InvalidDimensions - return False + if is_valid: + return True + else: + if not safety: + raise InvalidDimensions + return False - def _package(self, dicts=True): - """Packages Dataset into lists of dictionaries for transmission.""" + def _package(self, dicts=True): + """Packages Dataset into lists of dictionaries for transmission.""" - if self.headers: - if dicts: - data = [dict(zip(self.headers, data_row)) for data_row in self ._data] - else: - data = [list(self.headers)] + list(self._data) - else: - data = [list(row) for row in self._data] + if self.headers: + if dicts: + data = [dict(zip(self.headers, data_row)) for data_row in self ._data] + else: + data = [list(self.headers)] + list(self._data) + else: + data = [list(row) for row in self._data] - return data + return data - def _clean_col(self, col): - """Prepares the given column for insert/append.""" + def _clean_col(self, col): + """Prepares the given column for insert/append.""" - col = list(col) + col = list(col) - if self.headers: - header = [col.pop(0)] - else: - header = [] + if self.headers: + header = [col.pop(0)] + else: + header = [] - if len(col) == 1 and callable(col[0]): - col = map(col[0], self._data) - col = tuple(header + col) + if len(col) == 1 and callable(col[0]): + col = map(col[0], self._data) + col = tuple(header + col) - return col + return col - @property - def height(self): - """The number of rows currently in the :class:`Dataset`. - Cannot be directly modified. - """ - return len(self._data) + @property + def height(self): + """The number of rows currently in the :class:`Dataset`. + Cannot be directly modified. + """ + return len(self._data) - @property - def width(self): - """The number of columns currently in the :class:`Dataset`. - Cannot be directly modified. - """ + @property + def width(self): + """The number of columns currently in the :class:`Dataset`. + Cannot be directly modified. + """ - try: - return len(self._data[0]) - except IndexError: - try: - return len(self.headers) - except TypeError: - return 0 + try: + return len(self._data[0]) + except IndexError: + try: + return len(self.headers) + except TypeError: + return 0 - def _get_headers(self): - """An *optional* list of strings to be used for header rows and attribute names. + def _get_headers(self): + """An *optional* list of strings to be used for header rows and attribute names. This must be set manually. The given list length must equal :class:`Dataset.width`. - """ - return self.__headers + """ + return self.__headers - def _set_headers(self, collection): - """Validating headers setter.""" - self._validate(collection) - if collection: - try: - self.__headers = list(collection) - except TypeError: - raise TypeError - else: - self.__headers = None + def _set_headers(self, collection): + """Validating headers setter.""" + self._validate(collection) + if collection: + try: + self.__headers = list(collection) + except TypeError: + raise TypeError + else: + self.__headers = None - headers = property(_get_headers, _set_headers) + headers = property(_get_headers, _set_headers) - def _get_dict(self): - """A JSON representation of the :class:`Dataset` object. If headers have been + def _get_dict(self): + """A JSON representation of the :class:`Dataset` object. If headers have been set, a JSON list of objects will be returned. If no headers have been set, a JSON list of lists (rows) will be returned instead. @@ -312,155 +312,155 @@ class Dataset(object): data = tablib.Dataset() data.json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]' - """ - return self._package() + """ + return self._package() - def _set_dict(self, pickle): - """A native Python representation of the Dataset object. If headers have been - set, a list of Python dictionaries will be returned. If no headers have been - set, a list of tuples (rows) will be returned instead. + def _set_dict(self, pickle): + """A native Python representation of the Dataset object. If headers have been + set, a list of Python dictionaries will be returned. If no headers have been + set, a list of tuples (rows) will be returned instead. - A dataset object can also be imported by setting the :class:`Dataset.dict` attribute. :: + A dataset object can also be imported by setting the :class:`Dataset.dict` attribute. :: - data = tablib.Dataset() - data.dict = [{'age': 90, 'first_name': 'Kenneth', 'last_name': 'Reitz'}] + data = tablib.Dataset() + data.dict = [{'age': 90, 'first_name': 'Kenneth', 'last_name': 'Reitz'}] - """ - if not len(pickle): - return + """ + if not len(pickle): + return - # if list of rows - if isinstance(pickle[0], list): - self.wipe() - for row in pickle: - self.append(Row(row)) + # if list of rows + if isinstance(pickle[0], list): + self.wipe() + for row in pickle: + self.append(Row(row)) - # if list of objects - elif isinstance(pickle[0], dict): - self.wipe() - self.headers = pickle[0].keys() - for row in pickle: - self.append(Row(row.values())) - else: - raise UnsupportedFormat + # if list of objects + elif isinstance(pickle[0], dict): + self.wipe() + self.headers = pickle[0].keys() + for row in pickle: + self.append(Row(row.values())) + else: + raise UnsupportedFormat - dict = property(_get_dict, _set_dict) + dict = property(_get_dict, _set_dict) - @property - def xls(): - """An Excel Spreadsheet representation of the :class:`Dataset` object, with :ref:`seperators`. Cannot be set. + @property + def xls(): + """An Excel Spreadsheet representation of the :class:`Dataset` object, with :ref:`seperators`. Cannot be set. - .. admonition:: Binary Warning + .. admonition:: Binary Warning - :class:`Dataset.xls` contains binary data, so make sure to write in binary mode:: + :class:`Dataset.xls` contains binary data, so make sure to write in binary mode:: - with open('output.xls', 'wb') as f: - f.write(data.xls)' - """ - pass + with open('output.xls', 'wb') as f: + f.write(data.xls)' + """ + pass - @property - def csv(): - """A CSV representation of the :class:`Dataset` object. The top row will contain - headers, if they have been set. Otherwise, the top row will contain - the first row of the dataset. + @property + def csv(): + """A CSV representation of the :class:`Dataset` object. The top row will contain + headers, if they have been set. Otherwise, the top row will contain + the first row of the dataset. - A dataset object can also be imported by setting the :class:`Dataset.csv` attribute. :: + A dataset object can also be imported by setting the :class:`Dataset.csv` attribute. :: - data = tablib.Dataset() - data.csv = 'age, first_name, last_name\\n90, John, Adams' + data = tablib.Dataset() + data.csv = 'age, first_name, last_name\\n90, John, Adams' - Import assumes (for now) that headers exist. - """ - pass + Import assumes (for now) that headers exist. + """ + pass - @property - def tsv(): - """A TSV representation of the :class:`Dataset` object. The top row will contain - headers, if they have been set. Otherwise, the top row will contain - the first row of the dataset. + @property + def tsv(): + """A TSV representation of the :class:`Dataset` object. The top row will contain + headers, if they have been set. Otherwise, the top row will contain + the first row of the dataset. - A dataset object can also be imported by setting the :class:`Dataset.tsv` attribute. :: + A dataset object can also be imported by setting the :class:`Dataset.tsv` attribute. :: - data = tablib.Dataset() - data.tsv = 'age\tfirst_name\tlast_name\\n90\tJohn\tAdams' + data = tablib.Dataset() + data.tsv = 'age\tfirst_name\tlast_name\\n90\tJohn\tAdams' - Import assumes (for now) that headers exist. - """ - - @property - def yaml(): - """A YAML representation of the :class:`Dataset` object. If headers have been - set, a YAML list of objects will be returned. If no headers have - been set, a YAML list of lists (rows) will be returned instead. - - A dataset object can also be imported by setting the :class:`Dataset.json` attribute: :: - - data = tablib.Dataset() - data.yaml = '- {age: 90, first_name: John, last_name: Adams}' - - Import assumes (for now) that headers exist. - """ - pass - - - @property - def json(): - """A JSON representation of the :class:`Dataset` object. If headers have been - set, a JSON list of objects will be returned. If no headers have - been set, a JSON list of lists (rows) will be returned instead. - - A dataset object can also be imported by setting the :class:`Dataset.json` attribute: :: - - data = tablib.Dataset() - data.json = '[{age: 90, first_name: "John", liast_name: "Adams"}]' - - Import assumes (for now) that headers exist. - """ - - @property - def html(): - """A HTML table representation of the :class:`Dataset` object. If - headers have been set, they will be used as table headers. - - ..notice:: This method can be used for export only. - """ - pass - - def append(self, row=None, col=None, header=None, tags=list()): - """Adds a row or column to the :class:`Dataset`. - Usage is :class:`Dataset.insert` for documentation. + Import assumes (for now) that headers exist. """ - if row is not None: - self.insert(self.height, row=row, tags=tags) - elif col is not None: - self.insert(self.width, col=col, header=header) + @property + def yaml(): + """A YAML representation of the :class:`Dataset` object. If headers have been + set, a YAML list of objects will be returned. If no headers have + been set, a YAML list of lists (rows) will be returned instead. - def insert_separator(self, index, text='-'): - """Adds a separator to :class:`Dataset` at given index.""" + A dataset object can also be imported by setting the :class:`Dataset.json` attribute: :: - sep = (index, text) - self._separators.append(sep) + data = tablib.Dataset() + data.yaml = '- {age: 90, first_name: John, last_name: Adams}' + + Import assumes (for now) that headers exist. + """ + pass - def append_separator(self, text='-'): - """Adds a :ref:`seperator ` to the :class:`Dataset`.""" + @property + def json(): + """A JSON representation of the :class:`Dataset` object. If headers have been + set, a JSON list of objects will be returned. If no headers have + been set, a JSON list of lists (rows) will be returned instead. - # change offsets if headers are or aren't defined - if not self.headers: - index = self.height if self.height else 0 - else: - index = (self.height + 1) if self.height else 1 + A dataset object can also be imported by setting the :class:`Dataset.json` attribute: :: - self.insert_separator(index, text) + data = tablib.Dataset() + data.json = '[{age: 90, first_name: "John", liast_name: "Adams"}]' + + Import assumes (for now) that headers exist. + """ + + @property + def html(): + """A HTML table representation of the :class:`Dataset` object. If + headers have been set, they will be used as table headers. + + ..notice:: This method can be used for export only. + """ + pass + + def append(self, row=None, col=None, header=None, tags=list()): + """Adds a row or column to the :class:`Dataset`. + Usage is :class:`Dataset.insert` for documentation. + """ + + if row is not None: + self.insert(self.height, row=row, tags=tags) + elif col is not None: + self.insert(self.width, col=col, header=header) + + def insert_separator(self, index, text='-'): + """Adds a separator to :class:`Dataset` at given index.""" + + sep = (index, text) + self._separators.append(sep) - def insert(self, index, row=None, col=None, header=None, tags=list()): - """Inserts a row or column to the :class:`Dataset` at the given index. + def append_separator(self, text='-'): + """Adds a :ref:`seperator ` to the :class:`Dataset`.""" + + # change offsets if headers are or aren't defined + if not self.headers: + index = self.height if self.height else 0 + else: + index = (self.height + 1) if self.height else 1 + + self.insert_separator(index, text) + + + def insert(self, index, row=None, col=None, header=None, tags=list()): + """Inserts a row or column to the :class:`Dataset` at the given index. Rows and columns inserted must be the correct size (height or width). @@ -486,270 +486,270 @@ class Dataset(object): This gives you the ability to :class:`filter ` your :class:`Dataset` later. - """ - if row: - self._validate(row) - self._data.insert(index, Row(row, tags=tags)) - elif col: - col = list(col) + """ + if row: + self._validate(row) + self._data.insert(index, Row(row, tags=tags)) + elif col: + col = list(col) - # Callable Columns... - if len(col) == 1 and callable(col[0]): - col = map(col[0], self._data) + # Callable Columns... + if len(col) == 1 and callable(col[0]): + col = map(col[0], self._data) - col = self._clean_col(col) - self._validate(col=col) + col = self._clean_col(col) + self._validate(col=col) - if self.headers: - # pop the first item off, add to headers - if not header: - raise HeadersNeeded() - self.headers.insert(index, header) + if self.headers: + # pop the first item off, add to headers + if not header: + raise HeadersNeeded() + self.headers.insert(index, header) - if self.height and self.width: + if self.height and self.width: - for i, row in enumerate(self._data): + for i, row in enumerate(self._data): - row.insert(index, col[i]) - self._data[i] = row - else: - self._data = [Row([row]) for row in col] + row.insert(index, col[i]) + self._data[i] = row + else: + self._data = [Row([row]) for row in col] - def filter(self, tag): - """Returns a new instance of the :class:`Dataset`, excluding any rows - that do not contain the given :ref:`tags `. - """ - _dset = copy(self) - _dset._data = [row for row in _dset._data if row.has_tag(tag)] + def filter(self, tag): + """Returns a new instance of the :class:`Dataset`, excluding any rows + that do not contain the given :ref:`tags `. + """ + _dset = copy(self) + _dset._data = [row for row in _dset._data if row.has_tag(tag)] - return _dset + return _dset - def sort(self, col, reverse=False): - """Sort a :class:`Dataset` by a specific column, given string (for - header) or integer (for column index). The order can be reversed by - setting ``reverse`` to ``True``. - Returns a new :class:`Dataset` instance where columns have been - sorted.""" - - if isinstance(col, basestring): + def sort(self, col, reverse=False): + """Sort a :class:`Dataset` by a specific column, given string (for + header) or integer (for column index). The order can be reversed by + setting ``reverse`` to ``True``. + Returns a new :class:`Dataset` instance where columns have been + sorted.""" + + if isinstance(col, basestring): - if not self.headers: - raise HeadersNeeded + if not self.headers: + raise HeadersNeeded - _sorted = sorted(self.dict, key=itemgetter(col), reverse=reverse) - _dset = Dataset(headers=self.headers) + _sorted = sorted(self.dict, key=itemgetter(col), reverse=reverse) + _dset = Dataset(headers=self.headers) - for item in _sorted: - row = [item[key] for key in self.headers] - _dset.append(row=row) + for item in _sorted: + row = [item[key] for key in self.headers] + _dset.append(row=row) - else: - if self.headers: - col = self.headers[col] + else: + if self.headers: + col = self.headers[col] - _sorted = sorted(self.dict, key=itemgetter(col), reverse=reverse) - _dset = Dataset(headers=self.headers) + _sorted = sorted(self.dict, key=itemgetter(col), reverse=reverse) + _dset = Dataset(headers=self.headers) - for item in _sorted: - if self.headers: - row = [item[key] for key in self.headers] - else: - row = item - _dset.append(row=row) + for item in _sorted: + if self.headers: + row = [item[key] for key in self.headers] + else: + row = item + _dset.append(row=row) - return _dset + return _dset - def transpose(self): - """Transpose a :class:`Dataset`, turning rows into columns and vice - versa, returning a new ``Dataset`` instance. The first row of the - original instance becomes the new header row.""" + def transpose(self): + """Transpose a :class:`Dataset`, turning rows into columns and vice + versa, returning a new ``Dataset`` instance. The first row of the + original instance becomes the new header row.""" - # Don't transpose if there is no data - if not self: - return + # Don't transpose if there is no data + if not self: + return - _dset = Dataset() - # The first element of the headers stays in the headers, - # it is our "hinge" on which we rotate the data - new_headers = [self.headers[0]] + self[self.headers[0]] + _dset = Dataset() + # The first element of the headers stays in the headers, + # it is our "hinge" on which we rotate the data + new_headers = [self.headers[0]] + self[self.headers[0]] - _dset.headers = new_headers - for column in self.headers: + _dset.headers = new_headers + for column in self.headers: - if column == self.headers[0]: - # It's in the headers, so skip it - continue + if column == self.headers[0]: + # It's in the headers, so skip it + continue - # Adding the column name as now they're a regular column - row_data = [column] + self[column] - row_data = Row(row_data) - _dset.append(row=row_data) + # Adding the column name as now they're a regular column + row_data = [column] + self[column] + row_data = Row(row_data) + _dset.append(row=row_data) - return _dset + return _dset - def stack_rows(self, other): - """Stack two :class:`Dataset` instances together by - joining at the row level, and return new combined - ``Dataset`` instance.""" + def stack_rows(self, other): + """Stack two :class:`Dataset` instances together by + joining at the row level, and return new combined + ``Dataset`` instance.""" - if not isinstance(other, Dataset): - return + if not isinstance(other, Dataset): + return - if self.width != other.width: - raise InvalidDimensions + if self.width != other.width: + raise InvalidDimensions - # Copy the source data - _dset = copy(self) + # Copy the source data + _dset = copy(self) - rows_to_stack = [row for row in _dset._data] - other_rows = [row for row in other._data] + rows_to_stack = [row for row in _dset._data] + other_rows = [row for row in other._data] - rows_to_stack.extend(other_rows) - _dset._data = rows_to_stack + rows_to_stack.extend(other_rows) + _dset._data = rows_to_stack - return _dset + return _dset - def stack_columns(self, other): - """Stack two :class:`Dataset` instances together by - joining at the column level, and return a new - combined ``Dataset`` instance. If either ``Dataset`` - has headers set, than the other must as well.""" + def stack_columns(self, other): + """Stack two :class:`Dataset` instances together by + joining at the column level, and return a new + combined ``Dataset`` instance. If either ``Dataset`` + has headers set, than the other must as well.""" - if not isinstance(other, Dataset): - return + if not isinstance(other, Dataset): + return - if self.headers or other.headers: - if not self.headers or not other.headers: - raise HeadersNeeded + if self.headers or other.headers: + if not self.headers or not other.headers: + raise HeadersNeeded - if self.height != other.height: - raise InvalidDimensions + if self.height != other.height: + raise InvalidDimensions - try: - new_headers = self.headers + other.headers - except TypeError: - new_headers = None + try: + new_headers = self.headers + other.headers + except TypeError: + new_headers = None - _dset = Dataset() + _dset = Dataset() - for column in self.headers: - _dset.append(col=self[column]) + for column in self.headers: + _dset.append(col=self[column]) - for column in other.headers: - _dset.append(col=other[column]) + for column in other.headers: + _dset.append(col=other[column]) - _dset.headers = new_headers + _dset.headers = new_headers - return _dset + return _dset - def wipe(self): - """Removes all content and headers from the :class:`Dataset` object.""" - self._data = list() - self.__headers = None + def wipe(self): + """Removes all content and headers from the :class:`Dataset` object.""" + self._data = list() + self.__headers = None class Databook(object): - """A book of :class:`Dataset` objects. - """ + """A book of :class:`Dataset` objects. + """ - def __init__(self, sets=None): + def __init__(self, sets=None): - if sets is None: - self._datasets = list() - else: - self._datasets = sets + if sets is None: + self._datasets = list() + else: + self._datasets = sets - self._register_formats() + self._register_formats() - def __repr__(self): - try: - return '<%s databook>' % (self.title.lower()) - except AttributeError: - return '' + def __repr__(self): + try: + return '<%s databook>' % (self.title.lower()) + except AttributeError: + return '' - def wipe(self): - """Removes all :class:`Dataset` objects from the :class:`Databook`.""" - self._datasets = [] + def wipe(self): + """Removes all :class:`Dataset` objects from the :class:`Databook`.""" + self._datasets = [] - @classmethod - def _register_formats(cls): - """Adds format properties.""" - for fmt in formats.available: - try: - try: - setattr(cls, fmt.title, property(fmt.export_book, fmt.import_book)) - except AttributeError: - setattr(cls, fmt.title, property(fmt.export_book)) + @classmethod + def _register_formats(cls): + """Adds format properties.""" + for fmt in formats.available: + try: + try: + setattr(cls, fmt.title, property(fmt.export_book, fmt.import_book)) + except AttributeError: + setattr(cls, fmt.title, property(fmt.export_book)) - except AttributeError: - pass + except AttributeError: + pass - def add_sheet(self, dataset): - """Adds given :class:`Dataset` to the :class:`Databook`.""" - if type(dataset) is Dataset: - self._datasets.append(dataset) - else: - raise InvalidDatasetType + def add_sheet(self, dataset): + """Adds given :class:`Dataset` to the :class:`Databook`.""" + if type(dataset) is Dataset: + self._datasets.append(dataset) + else: + raise InvalidDatasetType - def _package(self): - """Packages :class:`Databook` for delivery.""" - collector = [] - for dset in self._datasets: - collector.append(dict( - title = dset.title, - data = dset.dict - )) - return collector + def _package(self): + """Packages :class:`Databook` for delivery.""" + collector = [] + for dset in self._datasets: + collector.append(dict( + title = dset.title, + data = dset.dict + )) + return collector - @property - def size(self): - """The number of the :class:`Dataset` objects within :class:`Databook`.""" - return len(self._datasets) + @property + def size(self): + """The number of the :class:`Dataset` objects within :class:`Databook`.""" + return len(self._datasets) def detect(stream): - """Return (format, stream) of given stream.""" - for fmt in formats.available: - try: - if fmt.detect(stream): - return (fmt, stream) - except AttributeError: - pass - return (None, stream) + """Return (format, stream) of given stream.""" + for fmt in formats.available: + try: + if fmt.detect(stream): + return (fmt, stream) + except AttributeError: + pass + return (None, stream) def import_set(stream): - """Return dataset of given stream.""" - (format, stream) = detect(stream) + """Return dataset of given stream.""" + (format, stream) = detect(stream) - try: - data = Dataset() - format.import_set(data, stream) - return data + try: + data = Dataset() + format.import_set(data, stream) + return data - except AttributeError, e: - return None + except AttributeError, e: + return None class InvalidDatasetType(Exception): - "Only Datasets can be added to a DataBook" + "Only Datasets can be added to a DataBook" class InvalidDimensions(Exception): - "Invalid size" + "Invalid size" class HeadersNeeded(Exception): - "Header parameter must be given when appending a column in this Dataset." + "Header parameter must be given when appending a column in this Dataset." class UnsupportedFormat(NotImplementedError): - "Format is not supported" + "Format is not supported" diff --git a/tablib/formats/_csv.py b/tablib/formats/_csv.py index 2391417..2c74a1c 100644 --- a/tablib/formats/_csv.py +++ b/tablib/formats/_csv.py @@ -16,34 +16,34 @@ extentions = ('csv',) def export_set(dataset): - """Returns CSV representation of Dataset.""" - stream = cStringIO.StringIO() - _csv = csv.writer(stream) + """Returns CSV representation of Dataset.""" + stream = cStringIO.StringIO() + _csv = csv.writer(stream) - for row in dataset._package(dicts=False): - _csv.writerow(row) + for row in dataset._package(dicts=False): + _csv.writerow(row) - return stream.getvalue() + return stream.getvalue() def import_set(dset, in_stream, headers=True): - """Returns dataset from CSV stream.""" + """Returns dataset from CSV stream.""" - dset.wipe() + dset.wipe() - rows = csv.reader(in_stream.split()) - for i, row in enumerate(rows): + rows = csv.reader(in_stream.split()) + for i, row in enumerate(rows): - if (i == 0) and (headers): - dset.headers = row - else: - dset.append(row) + if (i == 0) and (headers): + dset.headers = row + else: + dset.append(row) def detect(stream): - """Returns True if given stream is valid CSV.""" - try: - rows = dialect = csv.Sniffer().sniff(stream) - return True - except csv.Error: - return False \ No newline at end of file + """Returns True if given stream is valid CSV.""" + try: + rows = dialect = csv.Sniffer().sniff(stream) + return True + except csv.Error: + return False \ No newline at end of file diff --git a/tablib/formats/_json.py b/tablib/formats/_json.py index 7f31ee5..51cc207 100644 --- a/tablib/formats/_json.py +++ b/tablib/formats/_json.py @@ -4,12 +4,12 @@ """ try: - import json # load system JSON (Python >= 2.6) + import json # load system JSON (Python >= 2.6) except ImportError: - try: - import simplejson as json - except ImportError: - import tablib.packages.simplejson as json # use the vendorized copy + try: + import simplejson as json + except ImportError: + import tablib.packages.simplejson as json # use the vendorized copy import tablib.core @@ -19,37 +19,37 @@ extentions = ('json', 'jsn') def export_set(dataset): - """Returns JSON representation of Dataset.""" - return json.dumps(dataset.dict) + """Returns JSON representation of Dataset.""" + return json.dumps(dataset.dict) def export_book(databook): - """Returns JSON representation of Databook.""" - return json.dumps(databook._package()) + """Returns JSON representation of Databook.""" + return json.dumps(databook._package()) def import_set(dset, in_stream): - """Returns dataset from JSON stream.""" + """Returns dataset from JSON stream.""" - dset.wipe() - dset.dict = json.loads(in_stream) + dset.wipe() + dset.dict = json.loads(in_stream) def import_book(dbook, in_stream): - """Returns databook from JSON stream.""" + """Returns databook from JSON stream.""" - dbook.wipe() - for sheet in json.loads(in_stream): - data = tablib.core.Dataset() - data.title = sheet['title'] - data.dict = sheet['data'] - dbook.add_sheet(data) + dbook.wipe() + for sheet in json.loads(in_stream): + data = tablib.core.Dataset() + data.title = sheet['title'] + data.dict = sheet['data'] + dbook.add_sheet(data) def detect(stream): - """Returns True if given stream is valid JSON.""" - try: - json.loads(stream) - return True - except ValueError: - return False + """Returns True if given stream is valid JSON.""" + try: + json.loads(stream) + return True + except ValueError: + return False diff --git a/tablib/formats/_tsv.py b/tablib/formats/_tsv.py index 808f202..76a5f07 100644 --- a/tablib/formats/_tsv.py +++ b/tablib/formats/_tsv.py @@ -16,36 +16,36 @@ extentions = ('tsv',) def export_set(dataset): - """Returns a TSV representation of Dataset.""" - stream = cStringIO.StringIO() - _tsv = csv.writer(stream, delimiter='\t') + """Returns a TSV representation of Dataset.""" + stream = cStringIO.StringIO() + _tsv = csv.writer(stream, delimiter='\t') - for row in dataset._package(dicts=False): - _tsv.writerow(row) + for row in dataset._package(dicts=False): + _tsv.writerow(row) - return stream.getvalue() + return stream.getvalue() def import_set(dset, in_stream, headers=True): - """Returns dataset from TSV stream.""" - dset.wipe() + """Returns dataset from TSV stream.""" + dset.wipe() - rows = csv.reader(in_stream.split('\r\n'), delimiter='\t') - for i, row in enumerate(rows): - # Skip empty rows - if not row: - continue + rows = csv.reader(in_stream.split('\r\n'), delimiter='\t') + for i, row in enumerate(rows): + # Skip empty rows + if not row: + continue - if (i == 0) and (headers): - dset.headers = row - else: - dset.append(row) + if (i == 0) and (headers): + dset.headers = row + else: + dset.append(row) def detect(stream): - """Returns True if given stream is valid TSV.""" - try: - rows = dialect = csv.Sniffer().sniff(stream, delimiters='\t') - return True - except csv.Error: - return False + """Returns True if given stream is valid TSV.""" + try: + rows = dialect = csv.Sniffer().sniff(stream, delimiters='\t') + return True + except csv.Error: + return False diff --git a/tablib/formats/_xls.py b/tablib/formats/_xls.py index 08bc0f6..717a6d5 100644 --- a/tablib/formats/_xls.py +++ b/tablib/formats/_xls.py @@ -6,9 +6,9 @@ import cStringIO try: - import xlwt + import xlwt except ImportError: - import tablib.packages.xlwt as xlwt + import tablib.packages.xlwt as xlwt title = 'xls' @@ -20,66 +20,66 @@ bold = xlwt.easyxf("font: bold on") def export_set(dataset): - """Returns XLS representation of Dataset.""" + """Returns XLS representation of Dataset.""" - wb = xlwt.Workbook(encoding='utf8') - ws = wb.add_sheet(dataset.title if dataset.title else 'Tabbed Dataset') + wb = xlwt.Workbook(encoding='utf8') + ws = wb.add_sheet(dataset.title if dataset.title else 'Tabbed Dataset') - dset_sheet(dataset, ws) + dset_sheet(dataset, ws) - stream = cStringIO.StringIO() - wb.save(stream) - return stream.getvalue() + stream = cStringIO.StringIO() + wb.save(stream) + return stream.getvalue() def export_book(databook): - """Returns XLS representation of DataBook.""" + """Returns XLS representation of DataBook.""" - wb = xlwt.Workbook(encoding='utf8') + wb = xlwt.Workbook(encoding='utf8') - for i, dset in enumerate(databook._datasets): - ws = wb.add_sheet(dset.title if dset.title else 'Sheet%s' % (i)) + for i, dset in enumerate(databook._datasets): + ws = wb.add_sheet(dset.title if dset.title else 'Sheet%s' % (i)) - dset_sheet(dset, ws) + dset_sheet(dset, ws) - stream = cStringIO.StringIO() - wb.save(stream) - return stream.getvalue() + stream = cStringIO.StringIO() + wb.save(stream) + return stream.getvalue() def dset_sheet(dataset, ws): - """Completes given worksheet from given Dataset.""" - _package = dataset._package(dicts=False) + """Completes given worksheet from given Dataset.""" + _package = dataset._package(dicts=False) - for i, sep in enumerate(dataset._separators): - _offset = i - _package.insert((sep[0] + _offset), (sep[1],)) + for i, sep in enumerate(dataset._separators): + _offset = i + _package.insert((sep[0] + _offset), (sep[1],)) - for i, row in enumerate(_package): - for j, col in enumerate(row): + for i, row in enumerate(_package): + for j, col in enumerate(row): - # bold headers - if (i == 0) and dataset.headers: - ws.write(i, j, col, bold) + # bold headers + if (i == 0) and dataset.headers: + ws.write(i, j, col, bold) - # frozen header row - ws.panes_frozen = True - ws.horz_split_pos = 1 + # frozen header row + ws.panes_frozen = True + ws.horz_split_pos = 1 - # bold separators - elif len(row) < dataset.width: - ws.write(i, j, col, bold) + # bold separators + elif len(row) < dataset.width: + ws.write(i, j, col, bold) - # wrap the rest - else: - try: - if '\n' in col: - ws.write(i, j, col, wrap) - else: - ws.write(i, j, col) - except TypeError: - ws.write(i, j, col) + # wrap the rest + else: + try: + if '\n' in col: + ws.write(i, j, col, wrap) + else: + ws.write(i, j, col) + except TypeError: + ws.write(i, j, col) diff --git a/tablib/formats/_yaml.py b/tablib/formats/_yaml.py index 59d49a0..3f2f8b7 100644 --- a/tablib/formats/_yaml.py +++ b/tablib/formats/_yaml.py @@ -4,9 +4,9 @@ """ try: - import yaml + import yaml except ImportError: - import tablib.packages.yaml as yaml + import tablib.packages.yaml as yaml import tablib @@ -18,40 +18,40 @@ extentions = ('yaml', 'yml') def export_set(dataset): - """Returns YAML representation of Dataset.""" - return yaml.dump(dataset.dict) + """Returns YAML representation of Dataset.""" + return yaml.dump(dataset.dict) def export_book(databook): - """Returns YAML representation of Databook.""" - return yaml.dump(databook._package()) + """Returns YAML representation of Databook.""" + return yaml.dump(databook._package()) def import_set(dset, in_stream): - """Returns dataset from YAML stream.""" + """Returns dataset from YAML stream.""" - dset.wipe() - dset.dict = yaml.load(in_stream) + dset.wipe() + dset.dict = yaml.load(in_stream) def import_book(dbook, in_stream): - """Returns databook from YAML stream.""" + """Returns databook from YAML stream.""" - dbook.wipe() + dbook.wipe() - for sheet in yaml.load(in_stream): - data = tablib.core.Dataset() - data.title = sheet['title'] - data.dict = sheet['data'] - dbook.add_sheet(data) - + for sheet in yaml.load(in_stream): + data = tablib.core.Dataset() + data.title = sheet['title'] + data.dict = sheet['data'] + dbook.add_sheet(data) + def detect(stream): - """Returns True if given stream is valid YAML.""" - try: - _yaml = yaml.load(stream) - if isinstance(_yaml, (list, tuple, dict)): - return True - else: - return False - except yaml.parser.ParserError: - return False \ No newline at end of file + """Returns True if given stream is valid YAML.""" + try: + _yaml = yaml.load(stream) + if isinstance(_yaml, (list, tuple, dict)): + return True + else: + return False + except yaml.parser.ParserError: + return False \ No newline at end of file diff --git a/tablib/helpers.py b/tablib/helpers.py index f75c466..718d159 100644 --- a/tablib/helpers.py +++ b/tablib/helpers.py @@ -7,31 +7,31 @@ import sys class Struct(object): - """Your attributes are belong to us.""" - - def __init__(self, **entries): - self.__dict__.update(entries) - - def __getitem__(self, key): - return getattr(self, key, None) + """Your attributes are belong to us.""" + + def __init__(self, **entries): + self.__dict__.update(entries) + + def __getitem__(self, key): + return getattr(self, key, None) - def dictionary(self): - """Returns dictionary representation of object.""" - return self.__dict__ + def dictionary(self): + """Returns dictionary representation of object.""" + return self.__dict__ - def items(self): - """Returns items within object.""" - return self.__dict__.items() + def items(self): + """Returns items within object.""" + return self.__dict__.items() - def keys(self): - """Returns keys within object.""" - return self.__dict__.keys() + def keys(self): + """Returns keys within object.""" + return self.__dict__.keys() def piped(): - """Returns piped input via stdin, else False.""" - with sys.stdin as stdin: - # TTY is only way to detect if stdin contains data - return stdin.read() if not stdin.isatty() else None + """Returns piped input via stdin, else False.""" + with sys.stdin as stdin: + # TTY is only way to detect if stdin contains data + return stdin.read() if not stdin.isatty() else None diff --git a/tablib/packages/markup.py b/tablib/packages/markup.py index 98d9b1d..72a7162 100644 --- a/tablib/packages/markup.py +++ b/tablib/packages/markup.py @@ -29,10 +29,10 @@ class element: def __init__( self, tag, case='lower', parent=None ): self.parent = parent - if case == 'lower': - self.tag = tag.lower( ) - else: - self.tag = tag.upper( ) + if case == 'lower': + self.tag = tag.lower( ) + else: + self.tag = tag.upper( ) def __call__( self, *args, **kwargs ): if len( args ) > 1: @@ -67,8 +67,8 @@ class element: def render( self, tag, single, between, kwargs ): """Append the actual tags to content.""" - out = "<%s" % tag - for key, value in kwargs.iteritems( ): + out = "<%s" % tag + for key, value in kwargs.iteritems( ): 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. if key == 'http_equiv': # special cases, maybe change _ to - overall? @@ -78,13 +78,13 @@ class element: out = "%s %s=\"%s\"" % ( out, key, escape( value ) ) else: out = "%s %s" % ( out, key ) - if between is not None: - out = "%s>%s" % ( out, between, tag ) - else: - if single: - out = "%s />" % out - else: - out = "%s>" % out + if between is not None: + out = "%s>%s" % ( out, between, tag ) + else: + if single: + out = "%s />" % out + else: + out = "%s>" % out if self.parent is not None: self.parent.content.append( out ) else: @@ -145,30 +145,30 @@ class page: deprecated_twotags = [ "APPLET", "CENTER", "DIR", "FONT", "MENU", "S", "STRIKE", "U" ] self.header = [ ] - self.content = [ ] + self.content = [ ] self.footer = [ ] - self.case = case + self.case = case self.separator = separator # init( ) sets it to True so we know that has to be printed at the end self._full = False self.class_= class_ - if mode == 'strict_html' or mode == 'html': - self.onetags = valid_onetags - self.onetags += map( string.lower, self.onetags ) - self.twotags = valid_twotags - self.twotags += map( string.lower, self.twotags ) - self.deptags = deprecated_onetags + deprecated_twotags - self.deptags += map( string.lower, self.deptags ) - self.mode = 'strict_html' - elif mode == 'loose_html': - self.onetags = valid_onetags + deprecated_onetags - self.onetags += map( string.lower, self.onetags ) - self.twotags = valid_twotags + deprecated_twotags - self.twotags += map( string.lower, self.twotags ) - self.mode = mode - elif mode == 'xml': + if mode == 'strict_html' or mode == 'html': + self.onetags = valid_onetags + self.onetags += map( string.lower, self.onetags ) + self.twotags = valid_twotags + self.twotags += map( string.lower, self.twotags ) + self.deptags = deprecated_onetags + deprecated_twotags + self.deptags += map( string.lower, self.deptags ) + self.mode = 'strict_html' + elif mode == 'loose_html': + self.onetags = valid_onetags + deprecated_onetags + self.onetags += map( string.lower, self.onetags ) + self.twotags = valid_twotags + deprecated_twotags + self.twotags += map( string.lower, self.twotags ) + self.mode = mode + elif mode == 'xml': if onetags and twotags: self.onetags = onetags self.twotags = twotags @@ -178,8 +178,8 @@ class page: self.onetags = russell( ) self.twotags = russell( ) self.mode = mode - else: - raise ModeError( mode ) + else: + raise ModeError( mode ) def __getattr__( self, attr ): if attr.startswith("__") and attr.endswith("__"): @@ -192,7 +192,7 @@ class page: end = [ '', '' ] else: end = [ ] - + return self.separator.join( self.header + self.content + self.footer + end ) def __call__( self, escape=False ): @@ -444,37 +444,37 @@ class russell: """A dummy class that contains anything.""" def __contains__( self, item ): - return True + return True class MarkupError( Exception ): """All our exceptions subclass this.""" def __str__( self ): - return self.message + return self.message class ClosingError( MarkupError ): def __init__( self, tag ): - self.message = "The element '%s' does not accept non-keyword arguments (has no closing tag)." % tag + self.message = "The element '%s' does not accept non-keyword arguments (has no closing tag)." % tag class OpeningError( MarkupError ): def __init__( self, tag ): - self.message = "The element '%s' can not be opened." % tag + self.message = "The element '%s' can not be opened." % tag class ArgumentError( MarkupError ): def __init__( self, tag ): - self.message = "The element '%s' was called with more than one non-keyword argument." % tag + self.message = "The element '%s' was called with more than one non-keyword argument." % tag class InvalidElementError( MarkupError ): def __init__( self, tag, mode ): - self.message = "The element '%s' is not valid for your mode '%s'." % ( tag, mode ) + self.message = "The element '%s' is not valid for your mode '%s'." % ( tag, mode ) class DeprecationError( MarkupError ): def __init__( self, tag ): - self.message = "The element '%s' is deprecated, instantiate markup.page with mode='loose_html' to allow it." % tag + self.message = "The element '%s' is deprecated, instantiate markup.page with mode='loose_html' to allow it." % tag class ModeError( MarkupError ): def __init__( self, mode ): - self.message = "Mode '%s' is invalid, possible values: strict_html, loose_html, xml." % mode + self.message = "Mode '%s' is invalid, possible values: strict_html, loose_html, xml." % mode class CustomizationError( MarkupError ): def __init__( self ): diff --git a/test_tablib.py b/test_tablib.py index 15630f2..e4a4d11 100755 --- a/test_tablib.py +++ b/test_tablib.py @@ -12,452 +12,452 @@ import tablib class TablibTestCase(unittest.TestCase): - """Tablib test cases.""" + """Tablib test cases.""" - def setUp(self): - """Create simple data set with headers.""" + def setUp(self): + """Create simple data set with headers.""" - global data, book + global data, book - data = tablib.Dataset() - book = tablib.Databook() + data = tablib.Dataset() + book = tablib.Databook() - self.headers = ('first_name', 'last_name', 'gpa') - self.john = ('John', 'Adams', 90) - self.george = ('George', 'Washington', 67) - self.tom = ('Thomas', 'Jefferson', 50) + self.headers = ('first_name', 'last_name', 'gpa') + self.john = ('John', 'Adams', 90) + self.george = ('George', 'Washington', 67) + self.tom = ('Thomas', 'Jefferson', 50) - self.founders = tablib.Dataset(headers=self.headers) - self.founders.append(self.john) - self.founders.append(self.george) - self.founders.append(self.tom) + self.founders = tablib.Dataset(headers=self.headers) + self.founders.append(self.john) + self.founders.append(self.george) + self.founders.append(self.tom) - def tearDown(self): - """Teardown.""" - pass + def tearDown(self): + """Teardown.""" + pass - def test_empty_append(self): - """Verify append() correctly adds tuple with no headers.""" - new_row = (1, 2, 3) - data.append(new_row) + def test_empty_append(self): + """Verify append() correctly adds tuple with no headers.""" + new_row = (1, 2, 3) + data.append(new_row) - # Verify width/data - self.assertTrue(data.width == len(new_row)) - self.assertTrue(data[0] == new_row) + # Verify width/data + self.assertTrue(data.width == len(new_row)) + self.assertTrue(data[0] == new_row) - def test_empty_append_with_headers(self): - """Verify append() correctly detects mismatch of number of - headers and data. - """ - data.headers = ['first', 'second'] - new_row = (1, 2, 3, 4) + def test_empty_append_with_headers(self): + """Verify append() correctly detects mismatch of number of + headers and data. + """ + data.headers = ['first', 'second'] + new_row = (1, 2, 3, 4) - self.assertRaises(tablib.InvalidDimensions, data.append, new_row) + self.assertRaises(tablib.InvalidDimensions, data.append, new_row) - def test_add_column(self): - """Verify adding column works with/without headers.""" + def test_add_column(self): + """Verify adding column works with/without headers.""" - data.append(['kenneth']) - data.append(['bessie']) + data.append(['kenneth']) + data.append(['bessie']) - new_col = ['reitz', 'monke'] + new_col = ['reitz', 'monke'] - data.append(col=new_col) + data.append(col=new_col) - self.assertEquals(data[0], ('kenneth', 'reitz')) - self.assertEquals(data.width, 2) + self.assertEquals(data[0], ('kenneth', 'reitz')) + self.assertEquals(data.width, 2) - # With Headers - data.headers = ('fname', 'lname') - new_col = [21, 22] - data.append(col=new_col, header='age') + # With Headers + data.headers = ('fname', 'lname') + new_col = [21, 22] + data.append(col=new_col, header='age') - self.assertEquals(data['age'], new_col) + self.assertEquals(data['age'], new_col) - def test_add_column_no_data_no_headers(self): - """Verify adding new column with no headers.""" + def test_add_column_no_data_no_headers(self): + """Verify adding new column with no headers.""" - new_col = ('reitz', 'monke') + new_col = ('reitz', 'monke') - data.append(col=new_col) + data.append(col=new_col) - self.assertEquals(data[0], tuple([new_col[0]])) - self.assertEquals(data.width, 1) - self.assertEquals(data.height, len(new_col)) + self.assertEquals(data[0], tuple([new_col[0]])) + self.assertEquals(data.width, 1) + self.assertEquals(data.height, len(new_col)) - def test_add_callable_column(self): - """Verify adding column with values specified as callable.""" - new_col = [lambda x: x[0]] - self.founders.append(col=new_col, header='first_again') + def test_add_callable_column(self): + """Verify adding column with values specified as callable.""" + new_col = [lambda x: x[0]] + self.founders.append(col=new_col, header='first_again') # -# self.assertTrue(map(lambda x: x[0] == x[-1], self.founders)) +# self.assertTrue(map(lambda x: x[0] == x[-1], self.founders)) - def test_header_slicing(self): - """Verify slicing by headers.""" + def test_header_slicing(self): + """Verify slicing by headers.""" - self.assertEqual(self.founders['first_name'], - [self.john[0], self.george[0], self.tom[0]]) - self.assertEqual(self.founders['last_name'], - [self.john[1], self.george[1], self.tom[1]]) - self.assertEqual(self.founders['gpa'], - [self.john[2], self.george[2], self.tom[2]]) + self.assertEqual(self.founders['first_name'], + [self.john[0], self.george[0], self.tom[0]]) + self.assertEqual(self.founders['last_name'], + [self.john[1], self.george[1], self.tom[1]]) + self.assertEqual(self.founders['gpa'], + [self.john[2], self.george[2], self.tom[2]]) - def test_data_slicing(self): - """Verify slicing by data.""" + def test_data_slicing(self): + """Verify slicing by data.""" - # Slice individual rows - self.assertEqual(self.founders[0], self.john) - self.assertEqual(self.founders[:1], [self.john]) - self.assertEqual(self.founders[1:2], [self.george]) - self.assertEqual(self.founders[-1], self.tom) - self.assertEqual(self.founders[3:], []) + # Slice individual rows + self.assertEqual(self.founders[0], self.john) + self.assertEqual(self.founders[:1], [self.john]) + self.assertEqual(self.founders[1:2], [self.george]) + self.assertEqual(self.founders[-1], self.tom) + self.assertEqual(self.founders[3:], []) - # Slice multiple rows - self.assertEqual(self.founders[:], [self.john, self.george, self.tom]) - self.assertEqual(self.founders[0:2], [self.john, self.george]) - self.assertEqual(self.founders[1:3], [self.george, self.tom]) - self.assertEqual(self.founders[2:], [self.tom]) + # Slice multiple rows + self.assertEqual(self.founders[:], [self.john, self.george, self.tom]) + self.assertEqual(self.founders[0:2], [self.john, self.george]) + self.assertEqual(self.founders[1:3], [self.george, self.tom]) + self.assertEqual(self.founders[2:], [self.tom]) - def test_delete(self): - """Verify deleting from dataset works.""" + def test_delete(self): + """Verify deleting from dataset works.""" - # Delete from front of object - del self.founders[0] - self.assertEqual(self.founders[:], [self.george, self.tom]) + # Delete from front of object + del self.founders[0] + self.assertEqual(self.founders[:], [self.george, self.tom]) - # Verify dimensions, width should NOT change - self.assertEqual(self.founders.height, 2) - self.assertEqual(self.founders.width, 3) + # Verify dimensions, width should NOT change + self.assertEqual(self.founders.height, 2) + self.assertEqual(self.founders.width, 3) - # Delete from back of object - del self.founders[1] - self.assertEqual(self.founders[:], [self.george]) + # Delete from back of object + del self.founders[1] + self.assertEqual(self.founders[:], [self.george]) - # Verify dimensions, width should NOT change - self.assertEqual(self.founders.height, 1) - self.assertEqual(self.founders.width, 3) + # Verify dimensions, width should NOT change + self.assertEqual(self.founders.height, 1) + self.assertEqual(self.founders.width, 3) - # Delete from invalid index - self.assertRaises(IndexError, self.founders.__delitem__, 3) + # Delete from invalid index + self.assertRaises(IndexError, self.founders.__delitem__, 3) - def test_csv_export(self): - """Verify exporting dataset object as CSV.""" + def test_csv_export(self): + """Verify exporting dataset object as CSV.""" - # Build up the csv string with headers first, followed by each row - csv = '' - for col in self.headers: - csv += col + ',' + # Build up the csv string with headers first, followed by each row + csv = '' + for col in self.headers: + csv += col + ',' - csv = csv.strip(',') + '\r\n' + csv = csv.strip(',') + '\r\n' - for founder in self.founders: - for col in founder: - csv += str(col) + ',' - csv = csv.strip(',') + '\r\n' + for founder in self.founders: + for col in founder: + csv += str(col) + ',' + csv = csv.strip(',') + '\r\n' - self.assertEqual(csv, self.founders.csv) + self.assertEqual(csv, self.founders.csv) - def test_tsv_export(self): - """Verify exporting dataset object as CSV.""" + def test_tsv_export(self): + """Verify exporting dataset object as CSV.""" - # Build up the csv string with headers first, followed by each row - tsv = '' - for col in self.headers: - tsv += col + '\t' + # Build up the csv string with headers first, followed by each row + tsv = '' + for col in self.headers: + tsv += col + '\t' - tsv = tsv.strip('\t') + '\r\n' + tsv = tsv.strip('\t') + '\r\n' - for founder in self.founders: - for col in founder: - tsv += str(col) + '\t' - tsv = tsv.strip('\t') + '\r\n' + for founder in self.founders: + for col in founder: + tsv += str(col) + '\t' + tsv = tsv.strip('\t') + '\r\n' - 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""" - html = markup.page() - html.table.open() - html.thead.open() + html = markup.page() + html.table.open() + html.thead.open() - html.tr(markup.oneliner.th(self.founders.headers)) - html.thead.close() + html.tr(markup.oneliner.th(self.founders.headers)) + 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 = str(html) + html.table.close() + html = str(html) - self.assertEqual(html, self.founders.html) + self.assertEqual(html, self.founders.html) - def test_unicode_append(self): - """Passes in a single unicode charecter and exports.""" + def test_unicode_append(self): + """Passes in a single unicode charecter and exports.""" - new_row = ('å', 'é') - data.append(new_row) + new_row = ('å', 'é') + data.append(new_row) - data.json - data.yaml - data.csv - data.tsv - data.xls + data.json + data.yaml + data.csv + data.tsv + data.xls - def test_book_export_no_exceptions(self): - """Test that varoius exports don't error out.""" + def test_book_export_no_exceptions(self): + """Test that varoius exports don't error out.""" - book = tablib.Databook() - book.add_sheet(data) + book = tablib.Databook() + book.add_sheet(data) - book.json - book.yaml - book.xls + book.json + book.yaml + book.xls - def test_json_import_set(self): - """Generate and import JSON set serialization.""" - data.append(self.john) - data.append(self.george) - data.headers = self.headers + def test_json_import_set(self): + """Generate and import JSON set serialization.""" + data.append(self.john) + data.append(self.george) + data.headers = self.headers - _json = data.json + _json = data.json - data.json = _json + data.json = _json - self.assertEqual(_json, data.json) + self.assertEqual(_json, data.json) - def test_json_import_book(self): - """Generate and import JSON book serialization.""" - data.append(self.john) - data.append(self.george) - data.headers = self.headers + def test_json_import_book(self): + """Generate and import JSON book serialization.""" + data.append(self.john) + data.append(self.george) + data.headers = self.headers - book.add_sheet(data) - _json = book.json + book.add_sheet(data) + _json = book.json - book.json = _json + book.json = _json - self.assertEqual(_json, book.json) + self.assertEqual(_json, book.json) - def test_yaml_import_set(self): - """Generate and import YAML set serialization.""" - data.append(self.john) - data.append(self.george) - data.headers = self.headers + def test_yaml_import_set(self): + """Generate and import YAML set serialization.""" + data.append(self.john) + data.append(self.george) + data.headers = self.headers - _yaml = data.yaml + _yaml = data.yaml - data.yaml = _yaml + data.yaml = _yaml - self.assertEqual(_yaml, data.yaml) + self.assertEqual(_yaml, data.yaml) - def test_yaml_import_book(self): - """Generate and import YAML book serialization.""" - data.append(self.john) - data.append(self.george) - data.headers = self.headers + def test_yaml_import_book(self): + """Generate and import YAML book serialization.""" + data.append(self.john) + data.append(self.george) + data.headers = self.headers - book.add_sheet(data) - _yaml = book.yaml + book.add_sheet(data) + _yaml = book.yaml - book.yaml = _yaml + book.yaml = _yaml - self.assertEqual(_yaml, book.yaml) + self.assertEqual(_yaml, book.yaml) - def test_csv_import_set(self): - """Generate and import CSV set serialization.""" - data.append(self.john) - data.append(self.george) - data.headers = self.headers + def test_csv_import_set(self): + """Generate and import CSV set serialization.""" + data.append(self.john) + data.append(self.george) + data.headers = self.headers - _csv = data.csv + _csv = data.csv - data.csv = _csv + data.csv = _csv - self.assertEqual(_csv, data.csv) + self.assertEqual(_csv, data.csv) - def test_tsv_import_set(self): - """Generate and import TSV set serialization.""" - data.append(self.john) - data.append(self.george) - data.headers = self.headers + def test_tsv_import_set(self): + """Generate and import TSV set serialization.""" + data.append(self.john) + data.append(self.george) + data.headers = self.headers - _tsv = data.tsv + _tsv = data.tsv - data.tsv = _tsv + data.tsv = _tsv - self.assertEqual(_tsv, data.tsv) + self.assertEqual(_tsv, data.tsv) - def test_csv_format_detect(self): - """Test CSV format detection.""" + def test_csv_format_detect(self): + """Test CSV format detection.""" - _csv = ( - '1,2,3\n' - '4,5,6\n' - '7,8,9\n' - ) - _bunk = ( - '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' - ) + _csv = ( + '1,2,3\n' + '4,5,6\n' + '7,8,9\n' + ) + _bunk = ( + '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' + ) - self.assertTrue(tablib.formats.csv.detect(_csv)) - self.assertFalse(tablib.formats.csv.detect(_bunk)) + self.assertTrue(tablib.formats.csv.detect(_csv)) + self.assertFalse(tablib.formats.csv.detect(_bunk)) - def test_tsv_format_detect(self): - """Test TSV format detection.""" + def test_tsv_format_detect(self): + """Test TSV format detection.""" - _tsv = ( - '1\t2\t3\n' - '4\t5\t6\n' - '7\t8\t9\n' - ) - _bunk = ( - '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' - ) + _tsv = ( + '1\t2\t3\n' + '4\t5\t6\n' + '7\t8\t9\n' + ) + _bunk = ( + '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' + ) - self.assertTrue(tablib.formats.tsv.detect(_tsv)) - self.assertFalse(tablib.formats.tsv.detect(_bunk)) + self.assertTrue(tablib.formats.tsv.detect(_tsv)) + self.assertFalse(tablib.formats.tsv.detect(_bunk)) - def test_json_format_detect(self): - """Test JSON format detection.""" + def test_json_format_detect(self): + """Test JSON format detection.""" - _json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]' - _bunk = ( - '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' - ) + _json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]' + _bunk = ( + '¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' + ) - self.assertTrue(tablib.formats.json.detect(_json)) - self.assertFalse(tablib.formats.json.detect(_bunk)) + self.assertTrue(tablib.formats.json.detect(_json)) + self.assertFalse(tablib.formats.json.detect(_bunk)) - def test_yaml_format_detect(self): - """Test YAML format detection.""" + def test_yaml_format_detect(self): + """Test YAML format detection.""" - _yaml = '- {age: 90, first_name: John, last_name: Adams}' - _bunk = ( - '¡¡¡¡¡¡---///\n\n\n¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' - ) + _yaml = '- {age: 90, first_name: John, last_name: Adams}' + _bunk = ( + '¡¡¡¡¡¡---///\n\n\n¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' + ) - self.assertTrue(tablib.formats.yaml.detect(_yaml)) - self.assertFalse(tablib.formats.yaml.detect(_bunk)) + self.assertTrue(tablib.formats.yaml.detect(_yaml)) + self.assertFalse(tablib.formats.yaml.detect(_bunk)) - def test_auto_format_detect(self): - """Test auto format detection.""" + def test_auto_format_detect(self): + """Test auto format detection.""" - _yaml = '- {age: 90, first_name: John, last_name: Adams}' - _json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]' - _csv = '1,2,3\n4,5,6\n7,8,9\n' - _bunk = '¡¡¡¡¡¡---///\n\n\n¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' + _yaml = '- {age: 90, first_name: John, last_name: Adams}' + _json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]' + _csv = '1,2,3\n4,5,6\n7,8,9\n' + _bunk = '¡¡¡¡¡¡---///\n\n\n¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶' - self.assertEqual(tablib.detect(_yaml)[0], tablib.formats.yaml) - self.assertEqual(tablib.detect(_csv)[0], tablib.formats.csv) - self.assertEqual(tablib.detect(_json)[0], tablib.formats.json) - self.assertEqual(tablib.detect(_bunk)[0], None) + self.assertEqual(tablib.detect(_yaml)[0], tablib.formats.yaml) + self.assertEqual(tablib.detect(_csv)[0], tablib.formats.csv) + self.assertEqual(tablib.detect(_json)[0], tablib.formats.json) + self.assertEqual(tablib.detect(_bunk)[0], None) - def test_transpose(self): - """Transpose a dataset.""" + def test_transpose(self): + """Transpose a dataset.""" - transposed_founders = self.founders.transpose() - first_row = transposed_founders[0] - second_row = transposed_founders[1] + transposed_founders = self.founders.transpose() + first_row = transposed_founders[0] + second_row = transposed_founders[1] - self.assertEqual(transposed_founders.headers, - ["first_name","John", "George", "Thomas"]) - self.assertEqual(first_row, - ("last_name","Adams", "Washington", "Jefferson")) - self.assertEqual(second_row, - ("gpa",90, 67, 50)) + self.assertEqual(transposed_founders.headers, + ["first_name","John", "George", "Thomas"]) + self.assertEqual(first_row, + ("last_name","Adams", "Washington", "Jefferson")) + self.assertEqual(second_row, + ("gpa",90, 67, 50)) - def test_row_stacking(self): + def test_row_stacking(self): - """Row stacking.""" + """Row stacking.""" - to_join = tablib.Dataset(headers=self.founders.headers) + to_join = tablib.Dataset(headers=self.founders.headers) - for row in self.founders: - to_join.append(row=row) + for row in self.founders: + to_join.append(row=row) - row_stacked = self.founders.stack_rows(to_join) + row_stacked = self.founders.stack_rows(to_join) - for column in row_stacked.headers: + for column in row_stacked.headers: - original_data = self.founders[column] - expected_data = original_data + original_data - self.assertEqual(row_stacked[column], expected_data) + original_data = self.founders[column] + expected_data = original_data + original_data + self.assertEqual(row_stacked[column], expected_data) - def test_column_stacking(self): + def test_column_stacking(self): - """Column stacking""" + """Column stacking""" - to_join = tablib.Dataset(headers=self.founders.headers) + to_join = tablib.Dataset(headers=self.founders.headers) - for row in self.founders: - to_join.append(row=row) + for row in self.founders: + to_join.append(row=row) - column_stacked = self.founders.stack_columns(to_join) + column_stacked = self.founders.stack_columns(to_join) - for index, row in enumerate(column_stacked): + for index, row in enumerate(column_stacked): - original_data = self.founders[index] - expected_data = original_data + original_data - self.assertEqual(row, expected_data) + original_data = self.founders[index] + expected_data = original_data + original_data + self.assertEqual(row, expected_data) - self.assertEqual(column_stacked[0], - ("John", "Adams", 90, "John", "Adams", 90)) + self.assertEqual(column_stacked[0], + ("John", "Adams", 90, "John", "Adams", 90)) - def test_sorting(self): + def test_sorting(self): - """Sort columns.""" + """Sort columns.""" - sorted_data = self.founders.sort(col="first_name") + sorted_data = self.founders.sort(col="first_name") - first_row = sorted_data[0] - second_row = sorted_data[2] - third_row = sorted_data[1] - expected_first = self.founders[1] - expected_second = self.founders[2] - expected_third = self.founders[0] + first_row = sorted_data[0] + second_row = sorted_data[2] + third_row = sorted_data[1] + expected_first = self.founders[1] + expected_second = self.founders[2] + expected_third = self.founders[0] - self.assertEqual(first_row, expected_first) - self.assertEqual(second_row, expected_second) - self.assertEqual(third_row, expected_third) + self.assertEqual(first_row, expected_first) + self.assertEqual(second_row, expected_second) + self.assertEqual(third_row, expected_third) - def test_wipe(self): - """Purge a dataset.""" + def test_wipe(self): + """Purge a dataset.""" - new_row = (1, 2, 3) - data.append(new_row) + new_row = (1, 2, 3) + data.append(new_row) - # Verify width/data - self.assertTrue(data.width == len(new_row)) - self.assertTrue(data[0] == new_row) + # Verify width/data + self.assertTrue(data.width == len(new_row)) + self.assertTrue(data[0] == new_row) - data.wipe() - new_row = (1, 2, 3, 4) - data.append(new_row) - self.assertTrue(data.width == len(new_row)) - self.assertTrue(data[0] == new_row) + data.wipe() + new_row = (1, 2, 3, 4) + data.append(new_row) + self.assertTrue(data.width == len(new_row)) + self.assertTrue(data[0] == new_row) if __name__ == '__main__': - unittest.main() + unittest.main()