diff options
| author | Kenneth Reitz <me@kennethreitz.com> | 2011-02-17 16:31:52 -0500 |
|---|---|---|
| committer | Kenneth Reitz <me@kennethreitz.com> | 2011-02-17 16:31:52 -0500 |
| commit | ccb29c68fa814424f9fc761fc6ab3d24779a8cc6 (patch) | |
| tree | fb91e7b7526e8c80a82af527ce8d0e810f34d815 /tablib | |
| parent | e077a7f2bc8b37b36ac0da569c244f977c400254 (diff) | |
| download | tablib-ccb29c68fa814424f9fc761fc6ab3d24779a8cc6.tar.gz | |
*shutter* making everyone else happy
Diffstat (limited to 'tablib')
| -rw-r--r-- | tablib/__init__.py | 4 | ||||
| -rw-r--r-- | tablib/core.py | 940 | ||||
| -rw-r--r-- | tablib/formats/_csv.py | 40 | ||||
| -rw-r--r-- | tablib/formats/_json.py | 50 | ||||
| -rw-r--r-- | tablib/formats/_tsv.py | 46 | ||||
| -rw-r--r-- | tablib/formats/_xls.py | 98 | ||||
| -rw-r--r-- | tablib/formats/_yaml.py | 52 | ||||
| -rw-r--r-- | tablib/helpers.py | 40 | ||||
| -rw-r--r-- | tablib/packages/markup.py | 82 |
9 files changed, 676 insertions, 676 deletions
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 <newformats>`. - """ + """ - 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 '<dataset object>' + def __repr__(self): + try: + return '<%s dataset>' % (self.title.lower()) + except AttributeError: + return '<dataset object>' - @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. - """ + 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. + @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: :: + 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}' + data = tablib.Dataset() + data.yaml = '- {age: 90, first_name: John, last_name: Adams}' - Import assumes (for now) that headers exist. - """ - pass + 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. + @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: :: + 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"}]' + data = tablib.Dataset() + data.json = '[{age: 90, first_name: "John", liast_name: "Adams"}]' - Import assumes (for now) that headers exist. - """ + 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. + @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 + ..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. + 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) + 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.""" + def insert_separator(self, index, text='-'): + """Adds a separator to :class:`Dataset` at given index.""" - sep = (index, text) - self._separators.append(sep) + sep = (index, text) + self._separators.append(sep) - def append_separator(self, text='-'): - """Adds a :ref:`seperator <seperators>` to the :class:`Dataset`.""" + def append_separator(self, text='-'): + """Adds a :ref:`seperator <seperators>` 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 + # 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) + 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. + 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 <Dataset.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 <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 <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 '<databook object>' + def __repr__(self): + try: + return '<%s databook>' % (self.title.lower()) + except AttributeError: + return '<databook object>' - 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) - - 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): - - # 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 - - - # 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) + """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, row in enumerate(_package): + for j, col in enumerate(row): + + # 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 + + + # 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) 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</%s>" % ( out, between, tag ) - else: - if single: - out = "%s />" % out - else: - out = "%s>" % out + if between is not None: + out = "%s>%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 </body></html> 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 = [ '</body>', '</html>' ] 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 ): |
