File 0002-Update-deprecated-imports-xrange-unicode-to-Python3.patch of Package horus

From f0cb9c05a6ec10f797d8a82404281bd50b9edf03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
Date: Sun, 20 Feb 2022 06:04:44 +0100
Subject: [PATCH 2/4] Update deprecated imports, xrange, unicode to Python3

---
 .../engine/algorithms/laser_segmentation.py   |  4 +-
 .../engine/algorithms/point_cloud_roi.py      |  4 +-
 src/horus/engine/calibration/autocheck.py     |  6 +-
 .../engine/calibration/calibration_data.py    |  4 +-
 .../engine/calibration/camera_intrinsics.py   |  2 +-
 .../engine/calibration/combo_calibration.py   |  8 +-
 .../engine/calibration/laser_triangulation.py | 10 +-
 src/horus/engine/driver/board.py              |  4 +-
 src/horus/engine/driver/camera.py             |  6 +-
 src/horus/engine/scan/ciclop_scan.py          |  8 +-
 src/horus/engine/scan/current_video.py        |  2 +-
 src/horus/gui/main.py                         | 16 ++--
 src/horus/gui/util/custom_panels.py           |  6 +-
 src/horus/gui/util/opengl_gui.py              | 10 +-
 src/horus/gui/util/opengl_helpers.py          | 10 +-
 src/horus/gui/util/scene_view.py              |  4 +-
 src/horus/gui/wizard/connection_page.py       | 24 ++---
 .../gui/workbench/adjustment/current_video.py |  4 +-
 .../calibration/pages/camera_intrinsics.py    |  2 +-
 .../calibration/pages/capture_page.py         |  4 +-
 .../calibration/pages/laser_triangulation.py  |  2 +-
 .../calibration/pages/platform_extrinsics.py  |  2 +-
 .../calibration/pages/scanner_autocheck.py    |  2 +-
 src/horus/gui/workbench/scanning/panels.py    |  2 +-
 src/horus/gui/workbench/toolbar.py            | 16 ++--
 src/horus/gui/workbench/workbench.py          |  4 +-
 src/horus/util/avr_helpers.py                 |  2 +-
 src/horus/util/mesh_loaders/ply.py            |  4 +-
 src/horus/util/mesh_loaders/stl.py            |  2 +-
 src/horus/util/model.py                       |  4 +-
 src/horus/util/profile.py                     | 93 +++++++++----------
 src/horus/util/resources.py                   |  2 +-
 src/horus/util/version.py                     |  6 +-
 33 files changed, 139 insertions(+), 140 deletions(-)

diff --git a/src/horus/engine/algorithms/laser_segmentation.py b/src/horus/engine/algorithms/laser_segmentation.py
index c366537..d8afa3d 100644
--- a/src/horus/engine/algorithms/laser_segmentation.py
+++ b/src/horus/engine/algorithms/laser_segmentation.py
@@ -121,7 +121,7 @@ class LaserSegmentation(object):
                 _min = peak - self.window_value
                 _max = peak + self.window_value + 1
                 mask = np.zeros_like(image)
-                for i in xrange(self.calibration_data.height):
+                for i in range(self.calibration_data.height):
                     mask[i, _min[i]:_max[i]] = 255
                 # Apply mask
                 image = cv2.bitwise_and(image, mask)
@@ -211,7 +211,7 @@ class LaserSegmentation(object):
         best_inlier_num = 0
         best_inliers = None
         data_idx = np.arange(data.shape[0])
-        for _ in xrange(max_trials):
+        for _ in range(max_trials):
             sample = data[np.random.randint(0, data.shape[0], 2)]
             if model_class.is_degenerate(sample):
                 continue
diff --git a/src/horus/engine/algorithms/point_cloud_roi.py b/src/horus/engine/algorithms/point_cloud_roi.py
index c8423cd..8ec88db 100644
--- a/src/horus/engine/algorithms/point_cloud_roi.py
+++ b/src/horus/engine/algorithms/point_cloud_roi.py
@@ -40,9 +40,9 @@ class PointCloudROI(object):
         self._center_v = 0
         self._circle_resolution = 30
         self._circle_array = np.array([[np.cos(i * 2 * np.pi / self._circle_resolution)
-                                        for i in xrange(self._circle_resolution)],
+                                        for i in range(self._circle_resolution)],
                                        [np.sin(i * 2 * np.pi / self._circle_resolution)
-                                        for i in xrange(self._circle_resolution)],
+                                        for i in range(self._circle_resolution)],
                                        np.zeros(self._circle_resolution)])
 
     def set_diameter(self, value):
diff --git a/src/horus/engine/calibration/autocheck.py b/src/horus/engine/calibration/autocheck.py
index 2257de8..facf9fd 100644
--- a/src/horus/engine/calibration/autocheck.py
+++ b/src/horus/engine/calibration/autocheck.py
@@ -100,7 +100,7 @@ class Autocheck(Calibration):
             self._progress_callback(0)
 
         # Capture data
-        for i in xrange(0, 360, scan_step):
+        for i in range(0, 360, scan_step):
             self.current_angle = i
             if not self._is_calibrating:
                 raise CalibrationCancel()
@@ -123,7 +123,7 @@ class Autocheck(Calibration):
         max_x = max(patterns_detected.values())
         max_i = [key for key, value in patterns_detected.items() if value == max_x][0]
         min_v = max_x
-        for i in xrange(max_i, max_i + 360, scan_step):
+        for i in range(max_i, max_i + 360, scan_step):
             if i % 360 in patterns_detected:
                 v = patterns_detected[i % 360]
                 patterns_sorted[i] = v
@@ -146,7 +146,7 @@ class Autocheck(Calibration):
         image = self.image_capture.capture_pattern()
         corners = self.image_detection.detect_corners(image)
         self.image_capture.flush_laser()
-        for i in xrange(2):
+        for i in range(2):
             if not self._is_calibrating:
                 raise CalibrationCancel()
             image = self.image_capture.capture_laser(i)
diff --git a/src/horus/engine/calibration/calibration_data.py b/src/horus/engine/calibration/calibration_data.py
index e98315d..b44d0ee 100644
--- a/src/horus/engine/calibration/calibration_data.py
+++ b/src/horus/engine/calibration/calibration_data.py
@@ -6,7 +6,7 @@ __copyright__ = 'Copyright (C) 2014-2016 Mundo Reader S.L.'
 __license__ = 'GNU General Public License v2 http://www.gnu.org/licenses/gpl2.html'
 
 
-import md5
+import hashlib
 import cv2
 import numpy as np
 
@@ -80,7 +80,7 @@ class CalibrationData(object):
             self._dist_camera_matrix, self._roi = cv2.getOptimalNewCameraMatrix(
                 self._camera_matrix, self._distortion_vector,
                 (int(self.width), int(self.height)), alpha=1)
-            self._md5_hash = md5.new()
+            self._md5_hash = hashlib.md5()
             self._md5_hash.update(self._camera_matrix)
             self._md5_hash.update(self._distortion_vector)
             self._md5_hash = self._md5_hash.hexdigest()
diff --git a/src/horus/engine/calibration/camera_intrinsics.py b/src/horus/engine/calibration/camera_intrinsics.py
index 8af5186..ddf9ae4 100644
--- a/src/horus/engine/calibration/camera_intrinsics.py
+++ b/src/horus/engine/calibration/camera_intrinsics.py
@@ -68,7 +68,7 @@ class CameraIntrinsics(Calibration):
 
         if ret:
             # Compute calibration error
-            for i in xrange(len(self.object_points)):
+            for i in range(len(self.object_points)):
                 imgpoints2, _ = cv2.projectPoints(
                     self.object_points[i], rvecs[i], tvecs[i], cmat, dvec)
                 error += cv2.norm(self.image_points[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)
diff --git a/src/horus/engine/calibration/combo_calibration.py b/src/horus/engine/calibration/combo_calibration.py
index 7a71d85..b510567 100644
--- a/src/horus/engine/calibration/combo_calibration.py
+++ b/src/horus/engine/calibration/combo_calibration.py
@@ -53,7 +53,7 @@ class ComboCalibration(MovingCalibration):
             alpha = np.rad2deg(math.acos(normal[2])) * math.copysign(1, normal[0])
             if abs(alpha) < 30:
                 self.image_capture.flush_laser(14)
-                for i in xrange(2):
+                for i in range(2):
                     if (i == 0 and alpha < 10) or (i == 1 and alpha > -10):
                         image = self.image_capture.capture_laser(i)
                         image = self.image_detection.pattern_mask(image, corners)
@@ -87,7 +87,7 @@ class ComboCalibration(MovingCalibration):
 
         # Laser triangulation
         # Save point clouds
-        for i in xrange(2):
+        for i in range(2):
             laser_triangulation.save_point_cloud('PC' + str(i) + '.ply', self._point_cloud[i])
 
         self.distance = [None, None]
@@ -95,7 +95,7 @@ class ComboCalibration(MovingCalibration):
         self.std = [None, None]
 
         # Compute planes
-        for i in xrange(2):
+        for i in range(2):
             if self._is_calibrating:
                 plane = laser_triangulation.compute_plane(i, self._point_cloud[i])
                 self.distance[i], self.normal[i], self.std[i] = plane
@@ -152,7 +152,7 @@ class ComboCalibration(MovingCalibration):
         return response
 
     def accept(self):
-        for i in xrange(2):
+        for i in range(2):
             self.calibration_data.laser_planes[i].distance = self.distance[i]
             self.calibration_data.laser_planes[i].normal = self.normal[i]
         self.calibration_data.platform_rotation = self.R
diff --git a/src/horus/engine/calibration/laser_triangulation.py b/src/horus/engine/calibration/laser_triangulation.py
index 90753f6..ea9a4ac 100644
--- a/src/horus/engine/calibration/laser_triangulation.py
+++ b/src/horus/engine/calibration/laser_triangulation.py
@@ -55,7 +55,7 @@ class LaserTriangulation(MovingCalibration):
             alpha = np.rad2deg(math.acos(normal[2])) * math.copysign(1, normal[0])
             if abs(alpha) < 30:
                 self.image_capture.flush_laser(14)
-                for i in xrange(2):
+                for i in range(2):
                     if (i == 0 and alpha < 10) or (i == 1 and alpha > -10):
                         image = self.image_capture.capture_laser(i)
                         image = self.image_detection.pattern_mask(image, corners)
@@ -78,7 +78,7 @@ class LaserTriangulation(MovingCalibration):
         self.image_capture.stream = True
 
         # Save point clouds
-        for i in xrange(2):
+        for i in range(2):
             save_point_cloud('PC' + str(i) + '.ply', self._point_cloud[i])
 
         self.distance = [None, None]
@@ -86,7 +86,7 @@ class LaserTriangulation(MovingCalibration):
         self.std = [None, None]
 
         # Compute planes
-        for i in xrange(2):
+        for i in range(2):
             if self._is_calibrating:
                 plane = compute_plane(i, self._point_cloud[i])
                 self.distance[i], self.normal[i], self.std[i] = plane
@@ -107,7 +107,7 @@ class LaserTriangulation(MovingCalibration):
         return response
 
     def accept(self):
-        for i in xrange(2):
+        for i in range(2):
             self.calibration_data.laser_planes[i].distance = self.distance[i]
             self.calibration_data.laser_planes[i].normal = self.normal[i]
 
@@ -165,7 +165,7 @@ def ransac(data, model_class, min_samples, threshold, max_trials=500):
     best_inlier_num = 0
     best_inliers = None
     data_idx = np.arange(data.shape[0])
-    for _ in xrange(max_trials):
+    for _ in range(max_trials):
         sample = data[np.random.randint(0, data.shape[0], 3)]
         if model_class.is_degenerate(sample):
             continue
diff --git a/src/horus/engine/driver/board.py b/src/horus/engine/driver/board.py
index bc8a368..ac0e332 100644
--- a/src/horus/engine/driver/board.py
+++ b/src/horus/engine/driver/board.py
@@ -174,11 +174,11 @@ class Board(object):
                 self._send_command("M70T" + str(index + 1))
 
     def lasers_on(self):
-        for i in xrange(self._laser_number):
+        for i in range(self._laser_number):
             self.laser_on(i)
 
     def lasers_off(self):
-        for i in xrange(self._laser_number):
+        for i in range(self._laser_number):
             self.laser_off(i)
 
     def ldr_sensor(self, pin):
diff --git a/src/horus/engine/driver/camera.py b/src/horus/engine/driver/camera.py
index 02b6cd5..ca937c1 100644
--- a/src/horus/engine/driver/camera.py
+++ b/src/horus/engine/driver/camera.py
@@ -196,7 +196,7 @@ class Camera(object):
                         e = time.time()
                 else:
                     if flush > 0:
-                        for i in xrange(flush):
+                        for i in range(flush):
                             self._capture.read()
                             # Note: Windows needs read() to perform
                             #       the flush instead of grab()
@@ -387,7 +387,7 @@ class Camera(object):
         return ret
 
     def _count_cameras(self):
-        for i in xrange(5):
+        for i in range(5):
             cap = cv2.VideoCapture(i)
             res = not cap.isOpened()
             cap.release()
@@ -400,7 +400,7 @@ class Camera(object):
         if system == 'Windows':
             if not self._is_connected:
                 count = self._count_cameras()
-                for i in xrange(count):
+                for i in range(count):
                     baselist.append(str(i))
                 self._video_list = baselist
         elif system == 'Darwin':
diff --git a/src/horus/engine/scan/ciclop_scan.py b/src/horus/engine/scan/ciclop_scan.py
index 4e87a22..f5bd9df 100644
--- a/src/horus/engine/scan/ciclop_scan.py
+++ b/src/horus/engine/scan/ciclop_scan.py
@@ -6,7 +6,7 @@ __copyright__ = 'Copyright (C) 2014-2016 Mundo Reader S.L.'
 __license__ = 'GNU General Public License v2 http://www.gnu.org/licenses/gpl2.html'
 
 import time
-import Queue
+import queue
 import numpy as np
 import datetime
 
@@ -54,7 +54,7 @@ class CiclopScan(Scan):
         self._debug = False
         self._bicolor = False
         self._scan_sleep = 0.05
-        self._captures_queue = Queue.Queue(10)
+        self._captures_queue = queue.Queue(10)
         self.point_cloud_callback = None
 
     def set_capture_texture(self, value):
@@ -191,7 +191,7 @@ class CiclopScan(Scan):
         if self.laser[0] and self.laser[1]:
             capture.lasers = self.image_capture.capture_lasers()
         else:
-            for i in xrange(2):
+            for i in range(2):
                 if self.laser[i]:
                     capture.lasers[i] = self.image_capture.capture_laser(i)
 
@@ -252,7 +252,7 @@ class CiclopScan(Scan):
 
         # begin = time.time()
 
-        for i in xrange(2):
+        for i in range(2):
             if capture.lasers[i] is not None:
                 image = capture.lasers[i]
                 self.image = image
diff --git a/src/horus/engine/scan/current_video.py b/src/horus/engine/scan/current_video.py
index 08b5059..bda7f27 100644
--- a/src/horus/engine/scan/current_video.py
+++ b/src/horus/engine/scan/current_video.py
@@ -38,7 +38,7 @@ class CurrentVideo(object):
     def set_line(self, points, image):
         images = [None, None]
         if image is not None:
-            for i in xrange(2):
+            for i in range(2):
                 if points[i]:
                     images[i] = self._compute_line_image(points[i], image)
             image = self._combine_images(images)
diff --git a/src/horus/gui/main.py b/src/horus/gui/main.py
index 953b2c1..eff9bef 100644
--- a/src/horus/gui/main.py
+++ b/src/horus/gui/main.py
@@ -323,12 +323,12 @@ class MainWindow(wx.Frame):
         if status:
             self.toolbar.toolbar.Enable()
             self.toolbar.combo.Enable()
-            for i in xrange(self.menu_bar.GetMenuCount()):
+            for i in range(self.menu_bar.GetMenuCount()):
                 self.menu_bar.EnableTop(i, True)
         else:
             self.toolbar.toolbar.Disable()
             self.toolbar.combo.Disable()
-            for i in xrange(self.menu_bar.GetMenuCount()):
+            for i in range(self.menu_bar.GetMenuCount()):
                 self.menu_bar.EnableTop(i, False)
 
     def append_last_file(self, last_file):
@@ -442,18 +442,18 @@ class MainWindow(wx.Frame):
         self.wait_cursor = wx.BusyCursor()
         self.toolbar.combo.SetValue(name)
         if sys.is_windows():
-            for key, wb in self.workbench.iteritems():
+            for key, wb in self.workbench.items():
                 if wb.name == name:
                     wb.Show()
                     profile.settings['workbench'] = key
-            for key, wb in self.workbench.iteritems():
+            for key, wb in self.workbench.items():
                 if wb.name != name:
                     wb.Hide()
         else:
-            for key, wb in self.workbench.iteritems():
+            for key, wb in self.workbench.items():
                 if wb.name != name:
                     wb.Hide()
-            for key, wb in self.workbench.iteritems():
+            for key, wb in self.workbench.items():
                 if wb.name == name:
                     wb.Show()
                     profile.settings['workbench'] = key
@@ -541,7 +541,7 @@ class MainWindow(wx.Frame):
         dlg.Destroy()
 
     def update_profile_to_all_controls(self):
-        for _, w in self.workbench.iteritems():
+        for _, w in self.workbench.items():
             w.update_controls()
         self.workbench[profile.settings['workbench']].update_controls()
 
@@ -596,7 +596,7 @@ class MainWindow(wx.Frame):
         current_video_id = profile.settings['camera_id']
         if len(video_list) > 0:
             if current_video_id not in video_list:
-                profile.settings['camera_id'] = unicode(video_list[0])
+                profile.settings['camera_id'] = str(video_list[0])
 
         if len(profile.settings['camera_id']):
             driver.camera.camera_id = int(profile.settings['camera_id'][-1:])
diff --git a/src/horus/gui/util/custom_panels.py b/src/horus/gui/util/custom_panels.py
index 7c19596..2c32deb 100644
--- a/src/horus/gui/util/custom_panels.py
+++ b/src/horus/gui/util/custom_panels.py
@@ -31,9 +31,9 @@ class ExpandableCollection(wx.Panel):
         self.vbox.Add(panel, 0, wx.ALL ^ wx.TOP | wx.EXPAND, 3)
 
     def init_panels_layout(self):
-        values = self.expandable_panels.values()
-        if len(values) > 0:
-            self._expand_callback(values[0])
+        if len(self.expandable_panels) > 0:
+            [first_k, first_v] = next(iter(self.expandable_panels.items()))
+            self._expand_callback(first_v)
 
     def _expand_callback(self, selected_panel):
         if sys.is_windows():
diff --git a/src/horus/gui/util/opengl_gui.py b/src/horus/gui/util/opengl_gui.py
index 2b8d772..3d08c73 100644
--- a/src/horus/gui/util/opengl_gui.py
+++ b/src/horus/gui/util/opengl_gui.py
@@ -64,19 +64,19 @@ class glGuiControl(object):
 
     def focus_next(self):
         control_list = self._parent._gl_gui_control_list
-        for n in xrange(control_list.index(self) + 1, len(control_list)):
+        for n in range(control_list.index(self) + 1, len(control_list)):
             if self._parent._gl_gui_control_list[n].setFocus():
                 return
-        for n in xrange(0, control_list.index(self)):
+        for n in range(0, control_list.index(self)):
             if self._parent._gl_gui_control_list[n].setFocus():
                 return
 
     def focus_previous(self):
         control_list = self._parent._gl_gui_control_list
-        for n in xrange(control_list.index(self) - 1, -1, -1):
+        for n in range(control_list.index(self) - 1, -1, -1):
             if self._parent._gl_gui_control_list[n].setFocus():
                 return
-        for n in xrange(len(control_list) - 1, control_list.index(self), -1):
+        for n in range(len(control_list) - 1, control_list.index(self), -1):
             if self._parent._gl_gui_control_list[n].setFocus():
                 return
 
@@ -235,7 +235,7 @@ class glGuiPanel(glcanvas.GLCanvas):
             errStr = _("An error occurred during the 3D view drawing.")
             tb = traceback.extract_tb(sys.exc_info()[2])
             errStr += "\n%s: '%s'" % (str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]))
-            for n in xrange(len(tb) - 1, -1, -1):
+            for n in range(len(tb) - 1, -1, -1):
                 locationInfo = tb[n]
                 errStr += "\n @ %s:%s:%d" % (
                     os.path.basename(locationInfo[0]), locationInfo[2], locationInfo[1])
diff --git a/src/horus/gui/util/opengl_helpers.py b/src/horus/gui/util/opengl_helpers.py
index ff9e534..3bca826 100755
--- a/src/horus/gui/util/opengl_helpers.py
+++ b/src/horus/gui/util/opengl_helpers.py
@@ -245,7 +245,7 @@ class GLVBO(GLReferenceCounter):
             batch_size = 996
             extra_start_pos = int(self._size / batch_size) * batch_size  # leftovers.
             extra_count = self._size - extra_start_pos
-            for i in xrange(0, int(self._size / batch_size)):
+            for i in range(0, int(self._size / batch_size)):
                 glDrawArrays(self._render_type, i * batch_size, batch_size)
             glDrawArrays(self._render_type, extra_start_pos, extra_count)
 
@@ -301,7 +301,7 @@ def unproject(winx, winy, winz, model_matrix, proj_matrix, viewport):
     final_matrix = np_model_matrix * np_proj_matrix
     final_matrix = numpy.linalg.inv(final_matrix)
 
-    viewport = map(float, viewport)
+    viewport = list(map(float, viewport))
     if viewport[2] > 0 and viewport[3] > 0:
         vector = numpy.array([(winx - viewport[0]) / viewport[2] * 2.0 - 1.0,
                               (winy - viewport[1]) / viewport[3] * 2.0 - 1.0,
@@ -325,9 +325,9 @@ def load_gl_texture(filename):
     rgb_data = img.GetData()
     alpha_data = img.GetAlphaData()
     if alpha_data is not None:
-        data = ''
-        for i in xrange(0, len(alpha_data)):
-            data += rgb_data[i * 3:i * 3 + 3] + alpha_data[i]
+        data = b''
+        for i in range(0, len(alpha_data)):
+            data += rgb_data[i * 3:i * 3 + 3] + bytes([alpha_data[i]])
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(),
                      img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data)
     else:
diff --git a/src/horus/gui/util/scene_view.py b/src/horus/gui/util/scene_view.py
index fe2f3cc..1221a19 100644
--- a/src/horus/gui/util/scene_view.py
+++ b/src/horus/gui/util/scene_view.py
@@ -110,7 +110,7 @@ class SceneView(opengl_gui.glGuiPanel):
         # TODO: optimize
         if self._object is not None:
             if self._object._mesh is not None:
-                for i in xrange(point.shape[1]):
+                for i in range(point.shape[1]):
                     self._object._mesh._add_vertex(
                         point[0][i], point[1][i], point[2][i],
                         color[0][i], color[1][i], color[2][i])
@@ -646,7 +646,7 @@ class SceneView(opengl_gui.glGuiPanel):
 
             # Draw the sides of the build volume.
             glBegin(GL_QUADS)
-            for n in xrange(0, len(polys[0])):
+            for n in range(0, len(polys[0])):
                 if machine_shape == 'Rectangular':
                     if n % 2 == 0:
                         glColor4ub(5, 171, 231, 96)
diff --git a/src/horus/gui/wizard/connection_page.py b/src/horus/gui/wizard/connection_page.py
index 07219da..f4d7429 100644
--- a/src/horus/gui/wizard/connection_page.py
+++ b/src/horus/gui/wizard/connection_page.py
@@ -104,7 +104,7 @@ class ConnectionPage(WizardPage):
             current_video_id = profile.settings['camera_id']
             if len(video_list) > 0:
                 if current_video_id not in video_list:
-                    profile.settings['camera_id'] = unicode(video_list[0])
+                    profile.settings['camera_id'] = str(video_list[0])
                     driver.camera.camera_id = int(profile.settings['camera_id'][-1:])
 
             driver.set_callbacks(
@@ -131,7 +131,7 @@ class ConnectionPage(WizardPage):
                     self,
                     _("The board has the wrong firmware or an invalid baud rate.\n"
                       "Please select your board and press \"Upload firmware\""),
-                    _(result), wx.OK | wx.ICON_INFORMATION)
+                    _(str(result)), wx.OK | wx.ICON_INFORMATION)
                 dlg.ShowModal()
                 dlg.Destroy()
                 self.update_status(False)
@@ -141,7 +141,7 @@ class ConnectionPage(WizardPage):
                     self,
                     _("The board is not connected.\n"
                       "Please connect your board and select a valid Serial name"),
-                    _(result), wx.OK | wx.ICON_INFORMATION)
+                    _(str(result)), wx.OK | wx.ICON_INFORMATION)
                 dlg.ShowModal()
                 dlg.Destroy()
                 self.update_status(False)
@@ -151,7 +151,7 @@ class ConnectionPage(WizardPage):
                     self,
                     _("The board has and old firmware.\n"
                       "Please select your board and press \"Upload firmware\""),
-                    _(result), wx.OK | wx.ICON_INFORMATION)
+                    _(str(result)), wx.OK | wx.ICON_INFORMATION)
                 dlg.ShowModal()
                 dlg.Destroy()
                 self.update_status(False)
@@ -161,7 +161,7 @@ class ConnectionPage(WizardPage):
                     self,
                     _("You probably have selected the wrong camera.\n"
                       "Please select another Camera ID"),
-                    _(result), wx.OK | wx.ICON_INFORMATION)
+                    _(str(result)), wx.OK | wx.ICON_INFORMATION)
                 dlg.ShowModal()
                 dlg.Destroy()
                 self.update_status(False)
@@ -173,13 +173,13 @@ class ConnectionPage(WizardPage):
             elif isinstance(result, CameraNotConnected):
                 dlg = wx.MessageDialog(
                     self, _("Please plug your camera in and try to connect again"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
             elif isinstance(result, InvalidVideo):
                 dlg = wx.MessageDialog(
                     self, _("Unplug and plug your camera USB cable and try to connect again"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
             elif isinstance(result, WrongDriver):
@@ -187,7 +187,7 @@ class ConnectionPage(WizardPage):
                     dlg = wx.MessageDialog(
                         self, _("Please, download and install the camera driver: \n"
                                 "http://support.logitech.com/en_us/product/hd-webcam-c270"),
-                        _(result), wx.OK | wx.ICON_ERROR)
+                        _(str(result)), wx.OK | wx.ICON_ERROR)
                     dlg.ShowModal()
                     dlg.Destroy()
 
@@ -238,21 +238,21 @@ class ConnectionPage(WizardPage):
             dlg.ShowModal()
             dlg.Destroy()
         else:
-            self.result_label.SetLabel(str(_(result)))
+            self.result_label.SetLabel(_str(result))
             if isinstance(result, PatternNotDetected):
                 dlg = wx.MessageDialog(
                     self, _("Please, put the pattern on the platform. "
                             "Also you can set up the calibration's capture "
                             "settings in the \"Adjustment workbench\" "
                             "until the pattern is detected correctly"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
             elif isinstance(result, WrongMotorDirection):
                 dlg = wx.MessageDialog(
                     self, _(
                         "Please, select \"Invert the motor direction\" in the preferences"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
                 self.GetParent().parent.launch_preferences(basic=True)
@@ -262,7 +262,7 @@ class ConnectionPage(WizardPage):
                             "Also you can set up the calibration's capture and "
                             "segmentation settings in the \"Adjustment workbench\" "
                             "until the lasers are detected correctly"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
 
diff --git a/src/horus/gui/workbench/adjustment/current_video.py b/src/horus/gui/workbench/adjustment/current_video.py
index 648b316..be97f5e 100644
--- a/src/horus/gui/workbench/adjustment/current_video.py
+++ b/src/horus/gui/workbench/adjustment/current_video.py
@@ -59,13 +59,13 @@ class CurrentVideo(object):
                 corners = image_detection.detect_corners(image)
                 image_capture.flush_laser(14)
                 images = image_capture.capture_lasers()
-                for i in xrange(2):
+                for i in range(2):
                     images[i] = image_detection.pattern_mask(images[i], corners)
                     images[i] = laser_segmentation.compute_line_segmentation(images[i])
                     images[i] = cv2.cvtColor(images[i], cv2.COLOR_GRAY2RGB)
             else:
                 images = image_capture.capture_lasers()
-                for i in xrange(2):
+                for i in range(2):
                     images[i] = laser_segmentation.compute_line_segmentation(images[i])
                     (u, v), _ = laser_segmentation.compute_2d_points(images[i])
                     images[i] = cv2.cvtColor(images[i], cv2.COLOR_GRAY2RGB)
diff --git a/src/horus/gui/workbench/calibration/pages/camera_intrinsics.py b/src/horus/gui/workbench/calibration/pages/camera_intrinsics.py
index 24ea768..d82946f 100644
--- a/src/horus/gui/workbench/calibration/pages/camera_intrinsics.py
+++ b/src/horus/gui/workbench/calibration/pages/camera_intrinsics.py
@@ -140,7 +140,7 @@ class ResultPage(Page):
             if isinstance(result, CameraIntrinsicsError):
                 dlg = wx.MessageDialog(
                     self, _("Camera intrinsics calibration has failed. Please try again"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
 
diff --git a/src/horus/gui/workbench/calibration/pages/capture_page.py b/src/horus/gui/workbench/calibration/pages/capture_page.py
index d3efda1..426b455 100644
--- a/src/horus/gui/workbench/calibration/pages/capture_page.py
+++ b/src/horus/gui/workbench/calibration/pages/capture_page.py
@@ -38,7 +38,7 @@ class CapturePage(Page):
         self.current_grid = 0
         self.image_grid_panel = wx.Panel(self.panel)
         self.grid_sizer = wx.GridSizer(self.rows, self.columns, 3, 3)
-        for panel in xrange(self.rows * self.columns):
+        for panel in range(self.rows * self.columns):
             self.panel_grid.append(ImageView(self.image_grid_panel))
             self.panel_grid[panel].Bind(wx.EVT_KEY_DOWN, self.on_key_press)
             self.grid_sizer.Add(self.panel_grid[panel], 0, wx.ALL | wx.EXPAND)
@@ -62,7 +62,7 @@ class CapturePage(Page):
         self.current_grid = 0
         self.gauge.SetValue(0)
         camera_intrinsics.reset()
-        for panel in xrange(self.rows * self.columns):
+        for panel in range(self.rows * self.columns):
             self.panel_grid[panel].SetBackgroundColour((221, 221, 221))
             self.panel_grid[panel].set_image(wx.Image(resources.get_path_for_image("void.png")))
 
diff --git a/src/horus/gui/workbench/calibration/pages/laser_triangulation.py b/src/horus/gui/workbench/calibration/pages/laser_triangulation.py
index 80db341..03e6b63 100644
--- a/src/horus/gui/workbench/calibration/pages/laser_triangulation.py
+++ b/src/horus/gui/workbench/calibration/pages/laser_triangulation.py
@@ -168,7 +168,7 @@ class ResultPage(Page):
                             "Also you can set up the calibration's settings "
                             "in the \"Adjustment workbench\" until the pattern "
                             "and the lasers are detected correctly"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
 
diff --git a/src/horus/gui/workbench/calibration/pages/platform_extrinsics.py b/src/horus/gui/workbench/calibration/pages/platform_extrinsics.py
index 5e97a14..9e6de49 100644
--- a/src/horus/gui/workbench/calibration/pages/platform_extrinsics.py
+++ b/src/horus/gui/workbench/calibration/pages/platform_extrinsics.py
@@ -165,7 +165,7 @@ class ResultPage(Page):
                             "Also you can set up the calibration's capture settings "
                             "in the \"Adjustment workbench\" until the pattern "
                             "is detected correctly"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
 
diff --git a/src/horus/gui/workbench/calibration/pages/scanner_autocheck.py b/src/horus/gui/workbench/calibration/pages/scanner_autocheck.py
index 9d20d36..085262b 100644
--- a/src/horus/gui/workbench/calibration/pages/scanner_autocheck.py
+++ b/src/horus/gui/workbench/calibration/pages/scanner_autocheck.py
@@ -77,7 +77,7 @@ class ScannerAutocheckPages(wx.Panel):
                             "Also you can set up the calibration's capture "
                             "settings in the \"Adjustment workbench\" "
                             "until the pattern is detected correctly"),
-                    _(result), wx.OK | wx.ICON_ERROR)
+                    _(str(result)), wx.OK | wx.ICON_ERROR)
                 dlg.ShowModal()
                 dlg.Destroy()
             elif isinstance(result, WrongMotorDirection):
diff --git a/src/horus/gui/workbench/scanning/panels.py b/src/horus/gui/workbench/scanning/panels.py
index e72d4bc..cd0ce43 100644
--- a/src/horus/gui/workbench/scanning/panels.py
+++ b/src/horus/gui/workbench/scanning/panels.py
@@ -142,7 +142,7 @@ class PointCloudColor(ExpandablePanel):
             data = dialog.GetColourData()
             color = data.GetColour().Get()
             ciclop_scan.color = color
-            profile.settings['point_cloud_color'] = unicode("".join(map(chr, color)).encode('hex'))
+            profile.settings['point_cloud_color'] = str("".join(map(chr, color)).encode('hex'))
         dialog.Destroy()
 
     def on_selected(self):
diff --git a/src/horus/gui/workbench/toolbar.py b/src/horus/gui/workbench/toolbar.py
index 1256895..a956b75 100644
--- a/src/horus/gui/workbench/toolbar.py
+++ b/src/horus/gui/workbench/toolbar.py
@@ -69,7 +69,7 @@ class ToolbarConnection(Toolbar):
         current_video_id = profile.settings['camera_id']
         if len(video_list) > 0:
             if current_video_id not in video_list:
-                profile.settings['camera_id'] = unicode(video_list[0])
+                profile.settings['camera_id'] = str(video_list[0])
                 driver.camera.camera_id = int(profile.settings['camera_id'][-1:])
 
         driver.set_callbacks(lambda: wx.CallAfter(self.before_connect),
@@ -93,25 +93,25 @@ class ToolbarConnection(Toolbar):
         ret, result = response
         if not ret:
             if isinstance(result, WrongFirmware):
-                self._show_message(_(result), wx.ICON_INFORMATION,
+                self._show_message(_(str(result)), wx.ICON_INFORMATION,
                                    _("The board has the wrong firmware or an invalid baud rate.\n"
                                      "Please select your board and press \"Upload firmware\""))
                 self.update_status(False)
                 self.GetParent().launch_preferences()
             elif isinstance(result, BoardNotConnected):
-                self._show_message(_(result), wx.ICON_INFORMATION,
+                self._show_message(_(str(result)), wx.ICON_INFORMATION,
                                    _("The board is not connected.\n"
                                      "Please connect your board and select a valid Serial name"))
                 self.update_status(False)
                 self.GetParent().launch_preferences(basic=True)
             elif isinstance(result, OldFirmware):
-                self._show_message(_(result), wx.ICON_INFORMATION,
+                self._show_message(_(str(result)), wx.ICON_INFORMATION,
                                    _("The board has and old firmware.\n"
                                      "Please select your board and press \"Upload firmware\""))
                 self.update_status(False)
                 self.GetParent().launch_preferences()
             elif isinstance(result, WrongCamera):
-                self._show_message(_(result), wx.ICON_INFORMATION,
+                self._show_message(_(str(result)), wx.ICON_INFORMATION,
                                    _("You probably have selected the wrong camera.\n"
                                      "Please select another Camera ID"))
                 self.update_status(False)
@@ -121,16 +121,16 @@ class ToolbarConnection(Toolbar):
                 if profile.settings['camera_id'] == wrong_camera_id:
                     profile.settings['camera_id'] = ''
             elif isinstance(result, CameraNotConnected):
-                self._show_message(_(result), wx.ICON_ERROR,
+                self._show_message(_(str(result)), wx.ICON_ERROR,
                                    _("Please plug your camera in and try to connect again"))
             elif isinstance(result, InvalidVideo):
-                self._show_message(_(result), wx.ICON_ERROR,
+                self._show_message(_(str(result)), wx.ICON_ERROR,
                                    _("Unplug and plug your camera USB cable "
                                      "and try to connect again"))
             elif isinstance(result, WrongDriver):
                 if system.is_windows():
                     self._show_message(
-                        _(result), wx.ICON_ERROR,
+                        _(str(result)), wx.ICON_ERROR,
                         _("Please, download and install the camera driver: \n"
                           "http://support.logitech.com/en_us/product/hd-webcam-c270"))
 
diff --git a/src/horus/gui/workbench/workbench.py b/src/horus/gui/workbench/workbench.py
index f619efb..30dac26 100644
--- a/src/horus/gui/workbench/workbench.py
+++ b/src/horus/gui/workbench/workbench.py
@@ -89,12 +89,12 @@ class Workbench(wx.Panel):
     def on_connect(self):
         if driver.is_connected:
             self.setup_engine()
-            for _, p in self.pages_collection.iteritems():
+            for _, p in self.pages_collection.items():
                 p.Enable()
             self.on_open()
 
     def on_disconnect(self):
-        for _, p in self.pages_collection.iteritems():
+        for _, p in self.pages_collection.items():
             p.Disable()
         self.on_close()
         self.disable_content()
diff --git a/src/horus/util/avr_helpers.py b/src/horus/util/avr_helpers.py
index 908db1b..bb0c87f 100644
--- a/src/horus/util/avr_helpers.py
+++ b/src/horus/util/avr_helpers.py
@@ -6,7 +6,7 @@ __copyright__ = 'Copyright (C) 2014-2016 Mundo Reader S.L.'
 __license__ = 'GNU General Public License v2 http://www.gnu.org/licenses/gpl2.html'
 
 import os
-import resources
+from . import resources
 from subprocess import Popen, PIPE, STDOUT
 
 import logging
diff --git a/src/horus/util/mesh_loaders/ply.py b/src/horus/util/mesh_loaders/ply.py
index 31ecfd7..61c7884 100644
--- a/src/horus/util/mesh_loaders/ply.py
+++ b/src/horus/util/mesh_loaders/ply.py
@@ -156,12 +156,12 @@ def save_scene_stream(stream, _object):
         stream.write(frame)
         if m.vertex_count > 0:
             if binary:
-                for i in xrange(m.vertex_count):
+                for i in range(m.vertex_count):
                     stream.write(struct.pack("<fffBBB",
                                              m.vertexes[i, 0], m.vertexes[i, 1], m.vertexes[i, 2],
                                              m.colors[i, 0], m.colors[i, 1], m.colors[i, 2]))
             else:
-                for i in xrange(m.vertex_count):
+                for i in range(m.vertex_count):
                     stream.write("{0} {1} {2} {3} {4} {5}\n".format(
                                  m.vertexes[i, 0], m.vertexes[i, 1], m.vertexes[i, 2],
                                  m.colors[i, 0], m.colors[i, 1], m.colors[i, 2]))
diff --git a/src/horus/util/mesh_loaders/stl.py b/src/horus/util/mesh_loaders/stl.py
index a7c9f0b..dcb5003 100644
--- a/src/horus/util/mesh_loaders/stl.py
+++ b/src/horus/util/mesh_loaders/stl.py
@@ -62,7 +62,7 @@ def _load_binary(mesh, stream):
     data = np.fromfile(stream, dtype=dtype, count=count)
 
     mesh.vertex_count = 3 * count
-    n = np.zeros((mesh.vertex_count / 3, 9), np.float32)
+    n = np.zeros((count, 9), np.float32)
     n[:, 0:3] = n[:, 3:6] = n[:, 6:9] = data['n']
     mesh.normal = n.reshape(mesh.vertex_count, 3)
     mesh.vertexes = np.reshape(data['v'], (mesh.vertex_count, 3))
diff --git a/src/horus/util/model.py b/src/horus/util/model.py
index 9615c16..93bece1 100644
--- a/src/horus/util/model.py
+++ b/src/horus/util/model.py
@@ -52,7 +52,7 @@ class Model(object):
             vertexes = self._mesh.vertexes
             vmin = vertexes.min(0)
             vmax = vertexes.max(0)
-            for n in xrange(0, 3):
+            for n in range(0, 3):
                 self._min[n] = min(vmin[n], self._min[n])
                 self._max[n] = max(vmax[n], self._max[n])
 
@@ -136,7 +136,7 @@ class Mesh(object):
 
     def _calculate_normals(self):
         # Calculate the normals
-        tris = self.vertexes.reshape(self.vertex_count / 3, 3, 3)
+        tris = self.vertexes.reshape(self.vertex_count // 3, 3, 3)
         normals = np.cross(tris[::, 1] - tris[::, 0], tris[::, 2] - tris[::, 0])
         normals /= np.linalg.norm(normals)
         n = np.concatenate((np.concatenate((normals, normals), axis=1), normals), axis=1)
diff --git a/src/horus/util/profile.py b/src/horus/util/profile.py
index aa51204..6aebeb9 100644
--- a/src/horus/util/profile.py
+++ b/src/horus/util/profile.py
@@ -12,7 +12,6 @@ import math
 import sys
 import collections
 import json
-import types
 import numpy as np
 import logging
 logger = logging.getLogger(__name__)
@@ -74,17 +73,17 @@ class Settings(collections.MutableMapping):
         #    return
         setting_type = self.get_setting(key)._type
         try:
-            if setting_type == types.BooleanType:
+            if   isinstance(setting_type, bool):
                 value = bool(value)
-            elif setting_type == types.IntType:
+            elif isinstance(setting_type, int):
                 value = int(value)
-            elif setting_type == types.FloatType:
+            elif isinstance(setting_type, float):
                 value = float(value)
-            elif setting_type == types.UnicodeType:
-                value = unicode(value)
-            elif setting_type == types.ListType:
+            elif isinstance(setting_type, str):
+                value = str(value)
+            elif isinstance(setting_type, list):
                 value = value
-            elif setting_type == np.ndarray:
+            elif isinstance(setting_type, np.ndarray):
                 value = np.asarray(value)
         except:
             logger.error("Unable to cast setting %s to type %s" % (key, setting_type))
@@ -178,7 +177,7 @@ class Settings(collections.MutableMapping):
         _('Low')
         self._add_setting(
             Setting('luminosity', _('Luminosity'), 'profile_settings',
-                    unicode, u'Medium', possible_values=(u'High', u'Medium', u'Low')))
+                    str, u'Medium', possible_values=(u'High', u'Medium', u'Low')))
         self._add_setting(
             Setting('brightness_control', _('Brightness'), 'profile_settings',
                     int, 128, min_value=0, max_value=255))
@@ -206,7 +205,7 @@ class Settings(collections.MutableMapping):
 
         self._add_setting(
             Setting('current_panel_control', u'camera_control', 'profile_settings',
-                    unicode, u'camera_control',
+                    str, u'camera_control',
                     possible_values=(u'camera_control', u'laser_control',
                                      u'ldr_value', u'motor_control', u'gcode_control')))
 
@@ -215,7 +214,7 @@ class Settings(collections.MutableMapping):
         _('Laser')
         self._add_setting(
             Setting('capture_mode_scanning', _('Capture mode'), 'profile_settings',
-                    unicode, u'Texture', possible_values=(u'Texture', u'Laser')))
+                    str, u'Texture', possible_values=(u'Texture', u'Laser')))
 
         self._add_setting(
             Setting('brightness_texture_scanning', _('Brightness'), 'profile_settings',
@@ -250,7 +249,7 @@ class Settings(collections.MutableMapping):
             Setting('draw_line_scanning', _('Draw line'), 'profile_settings', bool, True))
         self._add_setting(
             Setting('red_channel_scanning', _('Red channel'), 'profile_settings',
-                    unicode, u'R (RGB)',
+                    str, u'R (RGB)',
                     possible_values=(u'R (RGB)', u'Cr (YCrCb)', u'U (YUV)')))
         self._add_setting(
             Setting('threshold_enable_scanning', _('Enable threshold'),
@@ -272,7 +271,7 @@ class Settings(collections.MutableMapping):
                     int, 8, min_value=0, max_value=30))
         self._add_setting(
             Setting('refinement_scanning', _('Refinement'), 'profile_settings',
-                    unicode, u'SGF',
+                    str, u'SGF',
                     possible_values=(u'None', u'SGF')))
         _('Open')
         _('Enable open')
@@ -282,7 +281,7 @@ class Settings(collections.MutableMapping):
         _('Laser')
         self._add_setting(
             Setting('capture_mode_calibration', _('Capture mode'), 'profile_settings',
-                    unicode, u'Pattern', possible_values=(u'Pattern', u'Laser')))
+                    str, u'Pattern', possible_values=(u'Pattern', u'Laser')))
 
         self._add_setting(
             Setting('brightness_pattern_calibration', _('Brightness'), 'profile_settings',
@@ -315,7 +314,7 @@ class Settings(collections.MutableMapping):
 
         self._add_setting(
             Setting('red_channel_calibration', _('Red channel'), 'profile_settings',
-                    unicode, u'R (RGB)',
+                    str, u'R (RGB)',
                     possible_values=(u'R (RGB)', u'Cr (YCrCb)', u'U (YUV)')))
         self._add_setting(
             Setting('threshold_enable_calibration', _('Enable threshold'),
@@ -337,17 +336,17 @@ class Settings(collections.MutableMapping):
                     int, 5, min_value=0, max_value=30))
         self._add_setting(
             Setting('refinement_calibration', _('Refinement'), 'profile_settings',
-                    unicode, u'RANSAC',
+                    str, u'RANSAC',
                     possible_values=(u'None', u'SGF', u'RANSAC')))
 
         self._add_setting(
             Setting('current_video_mode_adjustment', u'Texture', 'profile_settings',
-                    unicode, u'Texture',
+                    str, u'Texture',
                     possible_values=(u'Texture', u'Pattern', u'Laser', u'Gray')))
 
         self._add_setting(
             Setting('current_panel_adjustment', u'scan_capture', 'profile_settings',
-                    unicode, u'scan_capture',
+                    str, u'scan_capture',
                     possible_values=(u'scan_capture', u'scan_segmentation',
                                      u'calibration_capture', u'calibration_segmentation')))
 
@@ -359,7 +358,7 @@ class Settings(collections.MutableMapping):
         _('Both')
         self._add_setting(
             Setting('use_laser', _('Use laser'), 'profile_settings',
-                    unicode, u'Both', possible_values=(u'Left', u'Right', u'Both')))
+                    str, u'Both', possible_values=(u'Left', u'Right', u'Both')))
 
         self._add_setting(
             Setting('motor_step_scanning', _(u'Step (º)'), 'profile_settings',
@@ -383,7 +382,7 @@ class Settings(collections.MutableMapping):
                     int, 200, min_value=0, max_value=250))
         self._add_setting(
             Setting('point_cloud_color', _('Choose point cloud color'), 'profile_settings',
-                    unicode, u'AAAAAA'))
+                    str, u'AAAAAA'))
 
         self._add_setting(
             Setting('scan_sleep', _(u'Wait time in each scan interval'), 'profile_settings',
@@ -396,28 +395,28 @@ class Settings(collections.MutableMapping):
         _('Line')
         self._add_setting(
             Setting('video_scanning', _('Video'), 'profile_settings',
-                    unicode, u'Texture', possible_values=(u'Texture', u'Laser', u'Gray', u'Line')))
+                    str, u'Texture', possible_values=(u'Texture', u'Laser', u'Gray', u'Line')))
 
         self._add_setting(
-            Setting('save_image_button', _('Save image'), 'no_settings', unicode, u''))
+            Setting('save_image_button', _('Save image'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('left_button', _('Left'), 'no_settings', unicode, u''))
+            Setting('left_button', _('Left'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('right_button', _('Right'), 'no_settings', unicode, u''))
+            Setting('right_button', _('Right'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('move_button', _('Move'), 'no_settings', unicode, u''))
+            Setting('move_button', _('Move'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('enable_button', _('Enable'), 'no_settings', unicode, u''))
+            Setting('enable_button', _('Enable'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('reset_origin_button', _('Reset origin'), 'no_settings', unicode, u''))
+            Setting('reset_origin_button', _('Reset origin'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('gcode_gui', _('Send'), 'no_settings', unicode, u''))
+            Setting('gcode_gui', _('Send'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('ldr_value', _('Send'), 'no_settings', unicode, u''))
+            Setting('ldr_value', _('Send'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('autocheck_button', _('Perform autocheck'), 'no_settings', unicode, u''))
+            Setting('autocheck_button', _('Perform autocheck'), 'no_settings', str, u''))
         self._add_setting(
-            Setting('set_resolution_button', _('Set resolution'), 'no_settings', unicode, u''))
+            Setting('set_resolution_button', _('Set resolution'), 'no_settings', str, u''))
 
         # -- Calibration Settings
 
@@ -498,14 +497,14 @@ class Settings(collections.MutableMapping):
                     np.ndarray, np.ndarray(shape=(3,), buffer=np.array([-5.0, 90.0, 320.0]))))
 
         self._add_setting(
-            Setting('laser_triangulation_hash', '', 'calibration_settings', unicode, u''))
+            Setting('laser_triangulation_hash', '', 'calibration_settings', str, u''))
 
         self._add_setting(
-            Setting('platform_extrinsics_hash', '', 'calibration_settings', unicode, u''))
+            Setting('platform_extrinsics_hash', '', 'calibration_settings', str, u''))
 
         self._add_setting(
             Setting('current_panel_calibration', u'pattern_settings', 'profile_settings',
-                    unicode, u'pattern_settings',
+                    str, u'pattern_settings',
                     possible_values=(u'pattern_settings', u'camera_intrinsics',
                                      u'scanner_autocheck', u'rotating_platform_settings',
                                      u'laser_triangulation', u'platform_extrinsics',
@@ -526,10 +525,10 @@ class Settings(collections.MutableMapping):
         _('Rectangular')
         self._add_setting(
             Setting('machine_shape', _('Machine shape'), 'machine_settings',
-                    unicode, u'Circular', possible_values=(u'Circular', u'Rectangular')))
+                    str, u'Circular', possible_values=(u'Circular', u'Rectangular')))
         self._add_setting(
             Setting('machine_model_path', _('Machine model'), 'machine_settings',
-                    unicode, unicode(resources.get_path_for_mesh('ciclop_platform.stl'))))
+                    str, str(resources.get_path_for_mesh('ciclop_platform.stl'))))
         # self._add_setting(
         #     Setting('roi_width', _('Width (mm)'), 'machine_settings',
         #             int, 200, min_value=0, max_value=250))
@@ -539,26 +538,26 @@ class Settings(collections.MutableMapping):
 
         self._add_setting(
             Setting('current_panel_scanning', u'scan_parameters', 'profile_settings',
-                    unicode, u'scan_parameters',
+                    str, u'scan_parameters',
                     possible_values=(u'scan_parameters', u'rotating_platform',
                                      u'point_cloud_roi', u'point_cloud_color')))
 
         # -- Preferences
 
         self._add_setting(
-            Setting('serial_name', _('Serial name'), 'preferences', unicode, u''))
+            Setting('serial_name', _('Serial name'), 'preferences', str, u''))
         self._add_setting(
             Setting('baud_rate', _('Baud rate'), 'preferences', int, 115200,
                     possible_values=(9600, 14400, 19200, 38400, 57600, 115200)))
         self._add_setting(
-            Setting('camera_id', _('Camera ID'), 'preferences', unicode, u''))
+            Setting('camera_id', _('Camera ID'), 'preferences', str, u''))
         self._add_setting(
-            Setting('board', _('Board'), 'preferences', unicode, u'BT ATmega328',
+            Setting('board', _('Board'), 'preferences', str, u'BT ATmega328',
                     possible_values=(u'Arduino Uno', u'BT ATmega328')))
         self._add_setting(
             Setting('invert_motor', _('Invert motor'), 'preferences', bool, False))
         self._add_setting(
-            Setting('language', _('Language'), 'preferences', unicode, u'English',
+            Setting('language', _('Language'), 'preferences', str, u'English',
                     possible_values=(u'English', u'Español', u'Français',
                                      u'Deutsch', u'Italiano', u'Português'),
                     tooltip=_('Change the language of Horus. '
@@ -592,7 +591,7 @@ class Settings(collections.MutableMapping):
 
         # Hack to translate combo boxes:
         self._add_setting(
-            Setting('workbench', _('Workbench'), 'preferences', unicode, u'scanning',
+            Setting('workbench', _('Workbench'), 'preferences', str, u'scanning',
                     possible_values=(u'control', u'adjustment', u'calibration', u'scanning')))
         self._add_setting(
             Setting('show_welcome', _('Show welcome'), 'preferences', bool, True))
@@ -630,14 +629,14 @@ class Settings(collections.MutableMapping):
             Setting('last_files', _('Last files'), 'preferences', list, []))
         # TODO: Set this default value
         self._add_setting(
-            Setting('last_file', _('Last file'), 'preferences', unicode, u''))
+            Setting('last_file', _('Last file'), 'preferences', str, u''))
         # TODO: Set this default value
         self._add_setting(
-            Setting('last_profile', _('Last profile'), 'preferences', unicode, u''))
+            Setting('last_profile', _('Last profile'), 'preferences', str, u''))
         self._add_setting(
-            Setting('model_color', _('Model color'), 'preferences', unicode, u'888888'))
+            Setting('model_color', _('Model color'), 'preferences', str, u'888888'))
         self._add_setting(
-            Setting('last_clear_log_date', _('Last clear log date'), 'preferences', unicode, u''))
+            Setting('last_clear_log_date', _('Last clear log date'), 'preferences', str, u''))
 
 
 class Setting(object):
@@ -817,7 +816,7 @@ def get_size_polygons(size, machine_shape):
     if machine_shape == 'Circular':
         circle = []
         steps = 32
-        for n in xrange(0, steps):
+        for n in range(0, steps):
             circle.append([math.cos(float(n) / steps * 2 * math.pi) * size[0] / 2,
                            math.sin(float(n) / steps * 2 * math.pi) * size[1] / 2])
         ret.append(np.array(circle, np.float32))
diff --git a/src/horus/util/resources.py b/src/horus/util/resources.py
index ced9a1a..7276db8 100644
--- a/src/horus/util/resources.py
+++ b/src/horus/util/resources.py
@@ -62,7 +62,7 @@ def setup_localization(selected_language=None):
 
     locale_path = os.path.normpath(os.path.join(resource_base_path, 'locale'))
     translation = gettext.translation('horus', locale_path, languages, fallback=True)
-    translation.install(unicode=True)
+    translation.install()
 
 
 def get_language_options():
diff --git a/src/horus/util/version.py b/src/horus/util/version.py
index 3019de3..1fe4608 100644
--- a/src/horus/util/version.py
+++ b/src/horus/util/version.py
@@ -7,7 +7,7 @@ __copyright__ = 'Copyright (C) 2014-2016 Mundo Reader S.L.\
 __license__ = 'GNU General Public License v2 http://www.gnu.org/licenses/gpl2.html'
 
 import json
-import urllib2
+import urllib.request
 import webbrowser
 
 from horus import __version__, __datetime__, __commit__
@@ -46,10 +46,10 @@ URL_DOWNLOAD = 'https://github.com/bqlabs/horus/releases/download/'
 def download_lastest_data():
     global latest_version, latest_commit, latest_datetime
     try:
-        f = urllib2.urlopen(URL_API_RELEASES, timeout=1)
+        f = urllib.request.urlopen(URL_API_RELEASES, timeout=1)
         content = json.loads(f.read())
         tag_name = content['tag_name']
-        f = urllib2.urlopen(URL_DOWNLOAD + tag_name + '/version', timeout=1)
+        f = urllib.request.urlopen(URL_DOWNLOAD + tag_name + '/version', timeout=1)
         content = json.loads(f.read())
         latest_version = Version(content['version'])
         latest_datetime = content['datetime']
-- 
2.35.1

openSUSE Build Service is sponsored by