From c219972ccdf70c7ba0d4762e222b5404f3794b2e Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Fri, 18 Feb 2011 04:28:50 -0500 Subject: [PATCH 01/16] added pypy location to tox config --- tox.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 9cef9b3..ba10930 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,8 @@ envlist = py24,py25,py26,py27 [testenv] commands=py.test --junitxml=junit-{envname}.xml deps = - nose simplejson - pytest \ No newline at end of file + pytest + +[testenv:pypy] +basepython=/usr/bin/pypy-c From bccf0d1ba1adac259e0ffe5687455f6aadade7fd Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Fri, 18 Feb 2011 04:37:00 -0500 Subject: [PATCH 02/16] no more test suite. --- test_suite.sh | 5 ----- 1 file changed, 5 deletions(-) delete mode 100755 test_suite.sh diff --git a/test_suite.sh b/test_suite.sh deleted file mode 100755 index 5a1e7be..0000000 --- a/test_suite.sh +++ /dev/null @@ -1,5 +0,0 @@ -rm -fr nosetests.xml -tox -# coverage xml -rm -fr pylint.txt -# pylint -d W0312 -d W0212 -d E1101 -d E0202 -d W0102 -d E0102 -f parseable ./tablib > pylint.txt || true \ No newline at end of file From c2331f7a23ff0531d96baeb79e8769e5531c986c Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 02:11:59 -0500 Subject: [PATCH 03/16] Updated pythons list. --- docs/intro.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/intro.rst b/docs/intro.rst index c2d75b2..9a00a8e 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -44,8 +44,10 @@ Pythons Supported At this time, the following Python platforms are officially supported: -* Python 2.6 -* Python 2.7 +* cPython 2.5 +* cPython 2.6 +* cPython 2.7 +* PyPy-c 1.4 Support for other Pythons will be rolled out soon. From 1cf9bd14b451fd56c06416fde71ee5f8bc0beef2 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 02:12:41 -0500 Subject: [PATCH 04/16] ci.kennethreitz.com now --- docs/development.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/development.rst b/docs/development.rst index 77af330..6255d5e 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -87,7 +87,7 @@ Adding New Formats Tablib welcomes new format additions! Format suggestions include: -* Tab Seperated Values +* Tab Separated Values * MySQL Dump * HTML Table @@ -178,7 +178,7 @@ Every commit made to the **develop** branch is automatically tested and inspecte Anyone may view the build status and history at any time. - http://git.kennethreitz.com/ci/ + http://ci.kennethreitz.com/ If you are trustworthy and plan to contribute to tablib on a regular basis, please contact `Kenneth Reitz`_ to get an account on the Hudson Server. From 23c183114433f69415431c498d799b78b7f688f0 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 02:15:00 -0500 Subject: [PATCH 05/16] Added HACKING file. --- HACKING | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 HACKING diff --git a/HACKING b/HACKING new file mode 100644 index 0000000..018f9b7 --- /dev/null +++ b/HACKING @@ -0,0 +1,14 @@ +Where possible, please follow PEP8 with regard to coding style. Sometimes the line +length restriction is too hard to follow, so don't bend over backwards there. + +Triple-quotes should always be """, single quotes are ' unless using " +would result in less escaping within the string. + +All modules, functions, and methods should be well documented reStructuredText for +Sphinx AutoDoc. + +All functionality should be available in pure Python. Optional C (via Cython) +implementations may be written for performance reasons, but should never +replace the Python implementation. + +Lastly, don't take yourself too seriously :) \ No newline at end of file From 9ab277a4682546b64363ba308ef551fde3c4051d Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 02:32:20 -0500 Subject: [PATCH 06/16] docs: Python 2.5 is supported now. --- docs/install.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/install.rst b/docs/install.rst index 9b9a519..b6c3f31 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -55,7 +55,7 @@ However, if performance is important to you (and it should be), you can install $ pip install PyYAML -If you're using Python 2.5 (currently unsupported), you should also install the **simplejson** module. If you're using Python 2.6+, the built-in **json** module is already optimized and in use. :: +If you're using Python 2.5, you should also install the **simplejson** module (pip will do this for you). If you're using Python 2.6+, the built-in **json** module is already optimized and in use. :: $ pip install simplejson From d11c09febefbe6150f4e5b168d46970b232ee452 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 02:37:29 -0500 Subject: [PATCH 07/16] Added License text. --- docs/intro.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/intro.rst b/docs/intro.rst index 9a00a8e..bc4256a 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -36,6 +36,31 @@ Tablib is released under terms of `The MIT License`_. .. _`The MIT License`: http://www.opensource.org/licenses/mit-license.php +.. _license: + +Tablib License +-------------- + +Copyright (c) 2011 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. + .. _pythonsupport: From 76f09cd3b35f8cda1a8f081d81fd0f83d19fd2e0 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 02:37:53 -0500 Subject: [PATCH 08/16] Added release number to documentation. --- docs/index.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 4726d7b..77ce7cf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,8 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Tablib: Pythonic Tabular Data -============================= +Tablib: Pythonic Tabular Datasets +================================= + +Release |version|. .. Contents: .. From 22cddbcd6354dc87af9b2797849329a20500966b Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 02:55:24 -0500 Subject: [PATCH 09/16] well then --- hi | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 hi diff --git a/hi b/hi new file mode 100644 index 0000000..e69de29 From e1734f2315bdb87f894911b1e031de39e7297bb6 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 21 Feb 2011 14:07:42 -0500 Subject: [PATCH 10/16] added __docformat__ --- hi | 0 tablib/core.py | 1 + 2 files changed, 1 insertion(+) delete mode 100644 hi diff --git a/hi b/hi deleted file mode 100644 index e69de29..0000000 diff --git a/tablib/core.py b/tablib/core.py index dfbcb6a..548de55 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -26,6 +26,7 @@ __build__ = 0x000904 __author__ = 'Kenneth Reitz' __license__ = 'MIT' __copyright__ = 'Copyright 2011 Kenneth Reitz' +__docformat__ = 'restructuredtext' class Row(object): From 2f331cee8ece577b54644efb7e2219ed61d75380 Mon Sep 17 00:00:00 2001 From: Igor Davydenko Date: Tue, 1 Mar 2011 19:36:19 +0200 Subject: [PATCH 11/16] Fix #24, add support of spaces in CSV files. --- tablib/formats/_csv.py | 2 +- test_tablib.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tablib/formats/_csv.py b/tablib/formats/_csv.py index 2c74a1c..b71755b 100644 --- a/tablib/formats/_csv.py +++ b/tablib/formats/_csv.py @@ -31,7 +31,7 @@ def import_set(dset, in_stream, headers=True): dset.wipe() - rows = csv.reader(in_stream.split()) + rows = csv.reader(in_stream.splitlines()) for i, row in enumerate(rows): if (i == 0) and (headers): diff --git a/test_tablib.py b/test_tablib.py index e4a4d11..4079809 100755 --- a/test_tablib.py +++ b/test_tablib.py @@ -295,6 +295,19 @@ class TablibTestCase(unittest.TestCase): self.assertEqual(_csv, data.csv) + def test_csv_import_set_with_spaces(self): + """Generate and import CSV set serialization when row values have + spaces.""" + data.append(('Bill Gates', 'Microsoft')) + data.append(('Steve Jobs', 'Apple')) + data.headers = ('Name', 'Company') + + _csv = data.csv + + data.csv = _csv + + self.assertEqual(_csv, data.csv) + def test_tsv_import_set(self): """Generate and import TSV set serialization.""" data.append(self.john) From c8493ff047ddfbfa9d0231cd395d3645faedce80 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 22 Mar 2011 17:12:02 -0400 Subject: [PATCH 12/16] fixes issue #38: python 2.5 support --- tablib/helpers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tablib/helpers.py b/tablib/helpers.py index 718d159..f8a5351 100644 --- a/tablib/helpers.py +++ b/tablib/helpers.py @@ -2,6 +2,7 @@ """ Tablib - General Helpers. """ +from __future__ import with_statement import sys From e8ba7654263c1f3cddfe63dea3d282a739c9778f Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 23 Mar 2011 00:03:33 -0400 Subject: [PATCH 13/16] tablib.helpers is not longer needed :cake: --- tablib/helpers.py | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 tablib/helpers.py diff --git a/tablib/helpers.py b/tablib/helpers.py deleted file mode 100644 index f8a5351..0000000 --- a/tablib/helpers.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- - -""" Tablib - General Helpers. -""" -from __future__ import with_statement - -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 - From 8b5b29fc90ca4e222b2f2e9c0ceb6038b53fb0d6 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 23 Mar 2011 00:20:39 -0400 Subject: [PATCH 14/16] added Dataset.add_formatter --- tablib/core.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tablib/core.py b/tablib/core.py index 548de55..0915ee3 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -137,6 +137,9 @@ class Dataset(object): # ('title', index) tuples self._separators = [] + + # (column, callback) tuples + self._formatters = [] try: self.headers = kwargs['headers'] @@ -386,6 +389,7 @@ class Dataset(object): """ pass + @property def tsv(): """A TSV representation of the :class:`Dataset` object. The top row will contain @@ -470,6 +474,26 @@ class Dataset(object): self.insert_separator(index, text) + def add_formatter(col, handler): + """Adds a :ref:`formatter` to the :class:`Dataset`. + + .. 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. + """ + + if isinstance(col, basestring): + if col in self.headers: + col = self.headers.index(key) # get 'key' index from each data + else: + raise KeyError + + self._formatters.append((col, handler)) + + return True + + 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. @@ -659,12 +683,14 @@ class Dataset(object): return _dset + 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. """ From 3803a7a21b68633b0e54c6c01824647973ffa95d Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 23 Mar 2011 00:32:56 -0400 Subject: [PATCH 15/16] formatter execution in place upon export --- tablib/core.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tablib/core.py b/tablib/core.py index 0915ee3..6c17bc3 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -240,13 +240,26 @@ class Dataset(object): def _package(self, dicts=True): """Packages Dataset into lists of dictionaries for transmission.""" + _data = list(self._data) + + # Execute formatters + if self._formatters: + for row_i, row in enumerate(_data): + for col, callback in self._formatters: + if col is None: + for j, c in enumerate(row): + _data[row_i][j] = callback(c) + else: + _data[row_i][col] = callback(row[col]) + + if self.headers: if dicts: - data = [OrderedDict(zip(self.headers, data_row)) for data_row in self ._data] + data = [OrderedDict(zip(self.headers, data_row)) for data_row in _data] else: - data = [list(self.headers)] + list(self._data) + data = [list(self.headers)] + list(_data) else: - data = [list(row) for row in self._data] + data = [list(row) for row in _data] return data @@ -474,7 +487,7 @@ class Dataset(object): self.insert_separator(index, text) - def add_formatter(col, handler): + def add_formatter(self, col, handler): """Adds a :ref:`formatter` to the :class:`Dataset`. .. versionadded:: 0.9.5 From 65c73dfc42ec2012dcc5c91dff43de25936095b1 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Wed, 23 Mar 2011 00:38:45 -0400 Subject: [PATCH 16/16] do some internal validation for adding formatters --- tablib/core.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tablib/core.py b/tablib/core.py index 6c17bc3..c4efce3 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -246,12 +246,15 @@ class Dataset(object): if self._formatters: for row_i, row in enumerate(_data): for col, callback in self._formatters: - if col is None: - for j, c in enumerate(row): - _data[row_i][j] = callback(c) - else: - _data[row_i][col] = callback(row[col]) - + try: + if col is None: + for j, c in enumerate(row): + _data[row_i][j] = callback(c) + else: + _data[row_i][col] = callback(row[col]) + except IndexError: + raise InvalidDatasetIndex + if self.headers: if dicts: @@ -501,8 +504,11 @@ class Dataset(object): col = self.headers.index(key) # get 'key' index from each data else: raise KeyError - - self._formatters.append((col, handler)) + + if not col > self.width: + self._formatters.append((col, handler)) + else: + raise InvalidDatasetIndex return True @@ -798,6 +804,9 @@ class InvalidDatasetType(Exception): class InvalidDimensions(Exception): "Invalid size" + +class InvalidDatasetIndex(Exception): + "Outside of Dataset size" class HeadersNeeded(Exception): "Header parameter must be given when appending a column in this Dataset."