mirror of
https://github.com/kennethreitz/tablib.git
synced 2026-06-05 23:10:17 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 520a1986d7 | |||
| 1ea793112c | |||
| 41a7a5d329 | |||
| c4edaa2ca8 | |||
| c612bb3dae | |||
| bfe70066b8 | |||
| fbfbe01b70 | |||
| 06a394ea5c | |||
| 9427decdb0 | |||
| fb59035f8d | |||
| 187d12cffc | |||
| eaa4de7793 | |||
| d479c5735a | |||
| 96668bb393 | |||
| b369baba40 | |||
| 25f846a78a | |||
| 22fe18239f | |||
| 149bafa97b | |||
| 9f7fec2379 | |||
| 762ac39e27 | |||
| 2a7aa959b3 | |||
| d85523b6a6 | |||
| 25a5bcea0c | |||
| f58d4b67dc | |||
| a310ab7a09 | |||
| 7f2f925ddb | |||
| 3fc898e222 | |||
| de46f45e2e | |||
| 392eaac299 | |||
| 3a9c3944cf | |||
| 8c402da729 | |||
| 8feb6e8ddf | |||
| 9072b6ddae |
@@ -10,4 +10,5 @@ Development Lead
|
|||||||
Patches and Suggestions
|
Patches and Suggestions
|
||||||
```````````````````````
|
```````````````````````
|
||||||
|
|
||||||
- Luke Lee
|
- Luke Lee
|
||||||
|
- Josh Ourisman
|
||||||
+8
-1
@@ -1,7 +1,14 @@
|
|||||||
History
|
History
|
||||||
=======
|
=======
|
||||||
|
|
||||||
0.8.2 (2010-09-28)
|
0.8.3 (2010-10-04)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Ability to append new column passing a callable
|
||||||
|
as the value that will be applied to every row.
|
||||||
|
|
||||||
|
|
||||||
|
0.8.2 (2010-10-04)
|
||||||
------------------
|
------------------
|
||||||
* Added alignment wrapping to written cells.
|
* Added alignment wrapping to written cells.
|
||||||
* Added separator support to XLS.
|
* Added separator support to XLS.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ if sys.argv[-1] == "publish":
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='tablib',
|
name='tablib',
|
||||||
version='0.8.2',
|
version='0.8.3',
|
||||||
description='Format agnostic tabular data library (XLS, JSON, YAML, CSV)',
|
description='Format agnostic tabular data library (XLS, JSON, YAML, CSV)',
|
||||||
long_description=open('README.rst').read() + '\n\n' +
|
long_description=open('README.rst').read() + '\n\n' +
|
||||||
open('HISTORY.rst').read(),
|
open('HISTORY.rst').read(),
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Tabbed -- CLI for Tablib
|
||||||
|
Copyright (c) 2010 Kenneth Reitz. MIT License.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import tablib.cli
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
tablib.cli.start()
|
||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from tablib.core import (
|
from tablib.core import (
|
||||||
Databook, Dataset, InvalidDatasetType,
|
Databook, Dataset, detect, import_set,
|
||||||
InvalidDimensions, UnsupportedFormat
|
InvalidDatasetType, InvalidDimensions, UnsupportedFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
""" Tabbed CLI Inteface Application
|
||||||
|
"""
|
||||||
|
|
||||||
|
import io
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import argue
|
||||||
|
|
||||||
|
import tablib
|
||||||
|
from helpers import Struct, piped
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FORMATS = [fmt.title for fmt in tablib.formats.FORMATS]
|
||||||
|
|
||||||
|
opts = []
|
||||||
|
|
||||||
|
opts.append(('v', 'version', False, 'Report tabbed version'))
|
||||||
|
|
||||||
|
for format in FORMATS:
|
||||||
|
opts.append(('', format, False, 'Output to %s' % (format.upper())))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@argue.command(options=opts, usage='[FILE] [--FORMAT | FILE]')
|
||||||
|
def start(in_file=None, out_file=None, **opts):
|
||||||
|
"""Covertly convert dataset formats"""
|
||||||
|
|
||||||
|
opts = Struct(**opts)
|
||||||
|
|
||||||
|
if opts.version:
|
||||||
|
print('Tabbed, Ver. %s' % tablib.core.__version__)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
stdin = piped()
|
||||||
|
|
||||||
|
if stdin:
|
||||||
|
data = tablib.import_set(stdin)
|
||||||
|
|
||||||
|
elif in_file:
|
||||||
|
|
||||||
|
try:
|
||||||
|
in_stream =- io.open(in_file, 'r').read()
|
||||||
|
except Exception, e:
|
||||||
|
print(' %s cannot be read.' % in_file)
|
||||||
|
sys.exit(65)
|
||||||
|
|
||||||
|
try:
|
||||||
|
tablib.import_set(in_stream)
|
||||||
|
except Exception, e:
|
||||||
|
raise e
|
||||||
|
print('Import format not supported.')
|
||||||
|
sys.exit(65)
|
||||||
|
else:
|
||||||
|
print('Please provide input.')
|
||||||
|
sys.exit(65)
|
||||||
|
|
||||||
|
|
||||||
|
_formats_sum = sum(opts[f] for f in FORMATS)
|
||||||
|
|
||||||
|
# Multiple output formats given
|
||||||
|
if _formats_sum > 1:
|
||||||
|
print('Please specify a single output format.')
|
||||||
|
sys.exit(64)
|
||||||
|
|
||||||
|
# No output formats given
|
||||||
|
elif _formats_sum < 1:
|
||||||
|
print('Please specify an output format.')
|
||||||
|
sys.exit(64)
|
||||||
|
|
||||||
|
|
||||||
|
# fetch options.formats list
|
||||||
|
# if sum(()) > 1
|
||||||
|
# log only one data format please
|
||||||
|
# if sum of formats == 0, specity format
|
||||||
|
|
||||||
|
# look for filename
|
||||||
|
|
||||||
|
# print opts.__dict__
|
||||||
|
# print in_file
|
||||||
|
# print out_file
|
||||||
+13
-4
@@ -7,8 +7,8 @@ from tablib.formats import FORMATS as formats
|
|||||||
|
|
||||||
|
|
||||||
__title__ = 'tablib'
|
__title__ = 'tablib'
|
||||||
__version__ = '0.8.1'
|
__version__ = '0.8.3'
|
||||||
__build__ = 0x000801
|
__build__ = 0x000803
|
||||||
__author__ = 'Kenneth Reitz'
|
__author__ = 'Kenneth Reitz'
|
||||||
__license__ = 'MIT'
|
__license__ = 'MIT'
|
||||||
__copyright__ = 'Copyright 2010 Kenneth Reitz'
|
__copyright__ = 'Copyright 2010 Kenneth Reitz'
|
||||||
@@ -177,10 +177,19 @@ class Dataset(object):
|
|||||||
|
|
||||||
def append(self, row=None, col=None):
|
def append(self, row=None, col=None):
|
||||||
"""Adds a row to the end of Dataset"""
|
"""Adds a row to the end of Dataset"""
|
||||||
if row:
|
if row is not None:
|
||||||
self._validate(row)
|
self._validate(row)
|
||||||
self._data.append(tuple(row))
|
self._data.append(tuple(row))
|
||||||
elif col:
|
elif col is not None:
|
||||||
|
col = list(col)
|
||||||
|
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)
|
||||||
|
|
||||||
self._validate(col=col)
|
self._validate(col=col)
|
||||||
|
|
||||||
if self.headers:
|
if self.headers:
|
||||||
|
|||||||
@@ -8,4 +8,4 @@ import _json as json
|
|||||||
import _xls as xls
|
import _xls as xls
|
||||||
import _yaml as yaml
|
import _yaml as yaml
|
||||||
|
|
||||||
FORMATS = (csv, json, xls, yaml)
|
FORMATS = (json, xls, yaml, csv)
|
||||||
|
|||||||
@@ -40,3 +40,12 @@ def import_set(dset, in_stream, headers=True):
|
|||||||
dset.headers = row
|
dset.headers = row
|
||||||
else:
|
else:
|
||||||
dset.append(row)
|
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
|
||||||
@@ -36,3 +36,12 @@ def import_book(dbook, in_stream):
|
|||||||
data.title = sheet['title']
|
data.title = sheet['title']
|
||||||
data.dict = sheet['data']
|
data.dict = sheet['data']
|
||||||
dbook.add_sheet(data)
|
dbook.add_sheet(data)
|
||||||
|
|
||||||
|
|
||||||
|
def detect(stream):
|
||||||
|
"""Returns True if given stream is valid JSON."""
|
||||||
|
try:
|
||||||
|
json.loads(stream)
|
||||||
|
return True
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
return False
|
||||||
+12
-1
@@ -39,4 +39,15 @@ def import_book(dbook, in_stream):
|
|||||||
data = tablib.core.Dataset()
|
data = tablib.core.Dataset()
|
||||||
data.title = sheet['title']
|
data.title = sheet['title']
|
||||||
data.dict = sheet['data']
|
data.dict = sheet['data']
|
||||||
dbook.add_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
|
||||||
@@ -102,6 +102,13 @@ class TablibTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertRaises(tablib.InvalidDimensions, data.append, col=new_col)
|
self.assertRaises(tablib.InvalidDimensions, data.append, col=new_col)
|
||||||
|
|
||||||
|
def test_add_callable_column(self):
|
||||||
|
"""Verify adding column with values specified as callable."""
|
||||||
|
new_col = ['first_again', lambda x: x[0]]
|
||||||
|
self.founders.append(col=new_col)
|
||||||
|
|
||||||
|
self.assertTrue(map(lambda x: x[0] == x[-1], self.founders))
|
||||||
|
|
||||||
|
|
||||||
def test_header_slicing(self):
|
def test_header_slicing(self):
|
||||||
"""Verify slicing by headers."""
|
"""Verify slicing by headers."""
|
||||||
@@ -261,6 +268,58 @@ class TablibTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(_csv, data.csv)
|
self.assertEqual(_csv, data.csv)
|
||||||
|
|
||||||
|
def test_csv_format_detect(self):
|
||||||
|
"""Test CSV format detection."""
|
||||||
|
|
||||||
|
_csv = (
|
||||||
|
'1,2,3\n'
|
||||||
|
'4,5,6\n'
|
||||||
|
'7,8,9\n'
|
||||||
|
)
|
||||||
|
_bunk = (
|
||||||
|
'¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(tablib.formats.csv.detect(_csv))
|
||||||
|
self.assertFalse(tablib.formats.csv.detect(_bunk))
|
||||||
|
|
||||||
|
def test_json_format_detect(self):
|
||||||
|
"""Test JSON format detection."""
|
||||||
|
|
||||||
|
_json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]'
|
||||||
|
_bunk = (
|
||||||
|
'¡¡¡¡¡¡¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(tablib.formats.json.detect(_json))
|
||||||
|
self.assertFalse(tablib.formats.json.detect(_bunk))
|
||||||
|
|
||||||
|
|
||||||
|
def test_yaml_format_detect(self):
|
||||||
|
"""Test YAML format detection."""
|
||||||
|
|
||||||
|
_yaml = '- {age: 90, first_name: John, last_name: Adams}'
|
||||||
|
_bunk = (
|
||||||
|
'¡¡¡¡¡¡---///\n\n\n¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(tablib.formats.yaml.detect(_yaml))
|
||||||
|
self.assertFalse(tablib.formats.yaml.detect(_bunk))
|
||||||
|
|
||||||
|
|
||||||
|
def test_auto_format_detect(self):
|
||||||
|
"""Test auto format detection."""
|
||||||
|
|
||||||
|
_yaml = '- {age: 90, first_name: John, last_name: Adams}'
|
||||||
|
_json = '[{"last_name": "Adams","age": 90,"first_name": "John"}]'
|
||||||
|
_csv = '1,2,3\n4,5,6\n7,8,9\n'
|
||||||
|
_bunk = '¡¡¡¡¡¡---///\n\n\n¡¡£™∞¢£§∞§¶•¶ª∞¶•ªº••ª–º§•†•§º¶•†¥ª–º•§ƒø¥¨©πƒø†ˆ¥ç©¨√øˆ¥≈†ƒ¥ç©ø¨çˆ¥ƒçø¶'
|
||||||
|
|
||||||
|
self.assertEqual(tablib.detect(_yaml)[0], tablib.formats.yaml)
|
||||||
|
self.assertEqual(tablib.detect(_csv)[0], tablib.formats.csv)
|
||||||
|
self.assertEqual(tablib.detect(_json)[0], tablib.formats.json)
|
||||||
|
self.assertEqual(tablib.detect(_bunk)[0], None)
|
||||||
|
|
||||||
|
|
||||||
def test_wipe(self):
|
def test_wipe(self):
|
||||||
"""Purge a dataset."""
|
"""Purge a dataset."""
|
||||||
|
|||||||
Reference in New Issue
Block a user