From 2126ef50f422b7832e76b7fae3635ee18a666c0b Mon Sep 17 00:00:00 2001
From: Theo Steininger <theo.steininger@ultimanet.de>
Date: Wed, 3 May 2017 00:59:26 +0200
Subject: [PATCH] Added Python3 compatibility

---
 d2o/__init__.py                      |  13 +--
 d2o/config/__init__.py               |   3 +-
 d2o/d2o_iter.py                      |   3 +-
 d2o/d2o_librarian.py                 |   1 +
 d2o/distributed_data_object.py       |  25 +++--
 d2o/distributor_factory.py           | 132 ++++++++++++++-------------
 d2o/dtype_converter.py               |  10 +-
 d2o/factory_methods.py               |   5 +-
 d2o/slicing_generator.py             |   4 +-
 test/test_distributed_data_object.py | 123 ++++++++++++++-----------
 10 files changed, 181 insertions(+), 138 deletions(-)

diff --git a/d2o/__init__.py b/d2o/__init__.py
index 3803999..3d86cd1 100644
--- a/d2o/__init__.py
+++ b/d2o/__init__.py
@@ -17,13 +17,14 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import division
+from __future__ import absolute_import
 
-from version import __version__
+from .version import __version__
 
-from config import configuration
-from distributed_data_object import distributed_data_object
-from d2o_librarian import d2o_librarian
+from .config import configuration
+from .distributed_data_object import distributed_data_object
+from .d2o_librarian import d2o_librarian
 
-from strategies import STRATEGIES
+from .strategies import STRATEGIES
 
-from factory_methods import *
+from .factory_methods import *
diff --git a/d2o/config/__init__.py b/d2o/config/__init__.py
index 6a19b28..16fb1a0 100644
--- a/d2o/config/__init__.py
+++ b/d2o/config/__init__.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 # D2O
 # Copyright (C) 2016  Theo Steininger
 #
@@ -16,5 +17,5 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from d2o_config import dependency_injector,\
+from .d2o_config import dependency_injector,\
                        configuration
diff --git a/d2o/d2o_iter.py b/d2o/d2o_iter.py
index 94c3d12..65e338d 100644
--- a/d2o/d2o_iter.py
+++ b/d2o/d2o_iter.py
@@ -16,6 +16,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from builtins import object
 import numpy as np
 
 
@@ -29,7 +30,7 @@ class d2o_iter(object):
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         if self.n == 0:
             raise StopIteration()
 
diff --git a/d2o/d2o_librarian.py b/d2o/d2o_librarian.py
index 3367602..a331201 100644
--- a/d2o/d2o_librarian.py
+++ b/d2o/d2o_librarian.py
@@ -16,6 +16,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from builtins import object
 from weakref import WeakValueDictionary as weakdict
 
 
diff --git a/d2o/distributed_data_object.py b/d2o/distributed_data_object.py
index af4c48c..1106635 100644
--- a/d2o/distributed_data_object.py
+++ b/d2o/distributed_data_object.py
@@ -1,3 +1,5 @@
+from __future__ import division
+from __future__ import absolute_import
 # D2O
 # Copyright (C) 2016  Theo Steininger
 #
@@ -23,10 +25,10 @@ from keepers import Versionable,\
 from d2o.config import configuration as gc,\
                        dependency_injector as gdi
 
-from d2o_librarian import d2o_librarian
-from cast_axis_to_tuple import cast_axis_to_tuple
+from .d2o_librarian import d2o_librarian
+from .cast_axis_to_tuple import cast_axis_to_tuple
 
-from strategies import STRATEGIES
+from .strategies import STRATEGIES
 
 MPI = gdi[gc['mpi_module']]
 
@@ -174,7 +176,7 @@ class distributed_data_object(Loggable, Versionable, object):
         if distribution_strategy is None:
             distribution_strategy = gc['default_distribution_strategy']
 
-        from distributor_factory import distributor_factory
+        from .distributor_factory import distributor_factory
         self.distributor = distributor_factory.get_distributor(
                                 distribution_strategy=distribution_strategy,
                                 comm=comm,
@@ -263,7 +265,7 @@ class distributed_data_object(Loggable, Versionable, object):
         # repair its class
         new_copy.__class__ = self.__class__
         # now copy everthing in the __dict__ except for the data array
-        for key, value in self.__dict__.items():
+        for key, value in list(self.__dict__.items()):
             if key != 'data':
                 new_copy.__dict__[key] = value
             else:
@@ -837,7 +839,7 @@ class distributed_data_object(Loggable, Versionable, object):
         _builtin_helper
         """
 
-        return self.__div__(other)
+        return self._builtin_helper('__truediv__', other)
 
     def __rdiv__(self, other):
         """ x.__rdiv__(y) <==> y/x
@@ -857,7 +859,7 @@ class distributed_data_object(Loggable, Versionable, object):
         _builtin_helper
         """
 
-        return self.__rdiv__(other)
+        return self._builtin_helper('__rtruediv__', other)
 
     def __idiv__(self, other):
         """ x.__idiv__(y) <==> x/=y
@@ -879,7 +881,9 @@ class distributed_data_object(Loggable, Versionable, object):
         _builtin_helper
         """
 
-        return self.__idiv__(other)
+        return self._builtin_helper('__itruediv__',
+                                    other,
+                                    inplace=True)
 
     def __floordiv__(self, other):
         """ x.__floordiv__(y) <==> x//y
@@ -1472,7 +1476,10 @@ class distributed_data_object(Loggable, Versionable, object):
         if axis is ():
             return self.copy()
 
-        length = max(self.amax() + 1, minlength)
+        if minlength is not None:
+            length = max(self.amax() + 1, minlength)
+        else:
+            length = self.amax() + 1
 
         return self.distributor.bincount(obj=self,
                                          length=length,
diff --git a/d2o/distributor_factory.py b/d2o/distributor_factory.py
index a218efa..bb1c14c 100644
--- a/d2o/distributor_factory.py
+++ b/d2o/distributor_factory.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 # D2O
 # Copyright (C) 2016  Theo Steininger
 #
@@ -17,6 +18,11 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+from builtins import next
+from builtins import str
+from builtins import map
+from builtins import range
+from builtins import object
 import numpy as np
 
 from keepers import Loggable
@@ -24,17 +30,18 @@ from keepers import Loggable
 from d2o.config import configuration as gc,\
                        dependency_injector as gdi
 
-from distributed_data_object import distributed_data_object
+from .distributed_data_object import distributed_data_object
 
-from d2o_iter import d2o_slicing_iter,\
+from .d2o_iter import d2o_slicing_iter,\
                      d2o_not_iter
-from d2o_librarian import d2o_librarian
-from dtype_converter import dtype_converter
-from cast_axis_to_tuple import cast_axis_to_tuple
-from translate_to_mpi_operator import op_translate_dict
-from slicing_generator import slicing_generator
+from .d2o_librarian import d2o_librarian
+from .dtype_converter import dtype_converter
+from .cast_axis_to_tuple import cast_axis_to_tuple
+from .translate_to_mpi_operator import op_translate_dict
+from .slicing_generator import slicing_generator
 
-from strategies import STRATEGIES
+from .strategies import STRATEGIES
+from functools import reduce
 
 MPI = gdi[gc['mpi_module']]
 h5py = gdi.get('h5py')
@@ -208,10 +215,10 @@ class _distributor_factory(Loggable, object):
         kwargs['dtype'] = self.dictionize_np(kwargs['dtype'])
         kwargs['distribution_strategy'] = distribution_strategy
 
-        return frozenset(kwargs.items())
+        return frozenset(list(kwargs.items()))
 
     def dictionize_np(self, x):
-        dic = x.type.__dict__.items()
+        dic = list(x.type.__dict__.items())
         if x is np.float:
             dic[24] = 0
             dic[29] = 0
@@ -275,8 +282,8 @@ def _infer_key_type(key):
     elif isinstance(key, tuple) or isinstance(key, list):
         # Check if there is something different in the array than
         # scalars and slices
-        scalarQ = np.array(map(np.isscalar, key))
-        sliceQ = np.array(map(lambda z: isinstance(z, slice), key))
+        scalarQ = np.array(list(map(np.isscalar, key)))
+        sliceQ = np.array([isinstance(z, slice) for z in key])
         if np.all(scalarQ + sliceQ):
             found = 'slicetuple'
         else:
@@ -377,26 +384,24 @@ class distributor(object):
             # from the librarian
             else:
                 to_index_list = comm.allgather(to_key.index)
-                to_key_list = map(lambda z: d2o_librarian[z], to_index_list)
+                to_key_list = [d2o_librarian[z] for z in to_index_list]
 
             # gather the local from_keys. It is the same procedure as above
             if from_found != 'd2o':
                 from_key_list = comm.allgather(from_key)
             else:
                 from_index_list = comm.allgather(from_key.index)
-                from_key_list = map(lambda z: d2o_librarian[z],
-                                    from_index_list)
+                from_key_list = [d2o_librarian[z] for z in from_index_list]
 
             local_data_update_is_scalar = np.isscalar(data_update)
             local_scalar_list = comm.allgather(local_data_update_is_scalar)
-            for i in xrange(len(to_key_list)):
+            for i in range(len(to_key_list)):
                 if np.all(np.array(local_scalar_list) == True):
                     scalar_list = comm.allgather(data_update)
                     temp_data_update = scalar_list[i]
                 elif isinstance(data_update, distributed_data_object):
                     data_update_index_list = comm.allgather(data_update.index)
-                    data_update_list = map(lambda z: d2o_librarian[z],
-                                           data_update_index_list)
+                    data_update_list = [d2o_librarian[z] for z in data_update_index_list]
                     temp_data_update = data_update_list[i]
                 else:
                     # build a temporary freeform d2o which only contains data
@@ -458,14 +463,14 @@ class distributor(object):
             # do the reordering
             ndim = len(self.global_shape)
             axis = sorted(cast_axis_to_tuple(axis, length=ndim))
-            reordering = [x for x in xrange(ndim) if x not in axis]
+            reordering = [x for x in range(ndim) if x not in axis]
             reordering += axis
 
             data = np.transpose(data, reordering)
             if local_weights is not None:
                 local_weights = np.transpose(local_weights, reordering)
 
-            reord_axis = range(ndim-len(axis), ndim)
+            reord_axis = list(range(ndim-len(axis), ndim))
 
             # semi-flatten the dimensions in `axis`, i.e. after reordering
             # the last ones.
@@ -507,9 +512,9 @@ class distributor(object):
             # axis has been sorted above
             insert_position = axis[0]
             new_ndim = len(local_counts.shape)
-            return_order = (range(0, insert_position) +
+            return_order = (list(range(0, insert_position)) +
                             [new_ndim-1, ] +
-                            range(insert_position, new_ndim-1))
+                            list(range(insert_position, new_ndim-1)))
             local_counts = np.ascontiguousarray(
                                 local_counts.transpose(return_order))
         return self._combine_local_bincount_counts(obj, local_counts, axis)
@@ -656,7 +661,7 @@ class _slicing_distributor(distributor):
 
             # get first node with non-None data
             try:
-                start = next(i for i in xrange(size) if got_array_list[i] > 1)
+                start = next(i for i in range(size) if got_array_list[i] > 1)
             except(StopIteration):
                 raise ValueError("ERROR: No process with non-None data.")
 
@@ -675,7 +680,7 @@ class _slicing_distributor(distributor):
 
                 self.comm.Bcast([result_data, mpi_dtype], root=start)
 
-                for i in xrange(start+1, size):
+                for i in range(start+1, size):
                     if got_array_list[i] > 1:
                         if rank == i:
                             temp_data = data
@@ -686,7 +691,7 @@ class _slicing_distributor(distributor):
 
             else:
                 result_data = self.comm.bcast(data, root=start)
-                for i in xrange(start+1, size):
+                for i in range(start+1, size):
                     if got_array_list[i] > 1:
                         temp_data = self.comm.bcast(data, root=i)
                         result_data = op(result_data, temp_data)
@@ -702,7 +707,7 @@ class _slicing_distributor(distributor):
         if axis is None:
             new_shape = ()
         else:
-            new_shape = tuple([old_shape[i] for i in xrange(len(old_shape))
+            new_shape = tuple([old_shape[i] for i in range(len(old_shape))
                                if i not in axis])
 
         local_data = parent.data
@@ -1015,7 +1020,7 @@ class _slicing_distributor(distributor):
             # from the librarian
             else:
                 index_list = comm.allgather(key.index)
-                key_list = map(lambda z: d2o_librarian[z], index_list)
+                key_list = [d2o_librarian[z] for z in index_list]
             i = 0
             for temp_key in key_list:
                 # build the locally fed d2o
@@ -1104,7 +1109,7 @@ class _slicing_distributor(distributor):
             # if the index lies within the local nodes' data-range
             # take the shifted index, combined with rest of from_list_key
             result = [local_zeroth_key]
-            for ii in xrange(1, len(from_list_key)):
+            for ii in range(1, len(from_list_key)):
                 current = from_list_key[ii]
                 if isinstance(current, distributed_data_object):
                     result.append(current.get_full_data())
@@ -1125,21 +1130,20 @@ class _slicing_distributor(distributor):
                 raise ValueError("Index out of bounds!")
             # shift the indices according to shift
             shift_list = self.comm.allgather(shift)
-            local_zeroth_key_list = map(lambda z: zeroth_key - z, shift_list)
+            local_zeroth_key_list = [zeroth_key - z for z in shift_list]
             # discard all entries where the indices are negative or larger
             # than local_length
-            greater_than_lower_list = map(lambda z: z >= 0,
-                                          local_zeroth_key_list)
+            greater_than_lower_list = [z >= 0 for z in local_zeroth_key_list]
             # -> build up a list with the local selection d2o's
             local_length_list = self.comm.allgather(local_length)
-            less_than_upper_list = map(lambda z, zz: z < zz,
-                                       local_zeroth_key_list,
-                                       local_length_list)
-            local_selection_list = map(lambda z, zz: z * zz,
-                                       less_than_upper_list,
-                                       greater_than_lower_list)
-
-            for j in xrange(len(local_zeroth_key_list)):
+            less_than_upper_list = list(map(lambda z, zz: z < zz,
+                                            local_zeroth_key_list,
+                                            local_length_list))
+            local_selection_list = list(map(lambda z, zz: z * zz,
+                                            less_than_upper_list,
+                                            greater_than_lower_list))
+
+            for j in range(len(local_zeroth_key_list)):
                 temp_result = local_zeroth_key_list[j].\
                     get_data(local_selection_list[j]).\
                     get_full_data(target_rank=j)
@@ -1152,7 +1156,7 @@ class _slicing_distributor(distributor):
 #                   "ERROR: The first dimemnsion of list_key must be sorted!"))
 
             result = [result]
-            for ii in xrange(1, len(from_list_key)):
+            for ii in range(1, len(from_list_key)):
                 current = from_list_key[ii]
                 if np.isscalar(current):
                     result.append(current)
@@ -1161,7 +1165,7 @@ class _slicing_distributor(distributor):
                                    local_selection_list[rank],
                                    local_keys=True).get_local_data(copy=False))
                 else:
-                    for j in xrange(len(local_selection_list)):
+                    for j in range(len(local_selection_list)):
                         temp_select = local_selection_list[j].\
                             get_full_data(target_rank=j)
                         if j == rank:
@@ -1192,7 +1196,7 @@ class _slicing_distributor(distributor):
 #                raise ValueError(about_cstring(
 #                   "ERROR: The first dimemnsion of list_key must be sorted!"))
 
-            for ii in xrange(1, len(from_list_key)):
+            for ii in range(1, len(from_list_key)):
                 current = from_list_key[ii]
                 if np.isscalar(current):
                     result.append(current)
@@ -1270,21 +1274,23 @@ class _slicing_distributor(distributor):
                                global_length):
 
         # Reformulate negative indices
-        if slice_object.start < 0 and slice_object.start is not None:
-            temp_start = slice_object.start + global_length
-            if temp_start < 0:
-                temp_start = 0
+        if slice_object.start is not None:
+            if slice_object.start < 0:
+                temp_start = slice_object.start + global_length
+                if temp_start < 0:
+                    temp_start = 0
 
-            slice_object = slice(temp_start, slice_object.stop,
-                                 slice_object.step)
+                slice_object = slice(temp_start, slice_object.stop,
+                                     slice_object.step)
 
-        if slice_object.stop < 0 and slice_object.stop is not None:
-            temp_stop = slice_object.stop + global_length
-            if temp_stop < 0:
-                temp_stop = None
+        if slice_object.stop is not None:
+            if slice_object.stop < 0:
+                temp_stop = slice_object.stop + global_length
+                if temp_stop < 0:
+                    temp_stop = None
 
-            slice_object = slice(slice_object.start, temp_stop,
-                                 slice_object.step)
+                slice_object = slice(slice_object.start, temp_stop,
+                                     slice_object.step)
 
         # initialize the step
         if slice_object.step is None:
@@ -1530,10 +1536,10 @@ class _slicing_distributor(distributor):
         local_where[0] = local_where[0] + self.local_start
         local_where = tuple(local_where)
 
-        global_where = map(lambda z: distributed_data_object(
-                                             local_data=z,
-                                             distribution_strategy='freeform'),
-                           local_where)
+        global_where = \
+            [distributed_data_object(local_data=z,
+                                     distribution_strategy='freeform')
+             for z in local_where]
         return global_where
 
     def unique(self, data):
@@ -1552,7 +1558,7 @@ class _slicing_distributor(distributor):
                            [local_data_length_list, MPI.INT])
 
             global_unique_data = np.array([], dtype=self.dtype)
-            for i in xrange(size):
+            for i in range(size):
                 # broadcast data to the other nodes
                 # prepare the recv array
                 if rank != i:
@@ -2151,10 +2157,10 @@ class _not_distributor(distributor):
     def where(self, data):
         # compute the result from np.where
         local_where = np.where(data)
-        global_where = map(lambda z: distributed_data_object(
-                                                 global_data=z,
-                                                 distribution_strategy='not'),
-                           local_where)
+        global_where = \
+            [distributed_data_object(global_data=z,
+                                     distribution_strategy='not')
+             for z in local_where]
         return global_where
 
     def unique(self, data):
diff --git a/d2o/dtype_converter.py b/d2o/dtype_converter.py
index 6dbbe97..c8d8623 100644
--- a/d2o/dtype_converter.py
+++ b/d2o/dtype_converter.py
@@ -16,6 +16,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from builtins import map
+from builtins import object
 import numpy as np
 
 from d2o.config import configuration as gc,\
@@ -54,15 +56,17 @@ class _dtype_converter(object):
             [np.dtype('complex128'), MPI.DOUBLE_COMPLEX]]
 
         to_mpi_pre_dict = np.array(pre_dict)
-        to_mpi_pre_dict[:, 0] = map(self.dictionize_np, to_mpi_pre_dict[:, 0])
+        to_mpi_pre_dict[:, 0] = list(map(self.dictionize_np,
+                                         to_mpi_pre_dict[:, 0]))
         self._to_mpi_dict = dict(to_mpi_pre_dict)
 
         to_np_pre_dict = np.array(pre_dict)[:, ::-1]
-        to_np_pre_dict[:, 0] = map(self.dictionize_mpi, to_np_pre_dict[:, 0])
+        to_np_pre_dict[:, 0] = list(map(self.dictionize_mpi,
+                                        to_np_pre_dict[:, 0]))
         self._to_np_dict = dict(to_np_pre_dict)
 
     def dictionize_np(self, x):
-        dic = x.type.__dict__.items()
+        dic = list(x.type.__dict__.items())
         if x.type is np.float:
             dic[24] = 0
             dic[29] = 0
diff --git a/d2o/factory_methods.py b/d2o/factory_methods.py
index 294822e..4d8a08b 100644
--- a/d2o/factory_methods.py
+++ b/d2o/factory_methods.py
@@ -1,12 +1,13 @@
 # -*- coding: utf-8 -*-
 
+from __future__ import absolute_import
 import numpy as np
 
 from d2o.config import configuration as gc
 
-from distributed_data_object import distributed_data_object
+from .distributed_data_object import distributed_data_object
 
-from strategies import STRATEGIES
+from .strategies import STRATEGIES
 
 __all__ = ['arange']
 
diff --git a/d2o/slicing_generator.py b/d2o/slicing_generator.py
index 37428ed..c07a9c7 100644
--- a/d2o/slicing_generator.py
+++ b/d2o/slicing_generator.py
@@ -16,6 +16,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from builtins import next
+from builtins import range
 import itertools
 
 
@@ -52,7 +54,7 @@ def slicing_generator(shape, axes):
             raise ValueError("ERROR: axes(axis) does not match shape.")
         axes_select = [0 if x in axes else 1 for x, y in enumerate(shape)]
         axes_iterables =\
-            [range(y) for x, y in enumerate(shape) if x not in axes]
+            [list(range(y)) for x, y in enumerate(shape) if x not in axes]
         for current_index in itertools.product(*axes_iterables):
             it_iter = iter(current_index)
             slice_list = [next(it_iter) if use_axis else
diff --git a/test/test_distributed_data_object.py b/test/test_distributed_data_object.py
index a7f909d..f2c1fd3 100644
--- a/test/test_distributed_data_object.py
+++ b/test/test_distributed_data_object.py
@@ -1,3 +1,5 @@
+from __future__ import division
+from __future__ import print_function
 # D2O
 # Copyright (C) 2016  Theo Steininger
 #
@@ -16,6 +18,11 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from builtins import str
+from builtins import range
+
+from future.standard_library import PY2, PY3
+
 from numpy.testing import assert_equal,\
     assert_almost_equal,\
     assert_raises,\
@@ -86,12 +93,19 @@ hdf5_distribution_strategies = STRATEGIES['hdf5']
 ###############################################################################
 
 binary_non_inplace_operators = ['__add__', '__radd__', '__sub__', '__rsub__',
-                                '__div__', '__truediv__', '__rdiv__',
-                                '__rtruediv__', '__floordiv__',
+                                '__truediv__', '__rtruediv__', '__floordiv__',
                                 '__rfloordiv__', '__mul__', '__rmul__',
                                 '__pow__', '__rpow__']
-binary_inplace_operators = ['__iadd__', '__isub__', '__idiv__', '__itruediv__',
+
+if PY2:
+    binary_non_inplace_operators += ['__div__', '__rdiv__']
+
+binary_inplace_operators = ['__iadd__', '__isub__', '__itruediv__',
                             '__ifloordiv__', '__imul__', '__ipow__']
+if PY2:
+    binary_inplace_operators += ['__idiv__']
+
+
 comparison_operators = ['__ne__', '__lt__', '__le__', '__eq__', '__ge__',
                         '__gt__', ]
 
@@ -262,13 +276,12 @@ class Test_Globaltype_Initialization(unittest.TestCase):
          (), np.dtype('float64')],
     ], global_distribution_strategies),
         testcase_func_name=custom_name_func)
-    def test_special_init_cases(self,
-                                (global_data,
-                                 global_shape,
-                                 dtype,
-                                 expected_shape,
-                                 expected_dtype),
-                                distribution_strategy):
+    def test_special_init_cases(self, para, distribution_strategy):
+        (global_data,
+         global_shape,
+         dtype,
+         expected_shape,
+         expected_dtype) = para
         obj = distributed_data_object(
                                   global_data=global_data,
                                   global_shape=global_shape,
@@ -283,7 +296,8 @@ class Test_Globaltype_Initialization(unittest.TestCase):
         @parameterized.expand(itertools.product(hdf5_test_paths,
                                                 hdf5_distribution_strategies),
                               testcase_func_name=custom_name_func)
-        def test_hdf5_init(self, (alias, path), distribution_strategy):
+        def test_hdf5_init(self, para, distribution_strategy):
+            (alias, path) = para
             obj = distributed_data_object(
                                   global_data=1.,
                                   global_shape=(12, 6),
@@ -303,12 +317,12 @@ class Test_Globaltype_Initialization(unittest.TestCase):
                 (None, None, np.int_, None, (3,))],
             global_distribution_strategies),
         testcase_func_name=custom_name_func)
-    def test_failed_init_on_unsufficient_parameters(self,
-                                                    (global_data,
-                                                     global_shape,
-                                                     dtype,
-                                                     local_data, local_shape),
+    def test_failed_init_on_unsufficient_parameters(self, para,
                                                     distribution_strategy):
+        (global_data,
+         global_shape,
+         dtype,
+         local_data, local_shape) = para
         assert_raises(ValueError,
                       lambda: distributed_data_object(
                           global_data=global_data,
@@ -329,13 +343,13 @@ class Test_Globaltype_Initialization(unittest.TestCase):
                   None, None), ],
                 global_distribution_strategies),
             testcase_func_name=custom_name_func)
-        def test_failed_init_unsufficient_params_mpi(self,
-                                                     (global_data,
-                                                      global_shape,
-                                                      dtype,
-                                                      local_data,
-                                                      local_shape),
+        def test_failed_init_unsufficient_params_mpi(self, para,
                                                      distribution_strategy):
+            (global_data,
+             global_shape,
+             dtype,
+             local_data,
+             local_shape) = para
             assert_raises(ValueError,
                           lambda: distributed_data_object(
                               global_data=global_data,
@@ -481,13 +495,13 @@ class Test_Localtype_Initialization(unittest.TestCase):
          np.int, (2 * size, 2), np.int]
     ], local_distribution_strategies),
         testcase_func_name=custom_name_func)
-    def test_special_init_cases(self,
-                                (local_data,
-                                 local_shape,
-                                 dtype,
-                                 expected_shape,
-                                 expected_dtype),
+    def test_special_init_cases(self, para,
                                 distribution_strategy):
+        (local_data,
+         local_shape,
+         dtype,
+         expected_shape,
+         expected_dtype) = para
         obj = distributed_data_object(
                                   local_data=local_data,
                                   local_shape=local_shape,
@@ -532,13 +546,13 @@ class Test_Localtype_Initialization(unittest.TestCase):
                 (None, (4, 4), np.int_, None, None)],
             local_distribution_strategies),
         testcase_func_name=custom_name_func)
-    def test_failed_init_on_unsufficient_parameters(self,
-                                                    (global_data,
-                                                     global_shape,
-                                                     dtype,
-                                                     local_data,
-                                                     local_shape),
+    def test_failed_init_on_unsufficient_parameters(self, para,
                                                     distribution_strategy):
+        (global_data,
+         global_shape,
+         dtype,
+         local_data,
+         local_shape) = para
         assert_raises(ValueError,
                       lambda: distributed_data_object(
                           global_data=global_data,
@@ -561,13 +575,13 @@ class Test_Localtype_Initialization(unittest.TestCase):
                   None, (2, 2))],
                 local_distribution_strategies),
             testcase_func_name=custom_name_func)
-        def test_failed_init_unsufficient_params_mpi(self,
-                                                     (global_data,
-                                                      global_shape,
-                                                      dtype,
-                                                      local_data,
-                                                      local_shape),
+        def test_failed_init_unsufficient_params_mpi(self, para,
                                                      distribution_strategy):
+            (global_data,
+             global_shape,
+             dtype,
+             local_data,
+             local_shape) = para
             assert_raises(ValueError,
                           lambda: distributed_data_object(
                               global_data=global_data,
@@ -646,7 +660,8 @@ class Test_set_get_full_and_local_data(unittest.TestCase):
         @parameterized.expand(
             itertools.product(hdf5_test_paths, hdf5_distribution_strategies),
             testcase_func_name=custom_name_func)
-        def test_loading_hdf5_file(self, (alias, path), distribution_strategy):
+        def test_loading_hdf5_file(self, para, distribution_strategy):
+            (alias, path) = para
             a = np.arange(13 * 7).reshape((13, 7)).astype(np.float)
             b = a[::-1, ::-1]
             a = a + 1j * b
@@ -1034,10 +1049,10 @@ class Test_non_local_keys(unittest.TestCase):
         obj.set_data(local_data_update, local_scalar_key, local_keys=True)
         assert_equal(obj.get_full_data(), a)
 
-        local_data_update_list = [np.ones((8,)) * (z**2) for z in xrange(size)]
-        local_data_update_list = map(lambda z: distributed_data_object(
-                                        z, distribution_strategy='equal'),
-                                     local_data_update_list)
+        local_data_update_list = [np.ones((8,)) * (z**2) for z in range(size)]
+        local_data_update_list = \
+            [distributed_data_object(z, distribution_strategy='equal')
+             for z in local_data_update_list]
         obj = obj_backup.copy()
         obj.set_data(local_data_update_list[rank], local_scalar_key,
                      local_keys=True)
@@ -1072,9 +1087,12 @@ class Test_set_data_via_injection(unittest.TestCase):
         ],
             all_distribution_strategies
         ), testcase_func_name=custom_name_func)
-    def test_set_data_via_injection(self, (global_shape_1, slice_tuple_1,
-                                           global_shape_2, slice_tuple_2),
+    def test_set_data_via_injection(self, para,
                                     distribution_strategy):
+        (global_shape_1,
+         slice_tuple_1,
+         global_shape_2,
+         slice_tuple_2) = para
         dtype = np.dtype('float')
         (a, obj) = generate_data(global_shape_1, dtype,
                                  distribution_strategy)
@@ -1188,8 +1206,9 @@ class Test_copy_and_copy_empty(unittest.TestCase):
             (lambda x: x * x, True, None),
             (lambda x: x * x, True, np.int),
         ], all_distribution_strategies), testcase_func_name=custom_name_func)
-    def test_apply_scalar_function(self, (square_function, inplace, dtype),
+    def test_apply_scalar_function(self, para,
                                    distribution_strategy):
+        (square_function, inplace, dtype) = para
         global_shape = (8, 8)
         old_dtype = np.float64
         (a, obj) = generate_data(global_shape, old_dtype,
@@ -1565,13 +1584,13 @@ class Test_contractions(unittest.TestCase):
                           all_distribution_strategies
                           ))
     def test_argmin_argmax(self, dtype, distribution_strategy):
-        print (dtype, distribution_strategy)
+        print((dtype, distribution_strategy))
         global_shape = (8, 8)
         (a, obj) = generate_data(global_shape, dtype,
                                  distribution_strategy,
                                  strictly_positive=True)
         o_full = obj.get_full_data()
-        print (a, o_full)
+        print((a, o_full))
         assert_equal(obj.argmax(), np.argmax(a))
         assert_equal(obj.argmin(), np.argmin(a))
         assert_equal(obj.argmin_nonflat(),
@@ -1709,7 +1728,7 @@ class Test_special_methods(unittest.TestCase):
         b = ((a < 4) + (a > 30))
         p = ((obj < 4) + (obj > 30))
 
-        assert_equal(map(lambda z: z.get_full_data(), p.where()), np.where(b))
+        assert_equal([z.get_full_data() for z in p.where()], np.where(b))
 
 ###############################################################################
 
@@ -1812,7 +1831,7 @@ class Test_axis(unittest.TestCase):
                               (axis=axis))
         else:
             if axis in [(1, ), (0, 1)] and global_shape == (0,):
-                assert_raises(StandardError, lambda: getattr(obj, function)
+                assert_raises(Exception, lambda: getattr(obj, function)
                               (axis=axis))
             else:
                 assert_almost_equal(getattr(obj, function)(axis=axis),
-- 
GitLab