diff --git a/pandas/core/common.py b/pandas/core/common.py index d420d418352cd..092510e1a9b21 100644 --- a/pandas/core/common.py +++ b/pandas/core/common.py @@ -1,8 +1,10 @@ """ Misc tools for implementing data structures """ - -from cStringIO import StringIO +try: + from io import BytesIO +except ImportError: # Python < 2.6 + from cStringIO import StringIO as BytesIO import itertools from numpy.lib.format import read_array, write_array @@ -76,13 +78,13 @@ def notnull(obj): def _pickle_array(arr): arr = arr.view(np.ndarray) - buf = StringIO() + buf = BytesIO() write_array(buf, arr) return buf.getvalue() def _unpickle_array(bytes): - arr = read_array(StringIO(bytes)) + arr = read_array(BytesIO(bytes)) return arr def _take_1d_bool(arr, indexer, out): @@ -390,7 +392,7 @@ def rands(n): """Generates a random alphanumeric string of length *n*""" from random import Random import string - return ''.join(Random().sample(string.letters+string.digits, n)) + return ''.join(Random().sample(string.ascii_letters+string.digits, n)) def adjoin(space, *lists): """ @@ -458,7 +460,11 @@ def __init__(self, seq, key=lambda x:x): for value in seq: k = key(value) self.setdefault(k, []).append(value) - __iter__ = dict.iteritems + try: + __iter__ = dict.iteritems + except AttributeError: # Python 3 + def __iter__(self): + return iter(dict.items(self)) def map_indices_py(arr): """ diff --git a/pandas/core/frame.py b/pandas/core/frame.py index efb5deeca0cf1..410be6976f1c4 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -29,6 +29,7 @@ from pandas.core.internals import BlockManager, make_block, form_blocks from pandas.core.series import Series, _is_bool_indexer from pandas.util.decorators import deprecate +from pandas.util import py3compat import pandas.core.common as common import pandas.core.datetools as datetools import pandas._tseries as _tseries @@ -276,6 +277,10 @@ def iteritems(self): """Iterator over (column, series) pairs""" series = self._series return ((k, series[k]) for k in self.columns) + + iterkv = iteritems + if py3compat.PY3: + items = iteritems def __len__(self): """Returns length of index""" @@ -291,7 +296,7 @@ def __contains__(self, key): add = _arith_method(operator.add, 'add') mul = _arith_method(operator.mul, 'multiply') sub = _arith_method(operator.sub, 'subtract') - div = _arith_method(operator.div, 'divide') + div = _arith_method(lambda x, y: x / y, 'divide') radd = _arith_method(operator.add, 'add') rmul = _arith_method(operator.mul, 'multiply') @@ -301,19 +306,26 @@ def __contains__(self, key): __add__ = _arith_method(operator.add, '__add__', default_axis=None) __sub__ = _arith_method(operator.sub, '__sub__', default_axis=None) __mul__ = _arith_method(operator.mul, '__mul__', default_axis=None) - __div__ = _arith_method(operator.div, '__div__', default_axis=None) __truediv__ = _arith_method(operator.truediv, '__truediv__', default_axis=None) + __floordiv__ = _arith_method(operator.floordiv, '__floordiv__', + default_axis=None) __pow__ = _arith_method(operator.pow, '__pow__', default_axis=None) __radd__ = _arith_method(operator.add, '__radd__', default_axis=None) __rmul__ = _arith_method(operator.mul, '__rmul__', default_axis=None) __rsub__ = _arith_method(lambda x, y: y - x, '__rsub__', default_axis=None) - __rdiv__ = _arith_method(lambda x, y: y / x, '__rdiv__', default_axis=None) __rtruediv__ = _arith_method(lambda x, y: y / x, '__rtruediv__', default_axis=None) + __rfloordiv__ = _arith_method(lambda x, y: y // x, '__rfloordiv__', + default_axis=None) __rpow__ = _arith_method(lambda x, y: y ** x, '__rpow__', default_axis=None) + + # Python 2 division methods + if not py3compat.PY3: + __div__ = _arith_method(operator.div, '__div__', default_axis=None) + __rdiv__ = _arith_method(lambda x, y: y / x, '__rdiv__', default_axis=None) def __neg__(self): return self * -1 @@ -463,7 +475,7 @@ def to_sparse(self, fill_value=None, kind='block'): default_fill_value=fill_value) def to_csv(self, path, nanRep='', cols=None, header=True, - index=True, index_label=None, mode='wb'): + index=True, index_label=None, mode='w'): """ Write DataFrame to a comma-separated values (csv) file @@ -482,7 +494,7 @@ def to_csv(self, path, nanRep='', cols=None, header=True, Column label for index column(s) if desired. If None is given, and `header` and `index` are True, then the index names are used. A sequence should be given if the DataFrame uses MultiIndex. - mode : Python write mode, default 'wb' + mode : Python write mode, default 'w' """ f = open(path, mode) @@ -652,7 +664,7 @@ def dtypes(self): def get_dtype_counts(self): counts = {} - for _, series in self.iteritems(): + for _, series in self.iterkv(): if series.dtype in counts: counts[series.dtype] += 1 else: @@ -909,7 +921,7 @@ def _set_item(self, key, value): def _sanitize_column(self, value): # Need to make sure new columns (which go into the BlockManager as new # blocks) are always copied - if hasattr(value, '__iter__'): + if hasattr(value, '__iter__') and not isinstance(value, basestring): if isinstance(value, Series): if value.index.equals(self.index): # copy the values diff --git a/pandas/core/panel.py b/pandas/core/panel.py index b4f2589270a4a..3b7708e85ad92 100644 --- a/pandas/core/panel.py +++ b/pandas/core/panel.py @@ -19,6 +19,7 @@ from pandas.core.generic import AxisProperty, NDFrame from pandas.core.series import Series from pandas.util.decorators import deprecate +from pandas.util import py3compat import pandas.core.common as common import pandas._tseries as _tseries @@ -174,16 +175,22 @@ class Panel(NDFrame): __add__ = _arith_method(operator.add, '__add__') __sub__ = _arith_method(operator.sub, '__sub__') + __truediv__ = _arith_method(operator.truediv, '__truediv__') + __floordiv__ = _arith_method(operator.floordiv, '__floordiv__') __mul__ = _arith_method(operator.mul, '__mul__') - __div__ = _arith_method(operator.div, '__div__') __pow__ = _arith_method(operator.pow, '__pow__') __radd__ = _arith_method(operator.add, '__radd__') __rmul__ = _arith_method(operator.mul, '__rmul__') __rsub__ = _arith_method(lambda x, y: y - x, '__rsub__') - __rdiv__ = _arith_method(lambda x, y: y / x, '__rdiv__') + __rtruediv__ = _arith_method(lambda x, y: y / x, '__rtruediv__') + __rfloordiv__ = _arith_method(lambda x, y: y // x, '__rfloordiv__') __rpow__ = _arith_method(lambda x, y: y ** x, '__rpow__') + if not py3compat.PY3: + __div__ = _arith_method(operator.div, '__div__') + __rdiv__ = _arith_method(lambda x, y: y / x, '__rdiv__') + def __init__(self, data, items=None, major_axis=None, minor_axis=None, copy=False, dtype=None): """ @@ -333,6 +340,10 @@ def __iter__(self): def iteritems(self): for item in self.items: yield item, self[item] + + # Name that won't get automatically converted to items by 2to3. items is + # already in use for the first axis. + iterkv = iteritems def _get_plane_axes(self, axis): """ @@ -387,7 +398,7 @@ def to_sparse(self, fill_value=None, kind='block'): y : SparseDataFrame """ from pandas.core.sparse import SparsePanel - frames = dict(self.iteritems()) + frames = dict(self.iterkv()) return SparsePanel(frames, items=self.items, major_axis=self.major_axis, minor_axis=self.minor_axis, @@ -636,7 +647,7 @@ def fillna(self, value=None, method='pad'): """ if value is None: result = {} - for col, s in self.iteritems(): + for col, s in self.iterkv(): result[col] = s.fillna(method=method, value=value) return Panel.from_dict(result) @@ -646,8 +657,12 @@ def fillna(self, value=None, method='pad'): add = _panel_arith_method(operator.add, 'add') subtract = sub = _panel_arith_method(operator.sub, 'subtract') - divide = div = _panel_arith_method(operator.div, 'divide') multiply = mul = _panel_arith_method(operator.mul, 'multiply') + + try: + divide = div = _panel_arith_method(operator.div, 'divide') + except AttributeError: # Python 3 + divide = div = _panel_arith_method(operator.truediv, 'divide') def major_xs(self, key, copy=True): """ @@ -1218,8 +1233,12 @@ def _combine_panel_frame(self, other, func, axis='items'): add = _panel_arith_method(operator.add, 'add') subtract = sub = _panel_arith_method(operator.sub, 'subtract') - divide = div = _panel_arith_method(operator.div, 'divide') multiply = mul = _panel_arith_method(operator.mul, 'multiply') + + try: + divide = div = _panel_arith_method(operator.div, 'divide') + except AttributeError: # Python 3 + divide = div = _panel_arith_method(operator.truediv, 'divide') def to_wide(self): """ diff --git a/pandas/core/series.py b/pandas/core/series.py index b272fabf6ce56..0ffa28b9ad963 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -20,6 +20,7 @@ from pandas.core.index import Index, MultiIndex, _ensure_index from pandas.core.indexing import _SeriesIndexer, _maybe_droplevels from pandas.util.decorators import deprecate +from pandas.util import py3compat import pandas.core.common as common import pandas.core.datetools as datetools import pandas._tseries as lib @@ -366,6 +367,10 @@ def iteritems(self): Lazily iterate over (index, value) tuples """ return itertools.izip(iter(self.index), iter(self)) + + iterkv = iteritems + if py3compat.PY3: + items = iteritems #---------------------------------------------------------------------- # Arithmetic operators @@ -373,24 +378,30 @@ def iteritems(self): __add__ = _arith_method(operator.add, '__add__') __sub__ = _arith_method(operator.sub, '__sub__') __mul__ = _arith_method(operator.mul, '__mul__') - __div__ = _arith_method(operator.div, '__div__') __truediv__ = _arith_method(operator.truediv, '__truediv__') + __floordiv__ = _arith_method(operator.floordiv, '__floordiv__') __pow__ = _arith_method(operator.pow, '__pow__') - __truediv__ = _arith_method(operator.truediv, '__truediv__') __radd__ = _arith_method(operator.add, '__add__') __rmul__ = _arith_method(operator.mul, '__mul__') __rsub__ = _arith_method(lambda x, y: y - x, '__sub__') - __rdiv__ = _arith_method(lambda x, y: y / x, '__div__') __rtruediv__ = _arith_method(lambda x, y: y / x, '__truediv__') + __rfloordiv__ = _arith_method(lambda x, y: y // x, '__floordiv__') __rpow__ = _arith_method(lambda x, y: y ** x, '__pow__') # Inplace operators __iadd__ = __add__ __isub__ = __sub__ __imul__ = __mul__ - __idiv__ = __div__ + __itruediv__ = __truediv__ + __ifloordiv__ = __floordiv__ __ipow__ = __pow__ + + # Python 2 division operators + if not py3compat.PY3: + __div__ = _arith_method(operator.div, '__div__') + __rdiv__ = _arith_method(lambda x, y: y / x, '__div__') + __idiv__ = __div__ #---------------------------------------------------------------------- # Misc public methods @@ -977,7 +988,10 @@ def _binop(self, other, func, fill_value=None): add = _flex_method(operator.add, 'add') sub = _flex_method(operator.sub, 'subtract') mul = _flex_method(operator.mul, 'multiply') - div = _flex_method(operator.div, 'divide') + try: + div = _flex_method(operator.div, 'divide') + except AttributeError: # Python 3 + div = _flex_method(operator.truediv, 'divide') def combine(self, other, func, fill_value=nan): """ @@ -1529,7 +1543,7 @@ def to_csv(self, path): path : string or None Output filepath. If None, write to stdout """ - f = open(path, 'wb') + f = open(path, 'w') for idx, value in self.iteritems(): f.write(str(idx) + ',' + str(value) + '\n') f.close() diff --git a/pandas/core/sparse.py b/pandas/core/sparse.py index 24dc5ab857c17..1d1d096b050d5 100644 --- a/pandas/core/sparse.py +++ b/pandas/core/sparse.py @@ -20,6 +20,8 @@ import pandas.core.common as common import pandas.core.datetools as datetools +from pandas.util import py3compat + from pandas._sparse import BlockIndex, IntIndex import pandas._sparse as splib @@ -286,24 +288,31 @@ def __repr__(self): __add__ = _sparse_op_wrap(operator.add, 'add') __sub__ = _sparse_op_wrap(operator.sub, 'sub') __mul__ = _sparse_op_wrap(operator.mul, 'mul') - __div__ = _sparse_op_wrap(operator.div, 'div') __truediv__ = _sparse_op_wrap(operator.truediv, 'truediv') + __floordiv__ = _sparse_op_wrap(operator.floordiv, 'floordiv') __pow__ = _sparse_op_wrap(operator.pow, 'pow') # reverse operators __radd__ = _sparse_op_wrap(operator.add, '__radd__') - __rmul__ = _sparse_op_wrap(operator.mul, '__rmul__') __rsub__ = _sparse_op_wrap(lambda x, y: y - x, '__rsub__') - __rdiv__ = _sparse_op_wrap(lambda x, y: y / x, '__rdiv__') + __rmul__ = _sparse_op_wrap(operator.mul, '__rmul__') __rtruediv__ = _sparse_op_wrap(lambda x, y: y / x, '__rtruediv__') + __rfloordiv__ = _sparse_op_wrap(lambda x, y: y // x, 'floordiv') __rpow__ = _sparse_op_wrap(lambda x, y: y ** x, '__rpow__') # Inplace operators __iadd__ = __add__ __isub__ = __sub__ __imul__ = __mul__ - __idiv__ = __div__ + __itruediv__ = __truediv__ + __ifloordiv__ = __floordiv__ __ipow__ = __pow__ + + # Python 2 division operators + if not py3compat.PY3: + __div__ = _sparse_op_wrap(operator.div, 'div') + __rdiv__ = _sparse_op_wrap(lambda x, y: y / x, '__rdiv__') + __idiv__ = __div__ @property def values(self): @@ -1555,7 +1564,7 @@ def _combine(self, other, func, axis=0): return self._combinePanel(other, func) elif np.isscalar(other): new_frames = dict((k, func(v, other)) - for k, v in self.iteritems()) + for k, v in self.iterkv()) return self._new_like(new_frames) def _combineFrame(self, other, func, axis=0): @@ -1631,7 +1640,7 @@ def major_xs(self, key): y : DataFrame index -> minor axis, columns -> items """ - slices = dict((k, v.xs(key)) for k, v in self.iteritems()) + slices = dict((k, v.xs(key)) for k, v in self.iterkv()) return DataFrame(slices, index=self.minor_axis, columns=self.items) def minor_xs(self, key): @@ -1648,7 +1657,7 @@ def minor_xs(self, key): y : SparseDataFrame index -> major axis, columns -> items """ - slices = dict((k, v[key]) for k, v in self.iteritems()) + slices = dict((k, v[key]) for k, v in self.iterkv()) return SparseDataFrame(slices, index=self.major_axis, columns=self.items, default_fill_value=self.default_fill_value, diff --git a/pandas/io/tests/test_parsers.py b/pandas/io/tests/test_parsers.py index d1931f456bf02..a8e752b2b0618 100644 --- a/pandas/io/tests/test_parsers.py +++ b/pandas/io/tests/test_parsers.py @@ -120,6 +120,11 @@ def test_read_csv_no_index_name(self): assert_frame_equal(df, df2) def test_excel_table(self): + try: + import xlrd + except ImportError: + import nose + raise nose.SkipTest pth = os.path.join(self.dirpath, 'test.xls') xls = ExcelFile(pth) df = xls.parse('Sheet1') diff --git a/pandas/src/sparse.pyx b/pandas/src/sparse.pyx index 1a44152925918..96ad5d5f1c42a 100644 --- a/pandas/src/sparse.pyx +++ b/pandas/src/sparse.pyx @@ -31,6 +31,15 @@ cdef inline float64_t __div(float64_t a, float64_t b): else: return a / b +cdef inline float64_t __floordiv(float64_t a, float64_t b): + if b == 0: + if a >= 0: + return INF + else: + return -INF + else: + return a // b + cdef inline float64_t __mul(float64_t a, float64_t b): return a * b cdef inline float64_t __eq(float64_t a, float64_t b): @@ -725,6 +734,12 @@ cpdef sparse_nandiv(ndarray x, SparseIndex xindex, ndarray y, SparseIndex yindex): return sparse_nancombine(x, xindex, y, yindex, __div) +sparse_nantruediv = sparse_nandiv + +cpdef sparse_nanfloordiv(ndarray x, SparseIndex xindex, + ndarray y, SparseIndex yindex): + return sparse_nancombine(x, xindex, y, yindex, __floordiv) + cpdef sparse_nanpow(ndarray x, SparseIndex xindex, ndarray y, SparseIndex yindex): return sparse_nancombine(x, xindex, y, yindex, __pow) @@ -758,6 +773,12 @@ cpdef sparse_div(ndarray x, SparseIndex xindex, float64_t xfill, ndarray y, SparseIndex yindex, float64_t yfill): return sparse_combine(x, xindex, xfill, y, yindex, yfill, __div) +sparse_truediv = sparse_div + +cpdef sparse_floordiv(ndarray x, SparseIndex xindex, float64_t xfill, + ndarray y, SparseIndex yindex, float64_t yfill): + return sparse_combine(x, xindex, xfill, + y, yindex, yfill, __floordiv) cpdef sparse_pow(ndarray x, SparseIndex xindex, float64_t xfill, ndarray y, SparseIndex yindex, float64_t yfill): diff --git a/pandas/src/tseries.pyx b/pandas/src/tseries.pyx index b65ea0370ac50..ed65a9b39e660 100644 --- a/pandas/src/tseries.pyx +++ b/pandas/src/tseries.pyx @@ -49,8 +49,8 @@ cdef double_t *get_double_ptr(ndarray arr): cdef extern from "math.h": double sqrt(double x) -cdef extern from "cobject.h": - pass # for datetime API +#cdef extern from "cobject.h": +# pass # for datetime API cdef extern from "datetime.h": diff --git a/pandas/stats/plm.py b/pandas/stats/plm.py index 8634ed7a5afe0..43d6322f807d2 100644 --- a/pandas/stats/plm.py +++ b/pandas/stats/plm.py @@ -210,7 +210,10 @@ def _convert_x(self, x): # for x named 'variety', then x_conversion['variety'][0] is 'A'. x_converted = {} cat_mapping = {} - for key, df in x.iteritems(): + # x can be either a dict or a Panel, but in Python 3, dicts don't have + # .iteritems + iteritems = getattr(x, 'iteritems', x.items) + for key, df in iteritems(): assert(isinstance(df, DataFrame)) if _is_numeric(df): diff --git a/pandas/tests/test_daterange.py b/pandas/tests/test_daterange.py index 02ced4f5e42b3..f301411a8fc24 100644 --- a/pandas/tests/test_daterange.py +++ b/pandas/tests/test_daterange.py @@ -298,6 +298,7 @@ def _skip_if_no_pytz(): try: import pytz except ImportError: + import nose raise nose.SkipTest if __name__ == '__main__': diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 3f5e6777d1849..d256a8d138867 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -2368,23 +2368,23 @@ def test_combine_first(self): assert_frame_equal(comb, self.frame) def test_combine_first_mixed_bug(self): - idx = Index(['a','b','c','e']) - ser1 = Series([5.0,-9.0,4.0,100.],index=idx) - ser2 = Series(['a', 'b', 'c', 'e'], index=idx) - ser3 = Series([12,4,5,97], index=idx) - - frame1 = DataFrame({"col0" : ser1, - "col2" : ser2, - "col3" : ser3}) - - idx = Index(['a','b','c','f']) - ser1 = Series([5.0,-9.0,4.0,100.], index=idx) - ser2 = Series(['a','b','c','f'], index=idx) - ser3 = Series([12,4,5,97],index=idx) - - frame2 = DataFrame({"col1" : ser1, - "col2" : ser2, - "col5" : ser3}) + idx = Index(['a','b','c','e']) + ser1 = Series([5.0,-9.0,4.0,100.],index=idx) + ser2 = Series(['a', 'b', 'c', 'e'], index=idx) + ser3 = Series([12,4,5,97], index=idx) + + frame1 = DataFrame({"col0" : ser1, + "col2" : ser2, + "col3" : ser3}) + + idx = Index(['a','b','c','f']) + ser1 = Series([5.0,-9.0,4.0,100.], index=idx) + ser2 = Series(['a','b','c','f'], index=idx) + ser3 = Series([12,4,5,97],index=idx) + + frame2 = DataFrame({"col1" : ser1, + "col2" : ser2, + "col5" : ser3}) combined = frame1.combine_first(frame2) diff --git a/pandas/tests/test_groupby.py b/pandas/tests/test_groupby.py index d303ab2cd33fe..8caae56dd335c 100644 --- a/pandas/tests/test_groupby.py +++ b/pandas/tests/test_groupby.py @@ -61,7 +61,7 @@ def setUp(self): columns=['A', 'B', 'C']) def test_basic(self): - data = Series(np.arange(9) / 3, index=np.arange(9)) + data = Series(np.arange(9) // 3, index=np.arange(9)) index = np.arange(9) np.random.shuffle(index) @@ -197,7 +197,7 @@ def test_basic_regression(self): grouped.mean() def test_transform(self): - data = Series(np.arange(9) / 3, index=np.arange(9)) + data = Series(np.arange(9) // 3, index=np.arange(9)) index = np.arange(9) np.random.shuffle(index) diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py index fb2116c7c2ba7..173ba6490083a 100644 --- a/pandas/tests/test_index.py +++ b/pandas/tests/test_index.py @@ -547,7 +547,7 @@ def test_get_indexer(self): assert_almost_equal(r1, rexp1) self.assertRaises(Exception, idx1.get_indexer, - list(zip(*idx2.get_tuple_index())[0])) + list(list(zip(*idx2.get_tuple_index()))[0])) def test_format(self): self.index.format() diff --git a/pandas/tests/test_libsparse.py b/pandas/tests/test_libsparse.py index 5782b1ad224d8..2ff417537c3fa 100644 --- a/pandas/tests/test_libsparse.py +++ b/pandas/tests/test_libsparse.py @@ -333,7 +333,7 @@ def _check_case(xloc, xlen, yloc, ylen, eloc, elen): # too cute? oh but how I abhor code duplication -check_ops = ['add', 'sub', 'mul', 'div'] +check_ops = ['add', 'sub', 'mul', 'truediv', 'floordiv'] def make_nanoptestf(op): def f(self): sparse_op = getattr(splib, 'sparse_nan%s' % op) diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py index b4cafb42bf485..fc5cdbcac1603 100644 --- a/pandas/tests/test_panel.py +++ b/pandas/tests/test_panel.py @@ -14,6 +14,7 @@ from pandas.core.panel import Panel, LongPanel from pandas.core.series import remove_na import pandas.core.panel as panelmod +from pandas.util import py3compat from pandas.util.testing import (assert_panel_equal, assert_frame_equal, @@ -199,7 +200,8 @@ def test_arith(self): self._test_op(self.panel, operator.add) self._test_op(self.panel, operator.sub) self._test_op(self.panel, operator.mul) - self._test_op(self.panel, operator.div) + self._test_op(self.panel, operator.truediv) + self._test_op(self.panel, operator.floordiv) self._test_op(self.panel, operator.pow) self._test_op(self.panel, lambda x, y: y + x) @@ -219,11 +221,12 @@ def test_keys(self): common.equalContents(self.panel.keys(), self.panel.items) def test_iteritems(self): + """Test panel.iteritems(), aka panel.iterkv()""" # just test that it works - for k, v in self.panel.iteritems(): + for k, v in self.panel.iterkv(): pass - self.assertEqual(len(list(self.panel.iteritems())), + self.assertEqual(len(list(self.panel.iterkv())), len(self.panel.items)) def test_combineFrame(self): @@ -258,7 +261,10 @@ def check_op(op, name): check_op(operator.add, 'add') check_op(operator.sub, 'subtract') check_op(operator.mul, 'multiply') - check_op(operator.div, 'divide') + if py3compat.PY3: + check_op(operator.truediv, 'divide') + else: + check_op(operator.div, 'divide') def test_combinePanel(self): result = self.panel.add(self.panel) @@ -843,8 +849,8 @@ def test_fromRecords_toRecords(self): K = 10 recs = np.zeros(K, dtype='O,O,f8,f8') - recs['f0'] = range(K / 2) * 2 - recs['f1'] = np.arange(K) / (K / 2) + recs['f0'] = range(K // 2) * 2 + recs['f1'] = np.arange(K) / (K // 2) recs['f2'] = np.arange(K) * 2 recs['f3'] = np.arange(K) diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index cda6ecd98b44d..99b56f932df5b 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -11,6 +11,7 @@ from pandas import Index, Series, TimeSeries, DataFrame, isnull, notnull from pandas.core.index import MultiIndex import pandas.core.datetools as datetools +from pandas.util import py3compat from pandas.util.testing import assert_series_equal, assert_almost_equal import pandas.util.testing as common @@ -349,7 +350,10 @@ def test_iter(self): self.assertEqual(val, self.ts[i]) def test_keys(self): - self.assert_(self.ts.keys() is self.ts.index) + # HACK: By doing this in two stages, we avoid 2to3 wrapping the call + # to .keys() in a list() + getkeys = self.ts.keys + self.assert_(getkeys() is self.ts.index) def test_values(self): self.assert_(np.array_equal(self.ts, self.ts.values)) @@ -480,13 +484,15 @@ def _check_op(other, op): def check(other): _check_op(other, operator.add) _check_op(other, operator.sub) - _check_op(other, operator.div) + _check_op(other, operator.truediv) + _check_op(other, operator.floordiv) _check_op(other, operator.mul) _check_op(other, operator.pow) _check_op(other, lambda x, y: operator.add(y, x)) _check_op(other, lambda x, y: operator.sub(y, x)) - _check_op(other, lambda x, y: operator.div(y, x)) + _check_op(other, lambda x, y: operator.truediv(y, x)) + _check_op(other, lambda x, y: operator.floordiv(y, x)) _check_op(other, lambda x, y: operator.mul(y, x)) _check_op(other, lambda x, y: operator.pow(y, x)) @@ -544,7 +550,8 @@ def _check_op(arr, op): _check_op(arr, operator.add) _check_op(arr, operator.sub) _check_op(arr, operator.mul) - _check_op(arr, operator.div) + _check_op(arr, operator.truediv) + _check_op(arr, operator.floordiv) def test_operators_frame(self): # rpow does not work with DataFrame @@ -585,7 +592,11 @@ def _check_fill(meth, op, a, b, fill_value=0): b = Series([nan, 1, nan, 3, nan, 4.], index=np.arange(6)) ops = [Series.add, Series.sub, Series.mul, Series.div] - equivs = [operator.add, operator.sub, operator.mul, operator.div] + equivs = [operator.add, operator.sub, operator.mul] + if py3compat.PY3: + equivs.append(operator.truediv) + else: + equivs.append(operator.div) fillvals = [0, 0, 1, 1] for op, equiv_op, fv in zip(ops, equivs, fillvals): diff --git a/pandas/tests/test_sparse.py b/pandas/tests/test_sparse.py index 025ec042d10af..78c25abb86097 100644 --- a/pandas/tests/test_sparse.py +++ b/pandas/tests/test_sparse.py @@ -89,7 +89,7 @@ def assert_sp_frame_equal(left, right, exact_indices=True): assert(col in left) def assert_sp_panel_equal(left, right, exact_indices=True): - for item, frame in left.iteritems(): + for item, frame in left.iterkv(): assert(item in right) # trade-off? assert_sp_frame_equal(frame, right[item], exact_indices=exact_indices) @@ -350,12 +350,14 @@ def _check_op(a, b, op): def check(a, b): _check_op(a, b, operator.add) _check_op(a, b, operator.sub) - _check_op(a, b, operator.div) + _check_op(a, b, operator.truediv) + _check_op(a, b, operator.floordiv) _check_op(a, b, operator.mul) _check_op(a, b, lambda x, y: operator.add(y, x)) _check_op(a, b, lambda x, y: operator.sub(y, x)) - _check_op(a, b, lambda x, y: operator.div(y, x)) + _check_op(a, b, lambda x, y: operator.truediv(y, x)) + _check_op(a, b, lambda x, y: operator.floordiv(y, x)) _check_op(a, b, lambda x, y: operator.mul(y, x)) # NaN ** 0 = 1 in C? @@ -750,7 +752,7 @@ def _compare_to_dense(a, b, da, db, op): assert_sp_frame_equal(mixed_result, sparse_result, exact_indices=False) - opnames = ['add', 'sub', 'mul', 'div'] + opnames = ['add', 'sub', 'mul', 'truediv', 'floordiv'] ops = [getattr(operator, name) for name in opnames] fidx = frame.index diff --git a/pandas/util/py3compat.py b/pandas/util/py3compat.py new file mode 100644 index 0000000000000..e8bb212e215f2 --- /dev/null +++ b/pandas/util/py3compat.py @@ -0,0 +1,3 @@ +import sys + +PY3 = (sys.version_info[0] >= 3) diff --git a/pandas/util/testing.py b/pandas/util/testing.py index 1fae8fed79ea2..e5de8da459813 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -31,7 +31,7 @@ K = 4 def rands(n): - choices = string.letters + string.digits + choices = string.ascii_letters + string.digits return ''.join([random.choice(choices) for _ in xrange(n)]) #------------------------------------------------------------------------------- @@ -70,6 +70,10 @@ def isiterable(obj): def assert_almost_equal(a, b): if isinstance(a, dict) or isinstance(b, dict): return assert_dict_equal(a, b) + + if isinstance(a, basestring): + assert a == b, (a, b) + return True if isiterable(a): np.testing.assert_(isiterable(b)) @@ -119,7 +123,7 @@ def assert_series_equal(left, right): def assert_frame_equal(left, right): assert(isinstance(left, DataFrame)) assert(isinstance(right, DataFrame)) - for col, series in left.iteritems(): + for col, series in left.iterkv(): assert(col in right) assert_series_equal(series, right[col]) for col in right: @@ -132,7 +136,7 @@ def assert_panel_equal(left, right): assert(left.major_axis.equals(right.major_axis)) assert(left.minor_axis.equals(right.minor_axis)) - for col, series in left.iteritems(): + for col, series in left.iterkv(): assert(col in right) assert_frame_equal(series, right[col]) diff --git a/setup.py b/setup.py index 671afcbc9f0bc..63fa3d6b0813e 100755 --- a/setup.py +++ b/setup.py @@ -5,24 +5,26 @@ (https://github.com/zeromq/pyzmq) and hence are subject to the terms of the Lesser GPU General Public License. """ + +from distutils.core import setup, Command # use setuptools if available -# try: -# from setuptools import setup -# _have_setuptools = True -# except ImportError: -# _have_setuptools = False +try: + from setuptools import setup + _have_setuptools = True +except ImportError: + _have_setuptools = False from datetime import datetime from glob import glob import os import sys import shutil +import warnings import numpy as np # from numpy.distutils.core import setup -from distutils.core import setup, Command from distutils.extension import Extension from distutils.command.build import build from distutils.command.build_ext import build_ext @@ -128,10 +130,10 @@ import subprocess pipe = subprocess.Popen(["git", "rev-parse", "--short", "HEAD"], stdout=subprocess.PIPE).stdout - rev = pipe.read().strip() + rev = pipe.read().strip().decode('ascii') FULLVERSION += "-%s" % rev except: - print "WARNING: Couldn't get git revision" + warnings.warn("WARNING: Couldn't get git revision") def write_version_py(filename='pandas/version.py'): cnt = """\ @@ -215,10 +217,10 @@ def check_cython_extensions(self, extensions): for ext in extensions: for src in ext.sources: if not os.path.exists(src): - print """Cython-generated file '%s' not found. + raise Exception("""Cython-generated file '%s' not found. Cython is required to compile pandas from a development branch. Please install Cython or download a release package of pandas. - """ % src + """ % src) def build_extensions(self): self.check_cython_extensions(self.extensions) @@ -279,7 +281,7 @@ def srcpath(name=None, suffix='.pyx', subdir='src'): extensions = [tseries_ext, sparse_ext] -setuptools_args = {} +setuptools_args = {'use_2to3': True} # if _have_setuptools: # setuptools_args["test_suite"] = "nose.collector" @@ -293,13 +295,15 @@ def srcpath(name=None, suffix='.pyx', subdir='src'): 'pandas.io', 'pandas.sandbox', 'pandas.stats', - 'pandas.util'], - package_data={'pandas' : ['tests/*.py'], - 'pandas.io' : ['tests/*.py', - 'tests/*.h5', + 'pandas.util', + 'pandas.tests', + 'pandas.io.tests', + 'pandas.stats.tests', + ], + package_data={'pandas.io' : ['tests/*.h5', 'tests/*.csv', 'tests/*.xls'], - 'pandas.stats' : ['tests/*.py']}, + }, ext_modules=extensions, maintainer_email=MAINTAINER_EMAIL, description=DESCRIPTION,