|
@@ -5,23 +5,24 @@
|
|
|
|
|
|
|
|
This module implements the central Tablib objects.
|
|
This module implements the central Tablib objects.
|
|
|
|
|
|
|
|
- :copyright: (c) 2016 by Kenneth Reitz. 2019 Jazzband.
|
|
|
|
|
|
|
+ :copyright: (c) 2016 by Kenneth Reitz.
|
|
|
:license: MIT, see LICENSE for more details.
|
|
:license: MIT, see LICENSE for more details.
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
-from collections import OrderedDict
|
|
|
|
|
from copy import copy
|
|
from copy import copy
|
|
|
from operator import itemgetter
|
|
from operator import itemgetter
|
|
|
|
|
|
|
|
from tablib import formats
|
|
from tablib import formats
|
|
|
|
|
|
|
|
-from tablib.compat import unicode
|
|
|
|
|
|
|
+from tablib.compat import OrderedDict, unicode
|
|
|
|
|
|
|
|
|
|
|
|
|
__title__ = 'tablib'
|
|
__title__ = 'tablib'
|
|
|
|
|
+__version__ = '0.12.1'
|
|
|
|
|
+__build__ = 0x001201
|
|
|
__author__ = 'Kenneth Reitz'
|
|
__author__ = 'Kenneth Reitz'
|
|
|
__license__ = 'MIT'
|
|
__license__ = 'MIT'
|
|
|
-__copyright__ = 'Copyright 2017 Kenneth Reitz. 2019 Jazzband.'
|
|
|
|
|
|
|
+__copyright__ = 'Copyright 2017 Kenneth Reitz'
|
|
|
__docformat__ = 'restructuredtext'
|
|
__docformat__ = 'restructuredtext'
|
|
|
|
|
|
|
|
|
|
|
|
@@ -104,6 +105,8 @@ class Row(object):
|
|
|
return bool(len(set(tag) & set(self.tags)))
|
|
return bool(len(set(tag) & set(self.tags)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
class Dataset(object):
|
|
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.
|
|
functionality.
|
|
@@ -138,7 +141,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
data = tablib.Dataset(*data, headers=headers)
|
|
data = tablib.Dataset(*data, headers=headers)
|
|
|
|
|
|
|
|
- :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
|
|
:param title: (optional) string to use as title of the Dataset
|
|
|
|
|
|
|
@@ -169,11 +172,13 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self._register_formats()
|
|
self._register_formats()
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def __len__(self):
|
|
def __len__(self):
|
|
|
return self.height
|
|
return self.height
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def __getitem__(self, key):
|
|
def __getitem__(self, key):
|
|
|
- if isinstance(key, (str, unicode)):
|
|
|
|
|
|
|
+ if isinstance(key, str) or isinstance(key, unicode):
|
|
|
if key in self.headers:
|
|
if key in self.headers:
|
|
|
pos = self.headers.index(key) # get 'key' index from each data
|
|
pos = self.headers.index(key) # get 'key' index from each data
|
|
|
return [row[pos] for row in self._data]
|
|
return [row[pos] for row in self._data]
|
|
@@ -190,8 +195,9 @@ class Dataset(object):
|
|
|
self._validate(value)
|
|
self._validate(value)
|
|
|
self._data[key] = Row(value)
|
|
self._data[key] = Row(value)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def __delitem__(self, key):
|
|
def __delitem__(self, key):
|
|
|
- if isinstance(key, (str, unicode)):
|
|
|
|
|
|
|
+ if isinstance(key, str) or isinstance(key, unicode):
|
|
|
|
|
|
|
|
if key in self.headers:
|
|
if key in self.headers:
|
|
|
|
|
|
|
@@ -207,6 +213,7 @@ class Dataset(object):
|
|
|
else:
|
|
else:
|
|
|
del self._data[key]
|
|
del self._data[key]
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def __repr__(self):
|
|
def __repr__(self):
|
|
|
try:
|
|
try:
|
|
|
return '<%s dataset>' % (self.title.lower())
|
|
return '<%s dataset>' % (self.title.lower())
|
|
@@ -259,6 +266,7 @@ class Dataset(object):
|
|
|
except AttributeError:
|
|
except AttributeError:
|
|
|
cls._formats[fmt.title] = (None, None)
|
|
cls._formats[fmt.title] = (None, None)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def _validate(self, row=None, col=None, safety=False):
|
|
def _validate(self, row=None, col=None, safety=False):
|
|
|
"""Assures size of every row in dataset is of proper proportions."""
|
|
"""Assures size of every row in dataset is of proper proportions."""
|
|
|
if row:
|
|
if row:
|
|
@@ -278,6 +286,7 @@ class Dataset(object):
|
|
|
raise InvalidDimensions
|
|
raise InvalidDimensions
|
|
|
return False
|
|
return False
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def _package(self, dicts=True, ordered=True):
|
|
def _package(self, dicts=True, ordered=True):
|
|
|
"""Packages Dataset into lists of dictionaries for transmission."""
|
|
"""Packages Dataset into lists of dictionaries for transmission."""
|
|
|
# TODO: Dicts default to false?
|
|
# TODO: Dicts default to false?
|
|
@@ -302,6 +311,7 @@ class Dataset(object):
|
|
|
except IndexError:
|
|
except IndexError:
|
|
|
raise InvalidDatasetIndex
|
|
raise InvalidDatasetIndex
|
|
|
|
|
|
|
|
|
|
+
|
|
|
if self.headers:
|
|
if self.headers:
|
|
|
if dicts:
|
|
if dicts:
|
|
|
data = [dict_pack(list(zip(self.headers, data_row))) for data_row in _data]
|
|
data = [dict_pack(list(zip(self.headers, data_row))) for data_row in _data]
|
|
@@ -312,6 +322,8 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return data
|
|
return data
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def _get_headers(self):
|
|
def _get_headers(self):
|
|
|
"""An *optional* list of strings to be used for header rows and attribute names.
|
|
"""An *optional* list of strings to be used for header rows and attribute names.
|
|
|
|
|
|
|
@@ -320,6 +332,7 @@ class Dataset(object):
|
|
|
"""
|
|
"""
|
|
|
return self.__headers
|
|
return self.__headers
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def _set_headers(self, collection):
|
|
def _set_headers(self, collection):
|
|
|
"""Validating headers setter."""
|
|
"""Validating headers setter."""
|
|
|
self._validate(collection)
|
|
self._validate(collection)
|
|
@@ -333,6 +346,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
headers = property(_get_headers, _set_headers)
|
|
headers = property(_get_headers, _set_headers)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def _get_dict(self):
|
|
def _get_dict(self):
|
|
|
"""A native Python representation of the :class:`Dataset` object. If headers have
|
|
"""A native Python representation of the :class:`Dataset` object. If headers have
|
|
|
been set, a list of Python dictionaries will be returned. If no headers have been set,
|
|
been set, a list of Python dictionaries will be returned. If no headers have been set,
|
|
@@ -346,6 +360,7 @@ class Dataset(object):
|
|
|
"""
|
|
"""
|
|
|
return self._package()
|
|
return self._package()
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def _set_dict(self, pickle):
|
|
def _set_dict(self, pickle):
|
|
|
"""A native Python representation of the Dataset object. If headers have been
|
|
"""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 Python dictionaries will be returned. If no headers have been
|
|
@@ -378,6 +393,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
dict = property(_get_dict, _set_dict)
|
|
dict = property(_get_dict, _set_dict)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def _clean_col(self, col):
|
|
def _clean_col(self, col):
|
|
|
"""Prepares the given column for insert/append."""
|
|
"""Prepares the given column for insert/append."""
|
|
|
|
|
|
|
@@ -395,6 +411,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return col
|
|
return col
|
|
|
|
|
|
|
|
|
|
+
|
|
|
@property
|
|
@property
|
|
|
def height(self):
|
|
def height(self):
|
|
|
"""The number of rows currently in the :class:`Dataset`.
|
|
"""The number of rows currently in the :class:`Dataset`.
|
|
@@ -402,6 +419,7 @@ class Dataset(object):
|
|
|
"""
|
|
"""
|
|
|
return len(self._data)
|
|
return len(self._data)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
@property
|
|
@property
|
|
|
def width(self):
|
|
def width(self):
|
|
|
"""The number of columns currently in the :class:`Dataset`.
|
|
"""The number of columns currently in the :class:`Dataset`.
|
|
@@ -416,11 +434,12 @@ class Dataset(object):
|
|
|
except TypeError:
|
|
except TypeError:
|
|
|
return 0
|
|
return 0
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def load(self, in_stream, format=None, **kwargs):
|
|
def load(self, in_stream, format=None, **kwargs):
|
|
|
"""
|
|
"""
|
|
|
Import `in_stream` to the :class:`Dataset` object using the `format`.
|
|
Import `in_stream` to the :class:`Dataset` object using the `format`.
|
|
|
|
|
|
|
|
- :param \\*\\*kwargs: (optional) custom configuration to the format `import_set`.
|
|
|
|
|
|
|
+ :param \*\*kwargs: (optional) custom configuration to the format `import_set`.
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
if not format:
|
|
if not format:
|
|
@@ -433,11 +452,13 @@ class Dataset(object):
|
|
|
import_set(self, in_stream, **kwargs)
|
|
import_set(self, in_stream, **kwargs)
|
|
|
return self
|
|
return self
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def export(self, format, **kwargs):
|
|
def export(self, format, **kwargs):
|
|
|
"""
|
|
"""
|
|
|
Export :class:`Dataset` object to `format`.
|
|
Export :class:`Dataset` object to `format`.
|
|
|
|
|
|
|
|
- :param \\*\\*kwargs: (optional) custom configuration to the format `export_set`.
|
|
|
|
|
|
|
+ :param \*\*kwargs: (optional) custom configuration to the format `export_set`.
|
|
|
"""
|
|
"""
|
|
|
export_set, import_set = self._formats.get(format, (None, None))
|
|
export_set, import_set = self._formats.get(format, (None, None))
|
|
|
if not export_set:
|
|
if not export_set:
|
|
@@ -505,9 +526,9 @@ class Dataset(object):
|
|
|
|
|
|
|
|
Import assumes (for now) that headers exist.
|
|
Import assumes (for now) that headers exist.
|
|
|
|
|
|
|
|
- .. admonition:: Binary Warning for Python 2
|
|
|
|
|
|
|
+ .. admonition:: Binary Warning
|
|
|
|
|
|
|
|
- :class:`Dataset.csv` uses \\r\\n line endings by default so, in Python 2, make
|
|
|
|
|
|
|
+ :class:`Dataset.csv` uses \\r\\n line endings by default, so make
|
|
|
sure to write in binary mode::
|
|
sure to write in binary mode::
|
|
|
|
|
|
|
|
with open('output.csv', 'wb') as f:
|
|
with open('output.csv', 'wb') as f:
|
|
@@ -515,21 +536,10 @@ class Dataset(object):
|
|
|
|
|
|
|
|
If you do not do this, and you export the file on Windows, your
|
|
If you do not do this, and you export the file on Windows, your
|
|
|
CSV file will open in Excel with a blank line between each row.
|
|
CSV file will open in Excel with a blank line between each row.
|
|
|
-
|
|
|
|
|
- .. admonition:: Line endings for Python 3
|
|
|
|
|
-
|
|
|
|
|
- :class:`Dataset.csv` uses \\r\\n line endings by default so, in Python 3, make
|
|
|
|
|
- sure to include newline='' otherwise you will get a blank line between each row
|
|
|
|
|
- when you open the file in Excel::
|
|
|
|
|
-
|
|
|
|
|
- with open('output.csv', 'w', newline='') as f:
|
|
|
|
|
- f.write(data.csv)
|
|
|
|
|
-
|
|
|
|
|
- If you do not do this, and you export the file on Windows, your
|
|
|
|
|
- CSV file will open in Excel with a blank line between each row.
|
|
|
|
|
"""
|
|
"""
|
|
|
pass
|
|
pass
|
|
|
|
|
|
|
|
|
|
+
|
|
|
@property
|
|
@property
|
|
|
def tsv():
|
|
def tsv():
|
|
|
"""A TSV representation of the :class:`Dataset` object. The top row will contain
|
|
"""A TSV representation of the :class:`Dataset` object. The top row will contain
|
|
@@ -606,7 +616,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
# To import data from an existing DBF file:
|
|
# To import data from an existing DBF file:
|
|
|
data = tablib.Dataset()
|
|
data = tablib.Dataset()
|
|
|
- data.dbf = open('existing_table.dbf', mode='rb').read()
|
|
|
|
|
|
|
+ data.dbf = open('existing_table.dbf').read()
|
|
|
|
|
|
|
|
# to import data from an ASCII-encoded bytestring:
|
|
# to import data from an ASCII-encoded bytestring:
|
|
|
data = tablib.Dataset()
|
|
data = tablib.Dataset()
|
|
@@ -621,6 +631,7 @@ class Dataset(object):
|
|
|
"""
|
|
"""
|
|
|
pass
|
|
pass
|
|
|
|
|
|
|
|
|
|
+
|
|
|
@property
|
|
@property
|
|
|
def latex():
|
|
def latex():
|
|
|
"""A LaTeX booktabs representation of the :class:`Dataset` object. If a
|
|
"""A LaTeX booktabs representation of the :class:`Dataset` object. If a
|
|
@@ -630,13 +641,6 @@ class Dataset(object):
|
|
|
"""
|
|
"""
|
|
|
pass
|
|
pass
|
|
|
|
|
|
|
|
- @property
|
|
|
|
|
- def jira():
|
|
|
|
|
- """A Jira table representation of the :class:`Dataset` object.
|
|
|
|
|
-
|
|
|
|
|
- .. note:: This method can be used for export only.
|
|
|
|
|
- """
|
|
|
|
|
- pass
|
|
|
|
|
|
|
|
|
|
# ----
|
|
# ----
|
|
|
# Rows
|
|
# Rows
|
|
@@ -654,6 +658,7 @@ class Dataset(object):
|
|
|
self._validate(row)
|
|
self._validate(row)
|
|
|
self._data.insert(index, Row(row, tags=tags))
|
|
self._data.insert(index, Row(row, tags=tags))
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def rpush(self, row, tags=list()):
|
|
def rpush(self, row, tags=list()):
|
|
|
"""Adds a row to the end of the :class:`Dataset`.
|
|
"""Adds a row to the end of the :class:`Dataset`.
|
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
@@ -661,6 +666,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self.insert(self.height, row=row, tags=tags)
|
|
self.insert(self.height, row=row, tags=tags)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def lpush(self, row, tags=list()):
|
|
def lpush(self, row, tags=list()):
|
|
|
"""Adds a row to the top of the :class:`Dataset`.
|
|
"""Adds a row to the top of the :class:`Dataset`.
|
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
@@ -668,6 +674,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self.insert(0, row=row, tags=tags)
|
|
self.insert(0, row=row, tags=tags)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def append(self, row, tags=list()):
|
|
def append(self, row, tags=list()):
|
|
|
"""Adds a row to the :class:`Dataset`.
|
|
"""Adds a row to the :class:`Dataset`.
|
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
@@ -683,6 +690,7 @@ class Dataset(object):
|
|
|
for row in rows:
|
|
for row in rows:
|
|
|
self.append(row, tags)
|
|
self.append(row, tags)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def lpop(self):
|
|
def lpop(self):
|
|
|
"""Removes and returns the first row of the :class:`Dataset`."""
|
|
"""Removes and returns the first row of the :class:`Dataset`."""
|
|
|
|
|
|
|
@@ -691,6 +699,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return cache
|
|
return cache
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def rpop(self):
|
|
def rpop(self):
|
|
|
"""Removes and returns the last row of the :class:`Dataset`."""
|
|
"""Removes and returns the last row of the :class:`Dataset`."""
|
|
|
|
|
|
|
@@ -699,11 +708,13 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return cache
|
|
return cache
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def pop(self):
|
|
def pop(self):
|
|
|
"""Removes and returns the last row of the :class:`Dataset`."""
|
|
"""Removes and returns the last row of the :class:`Dataset`."""
|
|
|
|
|
|
|
|
return self.rpop()
|
|
return self.rpop()
|
|
|
|
|
|
|
|
|
|
+
|
|
|
# -------
|
|
# -------
|
|
|
# Columns
|
|
# Columns
|
|
|
# -------
|
|
# -------
|
|
@@ -758,6 +769,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self.headers.insert(index, header)
|
|
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):
|
|
@@ -767,6 +779,8 @@ class Dataset(object):
|
|
|
else:
|
|
else:
|
|
|
self._data = [Row([row]) for row in col]
|
|
self._data = [Row([row]) for row in col]
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def rpush_col(self, col, header=None):
|
|
def rpush_col(self, col, header=None):
|
|
|
"""Adds a column to the end of the :class:`Dataset`.
|
|
"""Adds a column to the end of the :class:`Dataset`.
|
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
@@ -774,6 +788,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self.insert_col(self.width, col, header=header)
|
|
self.insert_col(self.width, col, header=header)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def lpush_col(self, col, header=None):
|
|
def lpush_col(self, col, header=None):
|
|
|
"""Adds a column to the top of the :class:`Dataset`.
|
|
"""Adds a column to the top of the :class:`Dataset`.
|
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
See :class:`Dataset.insert` for additional documentation.
|
|
@@ -781,12 +796,14 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self.insert_col(0, col, header=header)
|
|
self.insert_col(0, col, header=header)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def insert_separator(self, index, text='-'):
|
|
def insert_separator(self, index, text='-'):
|
|
|
"""Adds a separator to :class:`Dataset` at given index."""
|
|
"""Adds a separator to :class:`Dataset` at given index."""
|
|
|
|
|
|
|
|
sep = (index, text)
|
|
sep = (index, text)
|
|
|
self._separators.append(sep)
|
|
self._separators.append(sep)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def append_separator(self, text='-'):
|
|
def append_separator(self, text='-'):
|
|
|
"""Adds a :ref:`separator <separators>` to the :class:`Dataset`."""
|
|
"""Adds a :ref:`separator <separators>` to the :class:`Dataset`."""
|
|
|
|
|
|
|
@@ -798,6 +815,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self.insert_separator(index, text)
|
|
self.insert_separator(index, text)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def append_col(self, col, header=None):
|
|
def append_col(self, col, header=None):
|
|
|
"""Adds a column to the :class:`Dataset`.
|
|
"""Adds a column to the :class:`Dataset`.
|
|
|
See :class:`Dataset.insert_col` for additional documentation.
|
|
See :class:`Dataset.insert_col` for additional documentation.
|
|
@@ -805,26 +823,27 @@ class Dataset(object):
|
|
|
|
|
|
|
|
self.rpush_col(col, header)
|
|
self.rpush_col(col, header)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def get_col(self, index):
|
|
def get_col(self, index):
|
|
|
"""Returns the column from the :class:`Dataset` at the given index."""
|
|
"""Returns the column from the :class:`Dataset` at the given index."""
|
|
|
|
|
|
|
|
return [row[index] for row in self._data]
|
|
return [row[index] for row in self._data]
|
|
|
|
|
|
|
|
|
|
+
|
|
|
# ----
|
|
# ----
|
|
|
# Misc
|
|
# Misc
|
|
|
# ----
|
|
# ----
|
|
|
|
|
|
|
|
def add_formatter(self, col, handler):
|
|
def add_formatter(self, col, handler):
|
|
|
- """Adds a formatter to the :class:`Dataset`.
|
|
|
|
|
|
|
+ """Adds a :ref:`formatter` to the :class:`Dataset`.
|
|
|
|
|
|
|
|
.. versionadded:: 0.9.5
|
|
.. versionadded:: 0.9.5
|
|
|
-
|
|
|
|
|
- :param col: column to. Accepts index int or header str.
|
|
|
|
|
- :param handler: reference to callback function to execute against
|
|
|
|
|
- each cell value.
|
|
|
|
|
|
|
+ :param col: column to. Accepts index int or header str.
|
|
|
|
|
+ :param handler: reference to callback function to execute
|
|
|
|
|
+ against each cell value.
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
- if isinstance(col, unicode):
|
|
|
|
|
|
|
+ if isinstance(col, str):
|
|
|
if col in self.headers:
|
|
if col in self.headers:
|
|
|
col = self.headers.index(col) # get 'key' index from each data
|
|
col = self.headers.index(col) # get 'key' index from each data
|
|
|
else:
|
|
else:
|
|
@@ -837,6 +856,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return True
|
|
return True
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def filter(self, tag):
|
|
def filter(self, tag):
|
|
|
"""Returns a new instance of the :class:`Dataset`, excluding any rows
|
|
"""Returns a new instance of the :class:`Dataset`, excluding any rows
|
|
|
that do not contain the given :ref:`tags <tags>`.
|
|
that do not contain the given :ref:`tags <tags>`.
|
|
@@ -846,6 +866,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return _dset
|
|
return _dset
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def sort(self, col, reverse=False):
|
|
def sort(self, col, reverse=False):
|
|
|
"""Sort a :class:`Dataset` by a specific column, given string (for
|
|
"""Sort a :class:`Dataset` by a specific column, given string (for
|
|
|
header) or integer (for column index). The order can be reversed by
|
|
header) or integer (for column index). The order can be reversed by
|
|
@@ -855,7 +876,7 @@ class Dataset(object):
|
|
|
sorted.
|
|
sorted.
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
- if isinstance(col, (str, unicode)):
|
|
|
|
|
|
|
+ if isinstance(col, str) or isinstance(col, unicode):
|
|
|
|
|
|
|
|
if not self.headers:
|
|
if not self.headers:
|
|
|
raise HeadersNeeded
|
|
raise HeadersNeeded
|
|
@@ -881,8 +902,10 @@ class Dataset(object):
|
|
|
row = item
|
|
row = item
|
|
|
_dset.append(row=row)
|
|
_dset.append(row=row)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
return _dset
|
|
return _dset
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def transpose(self):
|
|
def transpose(self):
|
|
|
"""Transpose a :class:`Dataset`, turning rows into columns and vice
|
|
"""Transpose a :class:`Dataset`, turning rows into columns and vice
|
|
|
versa, returning a new ``Dataset`` instance. The first row of the
|
|
versa, returning a new ``Dataset`` instance. The first row of the
|
|
@@ -911,6 +934,7 @@ class Dataset(object):
|
|
|
_dset.append(row=row_data)
|
|
_dset.append(row=row_data)
|
|
|
return _dset
|
|
return _dset
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def stack(self, other):
|
|
def stack(self, other):
|
|
|
"""Stack two :class:`Dataset` instances together by
|
|
"""Stack two :class:`Dataset` instances together by
|
|
|
joining at the row level, and return new combined
|
|
joining at the row level, and return new combined
|
|
@@ -933,6 +957,7 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return _dset
|
|
return _dset
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def stack_cols(self, other):
|
|
def stack_cols(self, other):
|
|
|
"""Stack two :class:`Dataset` instances together by
|
|
"""Stack two :class:`Dataset` instances together by
|
|
|
joining at the column level, and return a new
|
|
joining at the column level, and return a new
|
|
@@ -966,17 +991,20 @@ class Dataset(object):
|
|
|
|
|
|
|
|
return _dset
|
|
return _dset
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def remove_duplicates(self):
|
|
def remove_duplicates(self):
|
|
|
"""Removes all duplicate rows from the :class:`Dataset` object
|
|
"""Removes all duplicate rows from the :class:`Dataset` object
|
|
|
while maintaining the original order."""
|
|
while maintaining the original order."""
|
|
|
seen = set()
|
|
seen = set()
|
|
|
self._data[:] = [row for row in self._data if not (tuple(row) in seen or seen.add(tuple(row)))]
|
|
self._data[:] = [row for row in self._data if not (tuple(row) in seen or seen.add(tuple(row)))]
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def wipe(self):
|
|
def wipe(self):
|
|
|
"""Removes all content and headers from the :class:`Dataset` object."""
|
|
"""Removes all content and headers from the :class:`Dataset` object."""
|
|
|
self._data = list()
|
|
self._data = list()
|
|
|
self.__headers = None
|
|
self.__headers = None
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def subset(self, rows=None, cols=None):
|
|
def subset(self, rows=None, cols=None):
|
|
|
"""Returns a new instance of the :class:`Dataset`,
|
|
"""Returns a new instance of the :class:`Dataset`,
|
|
|
including only specified rows and columns.
|
|
including only specified rows and columns.
|
|
@@ -1017,6 +1045,7 @@ class Dataset(object):
|
|
|
return _dset
|
|
return _dset
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
class Databook(object):
|
|
class Databook(object):
|
|
|
"""A book of :class:`Dataset` objects.
|
|
"""A book of :class:`Dataset` objects.
|
|
|
"""
|
|
"""
|
|
@@ -1042,6 +1071,7 @@ class Databook(object):
|
|
|
"""Removes all :class:`Dataset` objects from the :class:`Databook`."""
|
|
"""Removes all :class:`Dataset` objects from the :class:`Databook`."""
|
|
|
self._datasets = []
|
|
self._datasets = []
|
|
|
|
|
|
|
|
|
|
+
|
|
|
@classmethod
|
|
@classmethod
|
|
|
def _register_formats(cls):
|
|
def _register_formats(cls):
|
|
|
"""Adds format properties."""
|
|
"""Adds format properties."""
|
|
@@ -1067,6 +1097,7 @@ class Databook(object):
|
|
|
else:
|
|
else:
|
|
|
raise InvalidDatasetType
|
|
raise InvalidDatasetType
|
|
|
|
|
|
|
|
|
|
+
|
|
|
def _package(self, ordered=True):
|
|
def _package(self, ordered=True):
|
|
|
"""Packages :class:`Databook` for delivery."""
|
|
"""Packages :class:`Databook` for delivery."""
|
|
|
collector = []
|
|
collector = []
|
|
@@ -1083,16 +1114,17 @@ class Databook(object):
|
|
|
))
|
|
))
|
|
|
return collector
|
|
return collector
|
|
|
|
|
|
|
|
|
|
+
|
|
|
@property
|
|
@property
|
|
|
def size(self):
|
|
def size(self):
|
|
|
"""The number of the :class:`Dataset` objects within :class:`Databook`."""
|
|
"""The number of the :class:`Dataset` objects within :class:`Databook`."""
|
|
|
return len(self._datasets)
|
|
return len(self._datasets)
|
|
|
|
|
|
|
|
- def load(self, in_stream, format, **kwargs):
|
|
|
|
|
|
|
+ def load(self, format, in_stream, **kwargs):
|
|
|
"""
|
|
"""
|
|
|
Import `in_stream` to the :class:`Databook` object using the `format`.
|
|
Import `in_stream` to the :class:`Databook` object using the `format`.
|
|
|
|
|
|
|
|
- :param \\*\\*kwargs: (optional) custom configuration to the format `import_book`.
|
|
|
|
|
|
|
+ :param \*\*kwargs: (optional) custom configuration to the format `import_book`.
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
if not format:
|
|
if not format:
|
|
@@ -1109,7 +1141,7 @@ class Databook(object):
|
|
|
"""
|
|
"""
|
|
|
Export :class:`Databook` object to `format`.
|
|
Export :class:`Databook` object to `format`.
|
|
|
|
|
|
|
|
- :param \\*\\*kwargs: (optional) custom configuration to the format `export_book`.
|
|
|
|
|
|
|
+ :param \*\*kwargs: (optional) custom configuration to the format `export_book`.
|
|
|
"""
|
|
"""
|
|
|
export_book, import_book = self._formats.get(format, (None, None))
|
|
export_book, import_book = self._formats.get(format, (None, None))
|
|
|
if not export_book:
|
|
if not export_book:
|
|
@@ -1127,7 +1159,6 @@ def detect_format(stream):
|
|
|
except AttributeError:
|
|
except AttributeError:
|
|
|
pass
|
|
pass
|
|
|
|
|
|
|
|
-
|
|
|
|
|
def import_set(stream, format=None, **kwargs):
|
|
def import_set(stream, format=None, **kwargs):
|
|
|
"""Return dataset of given stream."""
|
|
"""Return dataset of given stream."""
|
|
|
|
|
|
|
@@ -1147,14 +1178,11 @@ class InvalidDatasetType(Exception):
|
|
|
class InvalidDimensions(Exception):
|
|
class InvalidDimensions(Exception):
|
|
|
"Invalid size"
|
|
"Invalid size"
|
|
|
|
|
|
|
|
-
|
|
|
|
|
class InvalidDatasetIndex(Exception):
|
|
class InvalidDatasetIndex(Exception):
|
|
|
"Outside of Dataset size"
|
|
"Outside of Dataset size"
|
|
|
|
|
|
|
|
-
|
|
|
|
|
class HeadersNeeded(Exception):
|
|
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):
|
|
class UnsupportedFormat(NotImplementedError):
|
|
|
"Format is not supported"
|
|
"Format is not supported"
|