diff --git a/tablib/core.py b/tablib/core.py index 69a684b..8ef6312 100644 --- a/tablib/core.py +++ b/tablib/core.py @@ -13,6 +13,7 @@ from copy import copy from operator import itemgetter from tablib import formats +import collections try: from collections import OrderedDict @@ -63,7 +64,7 @@ class Row(object): return {slot: [getattr(self, slot) for slot in self.__slots__]} def __setstate__(self, state): - for (k, v) in state.items(): setattr(self, k, v) + for (k, v) in list(state.items()): setattr(self, k, v) def append(self, value): self._row.append(value) @@ -89,7 +90,7 @@ class Row(object): if tag == None: return False - elif isinstance(tag, basestring): + elif isinstance(tag, str): return (tag in self.tags) else: return bool(len(set(tag) & set(self.tags))) @@ -159,7 +160,7 @@ class Dataset(object): def __getitem__(self, key): - if isinstance(key, basestring): + if isinstance(key, str): if key in self.headers: pos = self.headers.index(key) # get 'key' index from each data return [row[pos] for row in self._data] @@ -179,7 +180,7 @@ class Dataset(object): def __delitem__(self, key): - if isinstance(key, basestring): + if isinstance(key, str): if key in self.headers: @@ -258,7 +259,7 @@ class Dataset(object): if self.headers: if dicts: - data = [OrderedDict(zip(self.headers, data_row)) for data_row in _data] + data = [OrderedDict(list(zip(self.headers, data_row))) for data_row in _data] else: data = [list(self.headers)] + list(_data) else: @@ -277,8 +278,8 @@ class Dataset(object): else: header = [] - if len(col) == 1 and callable(col[0]): - col = map(col[0], self._data) + if len(col) == 1 and isinstance(col[0], collections.Callable): + col = list(map(col[0], self._data)) col = tuple(header + col) return col @@ -367,9 +368,9 @@ class Dataset(object): # if list of objects elif isinstance(pickle[0], dict): self.wipe() - self.headers = pickle[0].keys() + self.headers = list(pickle[0].keys()) for row in pickle: - self.append(Row(row.values())) + self.append(Row(list(row.values()))) else: raise UnsupportedFormat @@ -499,7 +500,7 @@ class Dataset(object): against each cell value. """ - if isinstance(col, basestring): + if isinstance(col, str): if col in self.headers: col = self.headers.index(col) # get 'key' index from each data else: @@ -548,8 +549,8 @@ class Dataset(object): col = list(col) # Callable Columns... - if len(col) == 1 and callable(col[0]): - col = map(col[0], self._data) + if len(col) == 1 and isinstance(col[0], collections.Callable): + col = list(map(col[0], self._data)) col = self._clean_col(col) self._validate(col=col) @@ -587,7 +588,7 @@ class Dataset(object): Returns a new :class:`Dataset` instance where columns have been sorted.""" - if isinstance(col, basestring): + if isinstance(col, str): if not self.headers: raise HeadersNeeded @@ -794,7 +795,7 @@ def import_set(stream): format.import_set(data, stream) return data - except AttributeError, e: + except AttributeError as e: return None diff --git a/tablib/formats/__init__.py b/tablib/formats/__init__.py index 147df31..305026d 100644 --- a/tablib/formats/__init__.py +++ b/tablib/formats/__init__.py @@ -3,11 +3,11 @@ """ Tablib - formats """ -import _csv as csv -import _json as json -import _xls as xls -import _yaml as yaml -import _tsv as tsv -import _html as html +from . import _csv as csv +from . import _json as json +from . import _xls as xls +from . import _yaml as yaml +from . import _tsv as tsv +from . import _html as html available = (json, xls, yaml, csv, tsv, html) diff --git a/tablib/formats/_csv.py b/tablib/formats/_csv.py index b71755b..8174501 100644 --- a/tablib/formats/_csv.py +++ b/tablib/formats/_csv.py @@ -3,7 +3,7 @@ """ Tablib - CSV Support. """ -import cStringIO +import io import csv import os @@ -17,7 +17,7 @@ extentions = ('csv',) def export_set(dataset): """Returns CSV representation of Dataset.""" - stream = cStringIO.StringIO() + stream = io.StringIO() _csv = csv.writer(stream) for row in dataset._package(dicts=False): diff --git a/tablib/formats/_html.py b/tablib/formats/_html.py index 13dc055..d3a7459 100644 --- a/tablib/formats/_html.py +++ b/tablib/formats/_html.py @@ -3,7 +3,7 @@ """ Tablib - HTML export support. """ -from StringIO import StringIO +from io import StringIO from tablib.packages import markup import tablib diff --git a/tablib/formats/_tsv.py b/tablib/formats/_tsv.py index 76a5f07..708c4b9 100644 --- a/tablib/formats/_tsv.py +++ b/tablib/formats/_tsv.py @@ -3,7 +3,7 @@ """ Tablib - TSV (Tab Separated Values) Support. """ -import cStringIO +import io import csv import os @@ -17,7 +17,7 @@ extentions = ('tsv',) def export_set(dataset): """Returns a TSV representation of Dataset.""" - stream = cStringIO.StringIO() + stream = io.StringIO() _tsv = csv.writer(stream, delimiter='\t') for row in dataset._package(dicts=False): diff --git a/tablib/formats/_xls.py b/tablib/formats/_xls.py index 717a6d5..7c3cb06 100644 --- a/tablib/formats/_xls.py +++ b/tablib/formats/_xls.py @@ -3,7 +3,7 @@ """ Tablib - XLS Support. """ -import cStringIO +import io try: import xlwt @@ -27,8 +27,8 @@ def export_set(dataset): dset_sheet(dataset, ws) - stream = cStringIO.StringIO() - wb.save(stream) + stream = io.StringIO() + wb.save(str(stream)) return stream.getvalue() @@ -43,7 +43,7 @@ def export_book(databook): dset_sheet(dset, ws) - stream = cStringIO.StringIO() + stream = io.StringIO() wb.save(stream) return stream.getvalue() diff --git a/tablib/packages/anyjson.py b/tablib/packages/anyjson.py index 6603751..a7d1a5f 100644 --- a/tablib/packages/anyjson.py +++ b/tablib/packages/anyjson.py @@ -53,7 +53,7 @@ class _JsonImplementation(object): """Incapsulates a JSON implementation""" def __init__(self, modspec): - modinfo = dict(zip(_fields, modspec)) + modinfo = dict(list(zip(_fields, modspec))) # No try block. We want importerror to end up at caller module = self._attempt_load(modinfo["modname"]) @@ -64,9 +64,9 @@ class _JsonImplementation(object): self._encode_error = modinfo["encerror"] self._decode_error = modinfo["decerror"] - if isinstance(modinfo["encerror"], basestring): + if isinstance(modinfo["encerror"], str): self._encode_error = getattr(module, modinfo["encerror"]) - if isinstance(modinfo["decerror"], basestring): + if isinstance(modinfo["decerror"], str): self._decode_error = getattr(module, modinfo["decerror"]) self.name = modinfo["modname"] @@ -82,7 +82,7 @@ class _JsonImplementation(object): TypeError if the object could not be serialized.""" try: return self._encode(data) - except self._encode_error, exc: + except self._encode_error as exc: raise TypeError(*exc.args) def deserialize(self, s): @@ -90,7 +90,7 @@ class _JsonImplementation(object): ValueError if the string vould not be parsed.""" try: return self._decode(s) - except self._decode_error, exc: + except self._decode_error as exc: raise ValueError(*exc.args) diff --git a/tablib/packages/markup.py b/tablib/packages/markup.py index 234f116..0e1c6a1 100644 --- a/tablib/packages/markup.py +++ b/tablib/packages/markup.py @@ -68,7 +68,7 @@ class element: """Append the actual tags to content.""" out = "<%s" % tag - for key, value in kwargs.iteritems( ): + for key, value in kwargs.items( ): 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? @@ -156,17 +156,17 @@ class page: if mode == 'strict_html' or mode == 'html': self.onetags = valid_onetags - self.onetags += map( string.lower, self.onetags ) + self.onetags += list(map( string.lower, self.onetags )) self.twotags = valid_twotags - self.twotags += map( string.lower, self.twotags ) + self.twotags += list(map( string.lower, self.twotags )) self.deptags = deprecated_onetags + deprecated_twotags - self.deptags += map( string.lower, self.deptags ) + self.deptags += list(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.onetags += list(map( string.lower, self.onetags )) self.twotags = valid_twotags + deprecated_twotags - self.twotags += map( string.lower, self.twotags ) + self.twotags += list(map( string.lower, self.twotags )) self.mode = mode elif mode == 'xml': if onetags and twotags: @@ -183,7 +183,7 @@ class page: def __getattr__( self, attr ): if attr.startswith("__") and attr.endswith("__"): - raise AttributeError, attr + raise AttributeError(attr) return element( attr, case=self.case, parent=self ) def __str__( self ): @@ -307,7 +307,7 @@ class page: """This convenience function is only useful for html. It adds css stylesheet(s) to the document via the element.""" - if isinstance( filelist, basestring ): + if isinstance( filelist, str ): self.link( href=filelist, rel='stylesheet', type='text/css', media='all' ) else: for file in filelist: @@ -319,20 +319,20 @@ class page: a dictionary of the form { 'name':'content' }.""" if isinstance( mydict, dict ): - for name, content in mydict.iteritems( ): + for name, content in mydict.items( ): self.meta( name=name, content=content ) else: - raise TypeError, "Metainfo should be called with a dictionary argument of name:content pairs." + raise TypeError("Metainfo should be called with a dictionary argument of name:content pairs.") def scripts( self, mydict ): """Only useful in html, mydict is dictionary of src:type pairs will be rendered as """ if isinstance( mydict, dict ): - for src, type in mydict.iteritems( ): + for src, type in mydict.items( ): self.script( '', src=src, type='text/%s' % type ) else: - raise TypeError, "Script should be given a dictionary of src:type pairs." + raise TypeError("Script should be given a dictionary of src:type pairs.") class _oneliner: @@ -345,7 +345,7 @@ class _oneliner: def __getattr__( self, attr ): if attr.startswith("__") and attr.endswith("__"): - raise AttributeError, attr + raise AttributeError(attr) return element( attr, case=self.case, parent=None ) oneliner = _oneliner( case='lower' ) @@ -359,14 +359,14 @@ def _argsdicts( args, mydict ): elif len( args ) == 1: args = _totuple( args[0] ) else: - raise Exception, "We should have never gotten here." + raise Exception("We should have never gotten here.") - mykeys = mydict.keys( ) - myvalues = map( _totuple, mydict.values( ) ) + mykeys = list(mydict.keys( )) + myvalues = list(map( _totuple, list(mydict.values( )) )) - maxlength = max( map( len, [ args ] + myvalues ) ) + maxlength = max( list(map( len, [ args ] + myvalues )) ) - for i in xrange( maxlength ): + for i in range( maxlength ): thisdict = { } for key, value in zip( mykeys, myvalues ): try: @@ -383,7 +383,7 @@ def _argsdicts( args, mydict ): def _totuple( x ): """Utility stuff to convert string, int, float, None or anything to a usable tuple.""" - if isinstance( x, basestring ): + if isinstance( x, str ): out = x, elif isinstance( x, ( int, float ) ): out = str( x ), @@ -397,7 +397,7 @@ def _totuple( x ): def escape( text, newline=False ): """Escape special html characters.""" - if isinstance( text, basestring ): + if isinstance( text, str ): if '&' in text: text = text.replace( '&', '&' ) if '>' in text: @@ -419,7 +419,7 @@ _escape = escape def unescape( text ): """Inverse of escape.""" - if isinstance( text, basestring ): + if isinstance( text, str ): if '&' in text: text = text.replace( '&', '&' ) if '>' in text: @@ -481,4 +481,4 @@ class CustomizationError( MarkupError ): self.message = "If you customize the allowed elements, you must define both types 'onetags' and 'twotags'." if __name__ == '__main__': - print __doc__ + print(__doc__) diff --git a/tablib/packages/ordereddict.py b/tablib/packages/ordereddict.py index 5b0303f..a5b896d 100644 --- a/tablib/packages/ordereddict.py +++ b/tablib/packages/ordereddict.py @@ -1,127 +1,127 @@ -# Copyright (c) 2009 Raymond Hettinger -# -# 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. - -from UserDict import DictMixin - -class OrderedDict(dict, DictMixin): - - def __init__(self, *args, **kwds): - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__end - except AttributeError: - self.clear() - self.update(*args, **kwds) - - def clear(self): - self.__end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.__map = {} # key --> [key, prev, next] - dict.clear(self) - - def __setitem__(self, key, value): - if key not in self: - end = self.__end - curr = end[1] - curr[2] = end[1] = self.__map[key] = [key, curr, end] - dict.__setitem__(self, key, value) - - def __delitem__(self, key): - dict.__delitem__(self, key) - key, prev, next = self.__map.pop(key) - prev[2] = next - next[1] = prev - - def __iter__(self): - end = self.__end - curr = end[2] - while curr is not end: - yield curr[0] - curr = curr[2] - - def __reversed__(self): - end = self.__end - curr = end[1] - while curr is not end: - yield curr[0] - curr = curr[1] - - def popitem(self, last=True): - if not self: - raise KeyError('dictionary is empty') - if last: - key = reversed(self).next() - else: - key = iter(self).next() - value = self.pop(key) - return key, value - - def __reduce__(self): - items = [[k, self[k]] for k in self] - tmp = self.__map, self.__end - del self.__map, self.__end - inst_dict = vars(self).copy() - self.__map, self.__end = tmp - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def keys(self): - return list(self) - - setdefault = DictMixin.setdefault - update = DictMixin.update - pop = DictMixin.pop - values = DictMixin.values - items = DictMixin.items - iterkeys = DictMixin.iterkeys - itervalues = DictMixin.itervalues - iteritems = DictMixin.iteritems - - def __repr__(self): - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - - def copy(self): - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - if isinstance(other, OrderedDict): - if len(self) != len(other): - return False - for p, q in zip(self.items(), other.items()): - if p != q: - return False - return True - return dict.__eq__(self, other) - - def __ne__(self, other): - return not self == other +# Copyright (c) 2009 Raymond Hettinger +# +# 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. + +from UserDict import DictMixin + +class OrderedDict(dict, DictMixin): + + def __init__(self, *args, **kwds): + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__end + except AttributeError: + self.clear() + self.update(*args, **kwds) + + def clear(self): + self.__end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.__map = {} # key --> [key, prev, next] + dict.clear(self) + + def __setitem__(self, key, value): + if key not in self: + end = self.__end + curr = end[1] + curr[2] = end[1] = self.__map[key] = [key, curr, end] + dict.__setitem__(self, key, value) + + def __delitem__(self, key): + dict.__delitem__(self, key) + key, prev, next = self.__map.pop(key) + prev[2] = next + next[1] = prev + + def __iter__(self): + end = self.__end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.__end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + def popitem(self, last=True): + if not self: + raise KeyError('dictionary is empty') + if last: + key = next(reversed(self)) + else: + key = next(iter(self)) + value = self.pop(key) + return key, value + + def __reduce__(self): + items = [[k, self[k]] for k in self] + tmp = self.__map, self.__end + del self.__map, self.__end + inst_dict = vars(self).copy() + self.__map, self.__end = tmp + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def keys(self): + return list(self) + + setdefault = DictMixin.setdefault + update = DictMixin.update + pop = DictMixin.pop + values = DictMixin.values + items = DictMixin.items + iterkeys = DictMixin.iterkeys + itervalues = DictMixin.itervalues + iteritems = DictMixin.iteritems + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self.items())) + + def copy(self): + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + if isinstance(other, OrderedDict): + if len(self) != len(other): + return False + for p, q in zip(list(self.items()), list(other.items())): + if p != q: + return False + return True + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other