Commits

Lynn Rees committed d22fe6c

- intial commit

Comments (0)

Files changed (14)

+Tablib is written and maintained by Kenneth Reitz and
+various contributors:
+
+Development Lead
+````````````````
+
+- Kenneth Reitz <me@kennethreitz.com>
+
+
+Patches and Suggestions
+```````````````````````
+
+- Luke Lee
+History
+=======
+
+0.8.1 (2010-09-28)
+------------------
+* Packaging Fix
+
+
+0.8.0 (2010-09-25)
+------------------
+* New format plugin system!
+* Imports! ELEGANT Imports!
+* Tests. Lots of tests.
+
+
+0.7.1 (2010-09-20)
+------------------
+
+* Reverting methods back to properties. 
+* Windows bug compenated in documentation.
+
+
+0.7.0 (2010-09-20)
+------------------
+
+* Renamed DataBook Databook for consistiency.
+* Export properties changed to methods (XLS filename / StringIO bug).
+* Optional Dataset.xls(path='filename') support (for writing on windows).
+* Added utf-8 on the worksheet level.
+
+
+0.6.4 (2010-09-19)
+------------------
+
+* Updated unicode export for XLS.
+* More exhaustive unit tests.
+
+
+0.6.3 (2010-09-14)
+------------------
+* Added Dataset.append() support for columns.
+
+
+0.6.2 (2010-09-13)
+------------------
+* Fixed Dataset.append() error on empty dataset.
+* Updated Dataset.headers property w/ validation.
+* Added Testing Fixtures.
+
+0.6.1 (2010-09-12)
+------------------
+
+* Packaging hotfixes.
+
+
+0.6.0 (2010-09-11)
+------------------
+
+* Public Release.
+* Export Support for XLS, JSON, YAML, and CSV.
+* DataBook Export for XLS, JSON, and YAML.
+* Python Dict Property Support.
+
+Copyright (c) 2010 Kenneth Reitz.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+Metadata-Version: 1.0
+Name: tablib
+Version: 0.8.1
+Summary: Format agnostic tabular data library (XLS, JSON, YAML, CSV)
+Home-page: http://github.com/kennethreitz/tablib
+Author: Kenneth Reitz
+Author-email: me@kennethreitz.com
+License: MIT
+Description: Tablib: format-agnostic tabular dataset library
+        ===============================================
+        
+        ::
+        
+        	_____         ______  ___________ ______  
+        	__  /_______ ____  /_ ___  /___(_)___  /_ 
+        	_  __/_  __ `/__  __ \__  / __  / __  __ \
+        	/ /_  / /_/ / _  /_/ /_  /  _  /  _  /_/ /
+        	\__/  \__,_/  /_.___/ /_/   /_/   /_.___/
+        
+        
+        
+        Tablib is a format-agnostic tabular dataset library, written in Python. 
+        
+        Output formats supported:
+        
+        - Excel (Sets + Books)
+        - JSON (Sets + Books)
+        - YAML (Sets + Books)
+        - CSV (Sets)
+        
+        Import formats supported:
+        
+        - JSON (Sets + Books)
+        - YAML (Sets + Books)
+        - CSV (Sets)
+        
+        Note that tablib *purposefully* excludes XML support. It always will.
+        
+        Overview
+        --------
+        
+        `tablib.Dataset()`
+        	A Dataset is a table of tabular data. It may or may not have a header row. They can be build and maniuplated as raw Python datatypes (Lists of tuples|dictonaries). Datasets can be imported from JSON, YAML, and CSV; they can be exported to Excel (XLS), JSON, YAML, and CSV.
+        	
+        `tablib.Databook()`
+        	A Databook is a set of Datasets. The most common form of a Databook is an Excel file with multiple spreadsheets. Databooks can be imported from JSON and YAML; they can be exported to Excel (XLS), JSON, and YAML.
+        
+        Usage
+        -----
+        
+            
+        Populate fresh data files: ::
+            
+            headers = ('first_name', 'last_name')
+        
+            data = [
+                ('John', 'Adams'),
+                ('George', 'Washington')
+            ]
+            
+            data = tablib.Dataset(*data, headers=headers)
+        
+        
+        Intelligently add new rows: ::
+        
+            >>> data.append(('Henry', 'Ford'))
+        
+        Intelligently add new columns: ::
+        
+            >>> data.append(col=('age', 90, 67, 83))
+            
+        Slice rows:  ::
+        
+            >>> print data[:2]
+            [('John', 'Adams', 90), ('George', 'Washington', 67)]
+            
+        
+        Slice columns by header: ::
+        
+            >>> print data['first_name']
+            ['John', 'George', 'Henry']
+        
+        Easily delete rows: ::
+        
+            >>> del data[1]
+        
+        Exports
+        -------
+        
+        Drumroll please...........
+        
+        JSON! 
+        +++++
+        ::
+        
+        	>>> print data.json
+        	[
+        	  {
+        	    "last_name": "Adams",
+        	    "age": 90,
+        	    "first_name": "John"
+        	  },
+        	  {
+        	    "last_name": "Ford",
+        	    "age": 83,
+        	    "first_name": "Henry"
+        	  }
+        	]
+        	
+        
+        YAML! 
+        +++++
+        ::
+        
+        	>>> print data.yaml
+        	- {age: 90, first_name: John, last_name: Adams}
+        	- {age: 83, first_name: Henry, last_name: Ford}
+        	
+        CSV... 
+        ++++++
+        ::
+        
+        	>>> print data.csv
+        	first_name,last_name,age 
+        	John,Adams,90 
+        	Henry,Ford,83 
+        	
+        EXCEL! 
+        ++++++
+        ::
+        
+        	>>> open('people.xls', 'wb').write(data.xls)
+        
+        It's that easy.
+        
+        Imports!
+        --------
+        
+        JSON
+        ++++
+        
+        ::
+        
+        	>>> data.json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]'
+        	>>> print data[0]
+        	('John', 'Adams', 90)
+        
+        
+        YAML
+        ++++
+        ::
+        
+        	>>> data.yaml = '- {age: 90, first_name: John, last_name: Adams}'
+        	>>> print data[0]
+        	('John', 'Adams', 90)
+        
+        CSV
+        +++
+        ::
+        
+        	>>> data.yaml = 'age, first_name, last_name\n90, John, Adams'
+        	>>> print data[0]
+        	('John', 'Adams', 90)
+        	
+        	>>> print data.yaml
+        	- {age: 90, first_name: John, last_name: Adams}
+        	
+        
+        
+        Installation
+        ------------
+        
+        To install tablib, simply: ::
+        
+        	$ pip install tablib
+        	
+        Or, if you absolutely must: ::
+        
+        	$ easy_install tablib
+            
+        
+        Contribute
+        ----------
+        
+        If you'd like to contribute, simply fork `the repository`_, commit your changes to the **develop** branch (or branch off of it), and send a pull request. Make sure you add yourself to AUTHORS_.
+        
+        
+        Roadmap
+        -------
+        - Release CLI Interface
+        - Auto-detect import format
+        - Add possible other exports (SQL?)
+        - Ability to assign types to rows (set, regex=, &c.)
+        
+        .. _`the repository`: http://github.com/kennethreitz/tablib
+        .. _AUTHORS: http://github.com/kennethreitz/tablib/blob/master/AUTHORS
+        
+        
+        History
+        =======
+        
+        0.8.1 (2010-09-28)
+        ------------------
+        * Packaging Fix
+        
+        
+        0.8.0 (2010-09-25)
+        ------------------
+        * New format plugin system!
+        * Imports! ELEGANT Imports!
+        * Tests. Lots of tests.
+        
+        
+        0.7.1 (2010-09-20)
+        ------------------
+        
+        * Reverting methods back to properties. 
+        * Windows bug compenated in documentation.
+        
+        
+        0.7.0 (2010-09-20)
+        ------------------
+        
+        * Renamed DataBook Databook for consistiency.
+        * Export properties changed to methods (XLS filename / StringIO bug).
+        * Optional Dataset.xls(path='filename') support (for writing on windows).
+        * Added utf-8 on the worksheet level.
+        
+        
+        0.6.4 (2010-09-19)
+        ------------------
+        
+        * Updated unicode export for XLS.
+        * More exhaustive unit tests.
+        
+        
+        0.6.3 (2010-09-14)
+        ------------------
+        * Added Dataset.append() support for columns.
+        
+        
+        0.6.2 (2010-09-13)
+        ------------------
+        * Fixed Dataset.append() error on empty dataset.
+        * Updated Dataset.headers property w/ validation.
+        * Added Testing Fixtures.
+        
+        0.6.1 (2010-09-12)
+        ------------------
+        
+        * Packaging hotfixes.
+        
+        
+        0.6.0 (2010-09-11)
+        ------------------
+        
+        * Public Release.
+        * Export Support for XLS, JSON, YAML, and CSV.
+        * DataBook Export for XLS, JSON, and YAML.
+        * Python Dict Property Support.
+        
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Tablib: format-agnostic tabular dataset library
+===============================================
+
+::
+
+	_____         ______  ___________ ______  
+	__  /_______ ____  /_ ___  /___(_)___  /_ 
+	_  __/_  __ `/__  __ \__  / __  / __  __ \
+	/ /_  / /_/ / _  /_/ /_  /  _  /  _  /_/ /
+	\__/  \__,_/  /_.___/ /_/   /_/   /_.___/
+
+
+
+Tablib is a format-agnostic tabular dataset library, written in Python. 
+
+Output formats supported:
+
+- Excel (Sets + Books)
+- JSON (Sets + Books)
+- YAML (Sets + Books)
+- CSV (Sets)
+
+Import formats supported:
+
+- JSON (Sets + Books)
+- YAML (Sets + Books)
+- CSV (Sets)
+
+Note that tablib *purposefully* excludes XML support. It always will.
+
+Overview
+--------
+
+`tablib.Dataset()`
+	A Dataset is a table of tabular data. It may or may not have a header row. They can be build and maniuplated as raw Python datatypes (Lists of tuples|dictonaries). Datasets can be imported from JSON, YAML, and CSV; they can be exported to Excel (XLS), JSON, YAML, and CSV.
+	
+`tablib.Databook()`
+	A Databook is a set of Datasets. The most common form of a Databook is an Excel file with multiple spreadsheets. Databooks can be imported from JSON and YAML; they can be exported to Excel (XLS), JSON, and YAML.
+
+Usage
+-----
+
+    
+Populate fresh data files: ::
+    
+    headers = ('first_name', 'last_name')
+
+    data = [
+        ('John', 'Adams'),
+        ('George', 'Washington')
+    ]
+    
+    data = tablib.Dataset(*data, headers=headers)
+
+
+Intelligently add new rows: ::
+
+    >>> data.append(('Henry', 'Ford'))
+
+Intelligently add new columns: ::
+
+    >>> data.append(col=('age', 90, 67, 83))
+    
+Slice rows:  ::
+
+    >>> print data[:2]
+    [('John', 'Adams', 90), ('George', 'Washington', 67)]
+    
+
+Slice columns by header: ::
+
+    >>> print data['first_name']
+    ['John', 'George', 'Henry']
+
+Easily delete rows: ::
+
+    >>> del data[1]
+
+Exports
+-------
+
+Drumroll please...........
+
+JSON! 
++++++
+::
+
+	>>> print data.json
+	[
+	  {
+	    "last_name": "Adams",
+	    "age": 90,
+	    "first_name": "John"
+	  },
+	  {
+	    "last_name": "Ford",
+	    "age": 83,
+	    "first_name": "Henry"
+	  }
+	]
+	
+
+YAML! 
++++++
+::
+
+	>>> print data.yaml
+	- {age: 90, first_name: John, last_name: Adams}
+	- {age: 83, first_name: Henry, last_name: Ford}
+	
+CSV... 
+++++++
+::
+
+	>>> print data.csv
+	first_name,last_name,age 
+	John,Adams,90 
+	Henry,Ford,83 
+	
+EXCEL! 
+++++++
+::
+
+	>>> open('people.xls', 'wb').write(data.xls)
+
+It's that easy.
+
+Imports!
+--------
+
+JSON
+++++
+
+::
+
+	>>> data.json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]'
+	>>> print data[0]
+	('John', 'Adams', 90)
+
+
+YAML
+++++
+::
+
+	>>> data.yaml = '- {age: 90, first_name: John, last_name: Adams}'
+	>>> print data[0]
+	('John', 'Adams', 90)
+
+CSV
++++
+::
+
+	>>> data.yaml = 'age, first_name, last_name\n90, John, Adams'
+	>>> print data[0]
+	('John', 'Adams', 90)
+	
+	>>> print data.yaml
+	- {age: 90, first_name: John, last_name: Adams}
+	
+
+
+Installation
+------------
+
+To install tablib, simply: ::
+
+	$ pip install tablib
+	
+Or, if you absolutely must: ::
+
+	$ easy_install tablib
+    
+
+Contribute
+----------
+
+If you'd like to contribute, simply fork `the repository`_, commit your changes to the **develop** branch (or branch off of it), and send a pull request. Make sure you add yourself to AUTHORS_.
+
+
+Roadmap
+-------
+- Release CLI Interface
+- Auto-detect import format
+- Add possible other exports (SQL?)
+- Ability to assign types to rows (set, regex=, &c.)
+
+.. _`the repository`: http://github.com/kennethreitz/tablib
+.. _AUTHORS: http://github.com/kennethreitz/tablib/blob/master/AUTHORS
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+
+from distutils.core import setup
+
+
+def publish():
+	"""Publish to PyPi"""
+	os.system("python setup.py sdist upload")
+
+if sys.argv[-1] == "publish":
+	publish()
+	sys.exit()
+
+setup(
+	name='tablib',
+	version='0.8.1',
+	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://github.com/kennethreitz/tablib',
+	packages=['tablib', 'tablib.formats'],
+	install_requires=['xlwt', 'simplejson', 'PyYAML'],
+	license='MIT',
+	classifiers=(
+		'Development Status :: 4 - Beta',
+		'License :: OSI Approved :: MIT License',
+		'Programming Language :: Python',
+        # 'Programming Language :: Python :: 2.5',
+        'Programming Language :: Python :: 2.6',
+		'Programming Language :: Python :: 2.7',
+	),
+    # entry_points={
+    #   'console_scripts': [
+    #       'tabbed = tablib.cli:start',
+    #   ],
+    # }
+)

tablib/__init__.py

+""" Tablib.
+"""
+
+from tablib.core import (
+	Databook, Dataset, InvalidDatasetType,
+	InvalidDimensions, UnsupportedFormat
+)
+
+# -*- coding: utf-8 -*-
+
+""" Tablib - Core Library.
+"""
+
+from tablib.formats import FORMATS as formats
+
+
+__title__ = 'tablib'
+__version__ = '0.8.1'
+__build__ = 0x000801
+__author__ = 'Kenneth Reitz'
+__license__ = 'MIT'
+__copyright__ = 'Copyright 2010 Kenneth Reitz'
+
+
+class Dataset(object):
+	"""Epic Tabular-Dataset object. """
+
+	def __init__(self, *args, **kwargs):
+		self._data = list(args)
+		self.__headers = None
+
+		try:
+			self.headers = kwargs['headers']
+		except KeyError:
+			self.headers = None
+
+		try:
+			self.title = kwargs['title']
+		except KeyError:
+			self.title = None
+
+		self._register_formats()
+
+	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:
+			return self._data[key]
+
+
+	def __setitem__(self, key, value):
+		self._validate(value)
+		self._data[key] = tuple(value)
+
+
+	def __delitem__(self, key):
+		del self._data[key]
+
+
+	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:
+			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
+
+
+	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 self.headers:
+				is_valid = (len(col) - 1) == self.height
+			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
+
+
+	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]
+
+		return data
+
+	
+	@property
+	def height(self):
+		"""Returns the height of the Dataset."""
+		return len(self._data)
+
+
+	@property
+	def width(self):
+		"""Returns the width of the Dataset."""
+		try:
+			return len(self._data[0])
+		except IndexError:
+			try:
+				return len(self.headers)
+			except TypeError:
+				return 0
+
+
+	@property
+	def headers(self):
+		"""Headers property."""
+		return self.__headers
+
+
+	@headers.setter
+	def headers(self, collection):
+		"""Validating headers setter."""
+		self._validate(collection)
+		if collection:
+			try:
+				self.__headers = list(collection)
+			except TypeError:
+				raise TypeError
+		else:
+			self.__headers = None
+
+
+	@property
+	def dict(self):
+		"""Returns python dict of Dataset."""
+		return self._package()
+
+	
+	@dict.setter
+	def dict(self, pickle):
+		"""Returns python dict of Dataset."""
+		if not len(pickle):
+			return
+		if isinstance(pickle[0], list):
+			for row in pickle:
+				self.append(row)
+		elif isinstance(pickle[0], dict):
+			self.headers = pickle[0].keys()
+			for row in pickle:
+				self.append(row.values())
+		else:
+			raise UnsupportedFormat
+
+
+	def append(self, row=None, col=None):
+		"""Adds a row to the end of Dataset"""
+		if row:
+			self._validate(row)
+			self._data.append(tuple(row))
+		elif col:
+			self._validate(col=col)
+
+			if self.headers:
+				# pop the first item off, add to headers
+				self.headers.append(col[0])
+				col = col[1:]
+		
+			if self.height and self.width:
+
+				for i, row in enumerate(self._data):
+					_row = list(row)
+					_row.append(col[i])
+					self._data[i] = tuple(_row)
+			else:
+				self._data = [tuple([row]) for row in col]
+
+
+	def insert(self, i, row=None, col=None):
+		"""Inserts a row at given position in Dataset"""
+		if row:
+			self._validate(row)
+			self._data.insert(i, tuple(row))
+		elif col:
+			pass
+			
+	
+	def wipe(self):
+		"""Erases all data from Dataset."""
+		self._data = list()
+		self.__headers = None
+
+
+class Databook(object):
+	"""A book of Dataset objects.
+	   Currently, this exists only for XLS workbook support.
+	"""
+
+	def __init__(self, sets=[]):
+		self._datasets = sets
+		self._register_formats()
+
+
+	def __repr__(self):
+		try:
+			return '<%s databook>' % (self.title.lower())
+		except AttributeError:
+			return '<databook object>'
+
+	def wipe(self):
+		"""Wipe book clean."""
+		self._datasets = []
+		
+	@classmethod
+	def _register_formats(cls):
+		"""Adds format properties."""
+		for fmt in formats:
+			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
+
+
+	def add_sheet(self, dataset):
+		"""Adds given dataset."""
+		if type(dataset) is Dataset:
+			self._datasets.append(dataset)
+		else:
+			raise InvalidDatasetType
+
+
+	def _package(self):
+		"""Packages 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 Datasets within DataBook."""
+		return len(self._datasets)
+
+
+
+class InvalidDatasetType(Exception):
+	"Only Datasets can be added to a DataBook"
+
+
+class InvalidDimensions(Exception):
+	"Invalid size"
+
+	
+class UnsupportedFormat(NotImplementedError):
+	"Format is not supported"

tablib/formats/__init__.py

+# -*- coding: utf-8 -*-
+
+""" Tablib - formats
+"""
+
+import _csv as csv
+import _json as json
+import _xls as xls
+import _yaml as yaml
+
+FORMATS = (csv, json, xls, yaml)

tablib/formats/_csv.py

+# -*- coding: utf-8 -*-
+
+""" Tablib - CSV Support.
+"""
+
+import cStringIO
+import csv
+import os
+
+import simplejson as json
+
+import tablib
+
+
+title = 'csv'
+extentions = ('csv',)
+
+
+
+def export_set(dataset):
+	"""Returns CSV representation of Dataset."""
+	stream = cStringIO.StringIO()
+	_csv = csv.writer(stream)
+
+	for row in dataset._package(dicts=False):
+		_csv.writerow(row)
+
+	return stream.getvalue()
+
+
+def import_set(dset, in_stream, headers=True):
+	"""Returns dataset from CSV stream."""
+
+	dset.wipe()
+
+	rows = csv.reader(in_stream.split())
+	for i, row in enumerate(rows):
+
+		if (i == 0) and (headers):
+			dset.headers = row
+		else:
+			dset.append(row)

tablib/formats/_json.py

+# -*- coding: utf-8 -*-
+
+""" Tablib - JSON Support
+"""
+
+import simplejson as json
+import tablib.core
+
+title = 'json'
+extentions = ('json', 'jsn')
+
+
+def export_set(dataset):
+	"""Returns JSON representation of Dataset."""
+	return json.dumps(dataset.dict)
+
+
+def export_book(databook):
+	"""Returns JSON representation of Databook."""
+	return json.dumps(databook._package())
+	
+
+def import_set(dset, in_stream):
+	"""Returns dataset from JSON stream."""
+	
+	dset.wipe()
+	dset.dict = json.loads(in_stream)
+
+
+def import_book(dbook, in_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)

tablib/formats/_xls.py

+# -*- coding: utf-8 -*-
+
+""" Tablib - XLS Support.
+"""
+
+import xlwt
+import cStringIO
+
+
+title = 'xls'
+extentions = ('xls',)
+
+
+def export_set(dataset):
+	"""Returns XLS representation of Dataset."""
+
+	wb = xlwt.Workbook(encoding='utf8')
+	ws = wb.add_sheet(dataset.title if dataset.title else 'Tabbed Dataset')
+
+	for i, row in enumerate(dataset._package(dicts=False)):
+		for j, col in enumerate(row):
+			ws.write(i, j, col)
+
+	stream = cStringIO.StringIO()
+	wb.save(stream)
+	return stream.getvalue()
+
+
+def export_book(databook):
+	"""Returns XLS representation of DataBook."""
+
+	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 row in self._package(dicts=False):
+		for i, row in enumerate(dset._package(dicts=False)):
+			for j, col in enumerate(row):
+				ws.write(i, j, col)
+
+
+	stream = cStringIO.StringIO()
+	wb.save(stream)
+	return stream.getvalue()

tablib/formats/_yaml.py

+# -*- coding: utf-8 -*-
+
+""" Tablib - YAML Support.
+"""
+
+import yaml
+import tablib
+
+
+
+title = 'yaml'
+extentions = ('yaml', 'yml')
+
+
+
+def export_set(dataset):
+	"""Returns YAML representation of Dataset."""
+	return yaml.dump(dataset.dict)
+
+
+def export_book(databook):
+	"""Returns YAML representation of Databook."""
+	return yaml.dump(databook._package())
+
+
+def import_set(dset, in_stream):
+	"""Returns dataset from YAML stream."""
+
+	dset.wipe()
+	dset.dict = yaml.load(in_stream)
+
+
+def import_book(dbook, in_stream):
+	"""Returns databook from YAML stream."""
+
+	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)

tablib/helpers.py

+# -*- coding: utf-8 -*-
+
+""" Tablib - General Helpers.
+"""
+
+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)
+
+	def dictionary(self):
+		"""Returns dictionary representation of object."""
+		return self.__dict__
+
+	def items(self):
+		"""Returns items within object."""
+		return self.__dict__.items()
+
+	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
+