diff --git a/packages/collectd/pybitmessagestatus.py b/packages/collectd/pybitmessagestatus.py index d15c3a48..cb29a071 100644 --- a/packages/collectd/pybitmessagestatus.py +++ b/packages/collectd/pybitmessagestatus.py @@ -2,7 +2,7 @@ import collectd import json -import xmlrpclib +from six.moves import xmlrpc_client as xmlrpclib pybmurl = "" api = "" diff --git a/setup.py b/setup.py index 30436bec..0daf5d74 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,7 @@ import os import platform import shutil import sys +import six from importlib import import_module from setuptools import setup, Extension @@ -83,7 +84,7 @@ if __name__ == "__main__": 'images/kivy/text_images*.png' ]} - if sys.version_info[0] == 3: + if six.PY3: packages.extend( [ 'pybitmessage.bitmessagekivy', diff --git a/src/api.py b/src/api.py index a4445569..7b9c3c33 100644 --- a/src/api.py +++ b/src/api.py @@ -70,6 +70,7 @@ from struct import pack, unpack import six from six.moves import configparser, http_client, xmlrpc_server +from six.moves.reprlib import repr import helper_inbox import helper_sent diff --git a/src/bitmessagecli.py b/src/bitmessagecli.py index 84c618af..a0d0ea6c 100644 --- a/src/bitmessagecli.py +++ b/src/bitmessagecli.py @@ -21,7 +21,8 @@ import os import socket import sys import time -import xmlrpclib +from six.moves import xmlrpc_client as xmlrpclib +from six.moves import input as raw_input from bmconfigparser import config diff --git a/src/bitmessagecurses/__init__.py b/src/bitmessagecurses/__init__.py index 64fd735b..6f905963 100644 --- a/src/bitmessagecurses/__init__.py +++ b/src/bitmessagecurses/__init__.py @@ -10,13 +10,14 @@ Bitmessage commandline interface # * python2-pythondialog # * dialog -import ConfigParser +from six.moves import configparser import curses import os import sys import time from textwrap import fill from threading import Timer +import six from dialog import Dialog import helper_sent @@ -105,7 +106,7 @@ def ascii(s): """ASCII values""" r = "" for c in s: - if ord(c) in range(128): + if six.byte2int(c) in range(128): r += c return r @@ -326,13 +327,13 @@ def handlech(c, stdscr): if c != curses.ERR: global inboxcur, addrcur, sentcur, subcur, abookcur, blackcur if c in range(256): - if chr(c) in '12345678': + if six.int2byte(c) in '12345678': global menutab - menutab = int(chr(c)) - elif chr(c) == 'q': + menutab = int(six.int2byte(c)) + elif six.int2byte(c) == 'q': global quit_ quit_ = True - elif chr(c) == '\n': + elif six.int2byte(c) == '\n': curses.curs_set(1) d = Dialog(dialog="dialog") if menutab == 1: @@ -672,7 +673,7 @@ def handlech(c, stdscr): elif t == "2" and m is False: try: mn = config.get(a, "mailinglistname") - except ConfigParser.NoOptionError: + except configparser.NoOptionError: mn = "" r, t = d.inputbox("Mailing list name", init=mn) if r == d.DIALOG_OK: diff --git a/src/bitmessagekivy/identiconGeneration.py b/src/bitmessagekivy/identiconGeneration.py index 2e2f2e93..63c58c0d 100644 --- a/src/bitmessagekivy/identiconGeneration.py +++ b/src/bitmessagekivy/identiconGeneration.py @@ -3,7 +3,7 @@ Core classes for loading images and converting them to a Texture. The raw image data can be keep in memory for further access """ import hashlib -from io import BytesIO +from six import BytesIO from PIL import Image from kivy.core.image import Image as CoreImage diff --git a/src/bitmessagekivy/tests/telenium_process.py b/src/bitmessagekivy/tests/telenium_process.py index 0a81044d..5fc26e3b 100644 --- a/src/bitmessagekivy/tests/telenium_process.py +++ b/src/bitmessagekivy/tests/telenium_process.py @@ -6,6 +6,7 @@ import os import shutil import tempfile from time import time, sleep +from six.moves import getcwdb from telenium.tests import TeleniumTestCase from telenium.client import TeleniumHttpException @@ -32,7 +33,7 @@ def cleanup(files=_files): class TeleniumTestProcess(TeleniumTestCase): """Setting Screen Functionality Testing""" - cmd_entrypoint = [os.path.join(os.path.abspath(os.getcwd()), 'src', 'mockbm', 'kivy_main.py')] + cmd_entrypoint = [os.path.join(os.path.abspath(getcwdb()), 'src', 'mockbm', 'kivy_main.py')] @classmethod def setUpClass(cls): diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 1212e45a..30bb898e 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -14,8 +14,10 @@ import threading import time from datetime import datetime, timedelta from sqlite3 import register_adapter +import six +from six.moves import range as xrange -from ver import ustr, unic +from unqstr import ustr, unic from PyQt4 import QtCore, QtGui from PyQt4.QtNetwork import QLocalSocket, QLocalServer @@ -469,7 +471,7 @@ class MyForm(settingsmixin.SMainWindow): # add missing folders if len(db[toAddress]) > 0: j = 0 - for f, c in db[toAddress].iteritems(): + for f, c in six.iteritems(db[toAddress]): try: subwidget = Ui_FolderWidget(widget, j, toAddress, f, c['count']) except KeyError: @@ -599,7 +601,7 @@ class MyForm(settingsmixin.SMainWindow): # add missing folders if len(db[toAddress]) > 0: j = 0 - for f, c in db[toAddress].iteritems(): + for f, c in six.iteritems(db[toAddress]): if toAddress is not None and tab == 'messages' and folder == "new": continue subwidget = Ui_FolderWidget(widget, j, toAddress, f, c) @@ -1076,15 +1078,15 @@ class MyForm(settingsmixin.SMainWindow): for i in range(root.childCount()): addressItem = root.child(i) if addressItem.type == AccountMixin.ALL: - newCount = sum(totalUnread.itervalues()) + newCount = sum(six.itervalues(totalUnread)) self.drawTrayIcon(self.currentTrayIconFileName, newCount) else: try: - newCount = sum(( + newCount = sum(six.itervalues(( broadcastsUnread if addressItem.type == AccountMixin.SUBSCRIPTION else normalUnread - )[addressItem.address].itervalues()) + )[addressItem.address])) except KeyError: newCount = 0 if newCount != addressItem.unreadCount: @@ -2872,7 +2874,7 @@ class MyForm(settingsmixin.SMainWindow): QtCore.QEventLoop.AllEvents, 1000 ) self.saveSettings() - for attr, obj in self.ui.__dict__.iteritems(): + for attr, obj in six.iteritems(self.ui.__dict__): if hasattr(obj, "__class__") \ and isinstance(obj, settingsmixin.SettingsMixin): saveMethod = getattr(obj, "saveSettings", None) @@ -4210,7 +4212,7 @@ class MyForm(settingsmixin.SMainWindow): def initSettings(self): self.loadSettings() - for attr, obj in self.ui.__dict__.iteritems(): + for attr, obj in six.iteritems(self.ui.__dict__): if hasattr(obj, "__class__") and \ isinstance(obj, settingsmixin.SettingsMixin): loadMethod = getattr(obj, "loadSettings", None) diff --git a/src/bitmessageqt/account.py b/src/bitmessageqt/account.py index eefb3a7e..09ab4a1b 100644 --- a/src/bitmessageqt/account.py +++ b/src/bitmessageqt/account.py @@ -14,7 +14,7 @@ import re import sys import time -from ver import ustr +from unqstr import ustr from PyQt4 import QtGui import queues diff --git a/src/bitmessageqt/address_dialogs.py b/src/bitmessageqt/address_dialogs.py index 98d3dd1c..1c918814 100644 --- a/src/bitmessageqt/address_dialogs.py +++ b/src/bitmessageqt/address_dialogs.py @@ -5,7 +5,7 @@ Dialogs that work with BM address. import hashlib -from ver import ustr, unic +from unqstr import ustr, unic from PyQt4 import QtCore, QtGui import queues diff --git a/src/bitmessageqt/addressvalidator.py b/src/bitmessageqt/addressvalidator.py index ac23c31e..382e5c25 100644 --- a/src/bitmessageqt/addressvalidator.py +++ b/src/bitmessageqt/addressvalidator.py @@ -3,9 +3,9 @@ Address validator module. """ # pylint: disable=too-many-branches,too-many-arguments -from Queue import Empty +from six.moves.queue import Empty -from ver import ustr +from unqstr import ustr from PyQt4 import QtGui from addresses import decodeAddress, addBMIfNotPresent diff --git a/src/bitmessageqt/blacklist.py b/src/bitmessageqt/blacklist.py index 0927f596..fc5d462b 100644 --- a/src/bitmessageqt/blacklist.py +++ b/src/bitmessageqt/blacklist.py @@ -1,4 +1,4 @@ -from ver import ustr, unic +from unqstr import ustr, unic from PyQt4 import QtCore, QtGui import widgets diff --git a/src/bitmessageqt/dialogs.py b/src/bitmessageqt/dialogs.py index 85536410..3090114e 100644 --- a/src/bitmessageqt/dialogs.py +++ b/src/bitmessageqt/dialogs.py @@ -2,7 +2,7 @@ Custom dialog classes """ # pylint: disable=too-few-public-methods -from ver import ustr +from unqstr import ustr from PyQt4 import QtGui import paths diff --git a/src/bitmessageqt/foldertree.py b/src/bitmessageqt/foldertree.py index e9fe8038..ffd83042 100644 --- a/src/bitmessageqt/foldertree.py +++ b/src/bitmessageqt/foldertree.py @@ -6,7 +6,7 @@ Folder tree and messagelist widgets definitions. from cgi import escape -from ver import ustr, unic +from unqstr import ustr, unic from PyQt4 import QtCore, QtGui from bmconfigparser import config diff --git a/src/bitmessageqt/messageview.py b/src/bitmessageqt/messageview.py index a94b01d1..3959b168 100644 --- a/src/bitmessageqt/messageview.py +++ b/src/bitmessageqt/messageview.py @@ -5,7 +5,7 @@ zoom and URL click warning popup """ -from ver import ustr, unic +from unqstr import ustr, unic from PyQt4 import QtCore, QtGui from .safehtmlparser import SafeHTMLParser diff --git a/src/bitmessageqt/newchandialog.py b/src/bitmessageqt/newchandialog.py index 72b4f273..c8088f76 100644 --- a/src/bitmessageqt/newchandialog.py +++ b/src/bitmessageqt/newchandialog.py @@ -4,7 +4,7 @@ src/bitmessageqt/newchandialog.py """ -from ver import ustr, unic +from unqstr import ustr, unic from PyQt4 import QtCore, QtGui from bitmessageqt import widgets diff --git a/src/bitmessageqt/retranslateui.py b/src/bitmessageqt/retranslateui.py index ae22e96f..cf5fb65d 100644 --- a/src/bitmessageqt/retranslateui.py +++ b/src/bitmessageqt/retranslateui.py @@ -1,5 +1,6 @@ from os import path -from ver import ustr +from unqstr import ustr +import six from PyQt4 import QtGui from debug import logger from bitmessageqt import widgets @@ -8,7 +9,7 @@ class RetranslateMixin(object): def retranslateUi(self): defaults = QtGui.QWidget() widgets.load(self.__class__.__name__.lower() + '.ui', defaults) - for attr, value in defaults.__dict__.iteritems(): + for attr, value in six.iteritems(defaults.__dict__): setTextMethod = getattr(value, "setText", None) if callable(setTextMethod): getattr(self, attr).setText(ustr(getattr(defaults, attr).text())) diff --git a/src/bitmessageqt/safehtmlparser.py b/src/bitmessageqt/safehtmlparser.py index 42c71486..eff359de 100644 --- a/src/bitmessageqt/safehtmlparser.py +++ b/src/bitmessageqt/safehtmlparser.py @@ -2,12 +2,11 @@ import inspect import re -from HTMLParser import HTMLParser +from six.moves.html_parser import HTMLParser -from urllib import quote_plus -from urlparse import urlparse +from six.moves.urllib.parse import quote_plus, urlparse -from ver import ustr, unic +from unqstr import ustr, unic class SafeHTMLParser(HTMLParser): """HTML parser with sanitisation""" diff --git a/src/bitmessageqt/settings.py b/src/bitmessageqt/settings.py index 14f2d30a..5658651f 100644 --- a/src/bitmessageqt/settings.py +++ b/src/bitmessageqt/settings.py @@ -1,13 +1,13 @@ """ This module setting file is for settings """ -import ConfigParser +from six.moves import configparser import os import sys import tempfile import six -from ver import ustr +from unqstr import ustr from PyQt4 import QtCore, QtGui import debug @@ -30,9 +30,9 @@ from tr import _translate def getSOCKSProxyType(config): """Get user socksproxytype setting from *config*""" try: - result = ConfigParser.SafeConfigParser.get( + result = configparser.SafeConfigParser.get( config, 'bitmessagesettings', 'socksproxytype') - except (ConfigParser.NoSectionError, ConfigParser.NoOptionError): + except (configparser.NoSectionError, configparser.NoOptionError): return None else: if result.lower() in ('', 'none', 'false'): diff --git a/src/bitmessageqt/settingsmixin.py b/src/bitmessageqt/settingsmixin.py index 5a24837d..a80b8d27 100644 --- a/src/bitmessageqt/settingsmixin.py +++ b/src/bitmessageqt/settingsmixin.py @@ -5,7 +5,7 @@ src/settingsmixin.py """ -from ver import ustr +from unqstr import ustr from PyQt4 import QtCore, QtGui diff --git a/src/bitmessageqt/support.py b/src/bitmessageqt/support.py index cb28d534..9d3c7e26 100644 --- a/src/bitmessageqt/support.py +++ b/src/bitmessageqt/support.py @@ -6,7 +6,7 @@ import ssl import sys import time -from ver import ustr, unic +from unqstr import ustr, unic from PyQt4 import QtCore from bitmessageqt import account diff --git a/src/bitmessageqt/tests/main.py b/src/bitmessageqt/tests/main.py index 91f0ae11..01db4ed3 100644 --- a/src/bitmessageqt/tests/main.py +++ b/src/bitmessageqt/tests/main.py @@ -1,6 +1,6 @@ """Common definitions for bitmessageqt tests""" -import Queue +from six.moves import queue as Queue import sys import unittest diff --git a/src/bitmessageqt/tests/support.py b/src/bitmessageqt/tests/support.py index 8985987a..d83f90a0 100644 --- a/src/bitmessageqt/tests/support.py +++ b/src/bitmessageqt/tests/support.py @@ -6,7 +6,7 @@ from shared import isAddressInMyAddressBook from .main import TestBase -from ver import ustr +from unqstr import ustr class TestSupport(TestBase): diff --git a/src/bmconfigparser.py b/src/bmconfigparser.py index abf285ad..ec05af3e 100644 --- a/src/bmconfigparser.py +++ b/src/bmconfigparser.py @@ -21,7 +21,7 @@ config_ready = Event() class BMConfigParser(SafeConfigParser): """ - Singleton class inherited from :class:`ConfigParser.SafeConfigParser` + Singleton class inherited from :class:`configparser.SafeConfigParser` with additional methods specific to bitmessage config. """ # pylint: disable=too-many-ancestors diff --git a/src/class_singleWorker.py b/src/class_singleWorker.py index 45b7621f..4f080fa8 100644 --- a/src/class_singleWorker.py +++ b/src/class_singleWorker.py @@ -30,6 +30,7 @@ from bmconfigparser import config from helper_sql import sqlExecute, sqlQuery from network import knownnodes, StoppableThread from six.moves import configparser, queue +from six.moves.reprlib import repr def sizeof_fmt(num, suffix='h/s'): diff --git a/src/class_smtpDeliver.py b/src/class_smtpDeliver.py index 9e3b8ab3..490f296b 100644 --- a/src/class_smtpDeliver.py +++ b/src/class_smtpDeliver.py @@ -4,9 +4,9 @@ SMTP client thread for delivering emails # pylint: disable=unused-variable import smtplib -import urlparse +from six.moves.urllib import parse as urlparse from email.header import Header -from email.mime.text import MIMEText +from six.moves import email_mime_text import queues import state @@ -55,7 +55,7 @@ class smtpDeliver(StoppableThread): u = urlparse.urlparse(dest) to = urlparse.parse_qs(u.query)['to'] client = smtplib.SMTP(u.hostname, u.port) - msg = MIMEText(body, 'plain', 'utf-8') + msg = email_mime_text(body, 'plain', 'utf-8') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = fromAddress + '@' + SMTPDOMAIN toLabel = map( diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index 7df9e253..8b064a76 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -8,6 +8,7 @@ import sqlite3 import sys import threading import time +from six.moves.reprlib import repr try: import helper_sql diff --git a/src/depends.py b/src/depends.py index 4212d654..a2b0d6c6 100755 --- a/src/depends.py +++ b/src/depends.py @@ -6,6 +6,7 @@ and suggest how it may be installed import os import re import sys +import six # Only really old versions of Python don't have sys.hexversion. We don't # support them. The logging module was introduced in Python 2.3 @@ -452,7 +453,7 @@ def check_dependencies(verbose=False, optional=False): 'PyBitmessage requires Python 2.7.4 or greater' ' (but not Python 3+)') has_all_dependencies = False - if sys.hexversion >= 0x3000000: + if six.PY3: logger.error( 'PyBitmessage does not support Python 3+. Python 2.7.4' ' or greater is required. Python 2.7.18 is recommended.') diff --git a/src/fallback/umsgpack/umsgpack.py b/src/fallback/umsgpack/umsgpack.py index 34938614..68d5869a 100644 --- a/src/fallback/umsgpack/umsgpack.py +++ b/src/fallback/umsgpack/umsgpack.py @@ -49,10 +49,11 @@ License: MIT # pylint: disable=too-many-lines,too-many-branches,too-many-statements,global-statement,too-many-return-statements # pylint: disable=unused-argument -import collections -import io +from six.moves import collections_abc as collections +from six.moves import range as xrange import struct import sys +import six __version__ = "2.4.1" "Module version string" @@ -99,9 +100,9 @@ class Ext: # pylint: disable=old-style-class if not isinstance(type, int) or not (type >= 0 and type <= 127): raise TypeError("ext type out of range") # Check data is type bytes - elif sys.version_info[0] == 3 and not isinstance(data, bytes): + elif six.PY3 and not isinstance(data, bytes): raise TypeError("ext data is not type \'bytes\'") - elif sys.version_info[0] == 2 and not isinstance(data, str): + elif six.PY2 and not isinstance(data, str): raise TypeError("ext data is not type \'str\'") self.type = type self.data = data @@ -125,7 +126,7 @@ class Ext: # pylint: disable=old-style-class String representation of this Ext object. """ s = "Ext Object (Type: 0x%02x, Data: " % self.type - s += " ".join(["0x%02x" % ord(self.data[i:i + 1]) + s += " ".join(["0x%02x" % six.byte2int(self.data[i:i + 1]) for i in xrange(min(len(self.data), 8))]) if len(self.data) > 8: s += " ..." @@ -549,7 +550,7 @@ def _packb2(obj, **options): '\x82\xa7compact\xc3\xa6schema\x00' >>> """ - fp = io.BytesIO() + fp = six.BytesIO() _pack2(obj, fp, **options) return fp.getvalue() @@ -582,7 +583,7 @@ def _packb3(obj, **options): b'\x82\xa7compact\xc3\xa6schema\x00' >>> """ - fp = io.BytesIO() + fp = six.BytesIO() _pack3(obj, fp, **options) return fp.getvalue() @@ -599,7 +600,7 @@ def _read_except(fp, n): def _unpack_integer(code, fp, options): - if (ord(code) & 0xe0) == 0xe0: + if (six.byte2int(code) & 0xe0) == 0xe0: return struct.unpack("b", code)[0] elif code == b'\xd0': return struct.unpack("b", _read_except(fp, 1))[0] @@ -609,7 +610,7 @@ def _unpack_integer(code, fp, options): return struct.unpack(">i", _read_except(fp, 4))[0] elif code == b'\xd3': return struct.unpack(">q", _read_except(fp, 8))[0] - elif (ord(code) & 0x80) == 0x00: + elif (six.byte2int(code) & 0x80) == 0x00: return struct.unpack("B", code)[0] elif code == b'\xcc': return struct.unpack("B", _read_except(fp, 1))[0] @@ -619,21 +620,21 @@ def _unpack_integer(code, fp, options): return struct.unpack(">I", _read_except(fp, 4))[0] elif code == b'\xcf': return struct.unpack(">Q", _read_except(fp, 8))[0] - raise Exception("logic error, not int: 0x%02x" % ord(code)) + raise Exception("logic error, not int: 0x%02x" % six.byte2int(code)) def _unpack_reserved(code, fp, options): if code == b'\xc1': raise ReservedCodeException( - "encountered reserved code: 0x%02x" % ord(code)) + "encountered reserved code: 0x%02x" % six.byte2int(code)) raise Exception( - "logic error, not reserved code: 0x%02x" % ord(code)) + "logic error, not reserved code: 0x%02x" % six.byte2int(code)) def _unpack_nil(code, fp, options): if code == b'\xc0': return None - raise Exception("logic error, not nil: 0x%02x" % ord(code)) + raise Exception("logic error, not nil: 0x%02x" % six.byte2int(code)) def _unpack_boolean(code, fp, options): @@ -641,7 +642,7 @@ def _unpack_boolean(code, fp, options): return False elif code == b'\xc3': return True - raise Exception("logic error, not boolean: 0x%02x" % ord(code)) + raise Exception("logic error, not boolean: 0x%02x" % six.byte2int(code)) def _unpack_float(code, fp, options): @@ -649,12 +650,12 @@ def _unpack_float(code, fp, options): return struct.unpack(">f", _read_except(fp, 4))[0] elif code == b'\xcb': return struct.unpack(">d", _read_except(fp, 8))[0] - raise Exception("logic error, not float: 0x%02x" % ord(code)) + raise Exception("logic error, not float: 0x%02x" % six.byte2int(code)) def _unpack_string(code, fp, options): - if (ord(code) & 0xe0) == 0xa0: - length = ord(code) & ~0xe0 + if (six.byte2int(code) & 0xe0) == 0xa0: + length = six.byte2int(code) & ~0xe0 elif code == b'\xd9': length = struct.unpack("B", _read_except(fp, 1))[0] elif code == b'\xda': @@ -662,7 +663,7 @@ def _unpack_string(code, fp, options): elif code == b'\xdb': length = struct.unpack(">I", _read_except(fp, 4))[0] else: - raise Exception("logic error, not string: 0x%02x" % ord(code)) + raise Exception("logic error, not string: 0x%02x" % six.byte2int(code)) # Always return raw bytes in compatibility mode global compatibility @@ -686,7 +687,7 @@ def _unpack_binary(code, fp, options): elif code == b'\xc6': length = struct.unpack(">I", _read_except(fp, 4))[0] else: - raise Exception("logic error, not binary: 0x%02x" % ord(code)) + raise Exception("logic error, not binary: 0x%02x" % six.byte2int(code)) return _read_except(fp, length) @@ -709,9 +710,9 @@ def _unpack_ext(code, fp, options): elif code == b'\xc9': length = struct.unpack(">I", _read_except(fp, 4))[0] else: - raise Exception("logic error, not ext: 0x%02x" % ord(code)) + raise Exception("logic error, not ext: 0x%02x" % six.byte2int(code)) - ext = Ext(ord(_read_except(fp, 1)), _read_except(fp, length)) + ext = Ext(six.byte2int(_read_except(fp, 1)), _read_except(fp, length)) # Unpack with ext handler, if we have one ext_handlers = options.get("ext_handlers") @@ -722,14 +723,14 @@ def _unpack_ext(code, fp, options): def _unpack_array(code, fp, options): - if (ord(code) & 0xf0) == 0x90: - length = (ord(code) & ~0xf0) + if (six.byte2int(code) & 0xf0) == 0x90: + length = (six.byte2int(code) & ~0xf0) elif code == b'\xdc': length = struct.unpack(">H", _read_except(fp, 2))[0] elif code == b'\xdd': length = struct.unpack(">I", _read_except(fp, 4))[0] else: - raise Exception("logic error, not array: 0x%02x" % ord(code)) + raise Exception("logic error, not array: 0x%02x" % six.byte2int(code)) return [_unpack(fp, options) for _ in xrange(length)] @@ -741,14 +742,14 @@ def _deep_list_to_tuple(obj): def _unpack_map(code, fp, options): - if (ord(code) & 0xf0) == 0x80: - length = (ord(code) & ~0xf0) + if (six.byte2int(code) & 0xf0) == 0x80: + length = (six.byte2int(code) & ~0xf0) elif code == b'\xde': length = struct.unpack(">H", _read_except(fp, 2))[0] elif code == b'\xdf': length = struct.unpack(">I", _read_except(fp, 4))[0] else: - raise Exception("logic error, not map: 0x%02x" % ord(code)) + raise Exception("logic error, not map: 0x%02x" % six.byte2int(code)) d = {} if not options.get('use_ordered_dict') \ else collections.OrderedDict() @@ -911,7 +912,7 @@ def _unpackb2(s, **options): """ if not isinstance(s, (str, bytearray)): raise TypeError("packed data must be type 'str' or 'bytearray'") - return _unpack(io.BytesIO(s), options) + return _unpack(six.BytesIO(s), options) # For Python 3, expects a bytes object @@ -957,7 +958,7 @@ def _unpackb3(s, **options): """ if not isinstance(s, (bytes, bytearray)): raise TypeError("packed data must be type 'bytes' or 'bytearray'") - return _unpack(io.BytesIO(s), options) + return _unpack(six.BytesIO(s), options) ############################################################################# # Module Initialization @@ -990,7 +991,7 @@ def __init(): _float_precision = "single" # Map packb and unpackb to the appropriate version - if sys.version_info[0] == 3: + if six.PY3: pack = _pack3 packb = _packb3 dump = _pack3 diff --git a/src/l10n.py b/src/l10n.py index fe02d3f4..927937d7 100644 --- a/src/l10n.py +++ b/src/l10n.py @@ -3,8 +3,8 @@ import logging import os import re -import sys import time +import six from six.moves import range @@ -61,7 +61,7 @@ if not re.search(r'\d', time.strftime(time_format)): # It seems some systems lie about the encoding they use # so we perform comprehensive decoding tests -elif sys.version_info[0] == 2: +elif six.PY2: try: # Check day names for i in range(7): @@ -118,7 +118,7 @@ def formatTimestamp(timestamp=None): except ValueError: timestring = time.strftime(time_format) - if sys.version_info[0] == 2: + if six.PY2: return timestring.decode(encoding) return timestring diff --git a/src/multiqueue.py b/src/multiqueue.py index 88b6a4dd..80598220 100644 --- a/src/multiqueue.py +++ b/src/multiqueue.py @@ -3,7 +3,7 @@ A queue with multiple internal subqueues. Elements are added into a random subqueue, and retrieval rotates """ -from collections import deque +from six.moves.collections_abc import deque from six.moves import queue diff --git a/src/namecoin.py b/src/namecoin.py index 7311cd42..6f43ec55 100644 --- a/src/namecoin.py +++ b/src/namecoin.py @@ -4,7 +4,7 @@ Namecoin queries # pylint: disable=too-many-branches,protected-access import base64 -import httplib +from six.moves import http_client as httplib import json import os import socket diff --git a/src/network/asyncore_pollchoose.py b/src/network/asyncore_pollchoose.py index bdd312c6..a41145a1 100644 --- a/src/network/asyncore_pollchoose.py +++ b/src/network/asyncore_pollchoose.py @@ -18,6 +18,7 @@ from errno import ( ENOTCONN, ENOTSOCK, EPIPE, ESHUTDOWN, ETIMEDOUT, EWOULDBLOCK, errorcode ) from threading import current_thread +from six.moves.reprlib import repr import helper_random diff --git a/src/network/dandelion.py b/src/network/dandelion.py index 29879085..5784fdd2 100644 --- a/src/network/dandelion.py +++ b/src/network/dandelion.py @@ -6,6 +6,7 @@ from collections import namedtuple from random import choice, expovariate, sample from threading import RLock from time import time +import six from network import connectionpool import state @@ -74,7 +75,7 @@ class Dandelion: # pylint: disable=old-style-class if logger.isEnabledFor(logging.DEBUG): logger.debug( '%s entering fluff mode due to %s.', - ''.join('%02x' % ord(i) for i in hashId), reason) + ''.join('%02x' % six.byte2int(i) for i in hashId), reason) with self.lock: try: del self.hashMap[hashId] @@ -99,12 +100,12 @@ class Dandelion: # pylint: disable=old-style-class with self.lock: if len(self.stem) < MAX_STEMS: self.stem.append(connection) - for k in (k for k, v in self.nodeMap.iteritems() if v is None): + for k in (k for k, v in six.iteritems(self.nodeMap) if v is None): self.nodeMap[k] = connection - for k, v in { - k: v for k, v in self.hashMap.iteritems() + for k, v in six.iteritems({ + k: v for k, v in six.iteritems(self.hashMap) if v.child is None - }.iteritems(): + }): self.hashMap[k] = Stem( connection, v.stream, self.poissonTimeout()) invQueue.put((v.stream, k, v.child)) @@ -120,14 +121,14 @@ class Dandelion: # pylint: disable=old-style-class self.stem.remove(connection) # active mappings to pointing to the removed node for k in ( - k for k, v in self.nodeMap.iteritems() + k for k, v in six.iteritems(self.nodeMap) if v == connection ): self.nodeMap[k] = None - for k, v in { - k: v for k, v in self.hashMap.iteritems() + for k, v in six.iteritems({ + k: v for k, v in six.iteritems(self.hashMap) if v.child == connection - }.iteritems(): + }): self.hashMap[k] = Stem( None, v.stream, self.poissonTimeout()) @@ -168,7 +169,7 @@ class Dandelion: # pylint: disable=old-style-class with self.lock: deadline = time() toDelete = [ - [v.stream, k, v.child] for k, v in self.hashMap.iteritems() + [v.stream, k, v.child] for k, v in six.iteritems(self.hashMap) if v.timeout < deadline ] diff --git a/src/network/downloadthread.py b/src/network/downloadthread.py index 4230cca7..38b1c432 100644 --- a/src/network/downloadthread.py +++ b/src/network/downloadthread.py @@ -3,6 +3,7 @@ """ import time import state +import six import addresses import helper_random import protocol @@ -28,7 +29,7 @@ class DownloadThread(StoppableThread): deadline = time.time() - self.requestExpires try: toDelete = [ - k for k, v in missingObjects.iteritems() + k for k, v in six.iteritems(missingObjects) if v < deadline] except RuntimeError: pass diff --git a/src/network/invthread.py b/src/network/invthread.py index 51224b7f..82a34e13 100644 --- a/src/network/invthread.py +++ b/src/network/invthread.py @@ -1,7 +1,7 @@ """ Thread to send inv annoucements """ -import Queue +from six.moves import queue as Queue import random from time import time diff --git a/src/network/knownnodes.py b/src/network/knownnodes.py index c53be2cd..702f59c6 100644 --- a/src/network/knownnodes.py +++ b/src/network/knownnodes.py @@ -10,10 +10,8 @@ import os import pickle # nosec B403 import threading import time -try: - from collections.abc import Iterable -except ImportError: - from collections import Iterable +from six.moves.collections_abc import Iterable +import six import state from bmconfigparser import config @@ -54,8 +52,8 @@ def json_serialize_knownnodes(output): Reorganize knownnodes dict and write it as JSON to output """ _serialized = [] - for stream, peers in knownNodes.iteritems(): - for peer, info in peers.iteritems(): + for stream, peers in six.iteritems(knownNodes): + for peer, info in six.iteritems(peers): info.update(rating=round(info.get('rating', 0), 2)) _serialized.append({ 'stream': stream, 'peer': peer._asdict(), 'info': info @@ -87,7 +85,7 @@ def pickle_deserialize_old_knownnodes(source): global knownNodes knownNodes = pickle.load(source) # nosec B301 for stream in knownNodes.keys(): - for node, params in knownNodes[stream].iteritems(): + for node, params in six.iteritems(knownNodes[stream]): if isinstance(params, (float, int)): addKnownNode(stream, node, params) diff --git a/src/network/node.py b/src/network/node.py index 4c532b81..e580778b 100644 --- a/src/network/node.py +++ b/src/network/node.py @@ -1,7 +1,7 @@ """ Named tuples representing the network peers """ -import collections +from six.moves import collections_abc as collections Peer = collections.namedtuple('Peer', ['host', 'port']) Node = collections.namedtuple('Node', ['services', 'host', 'port']) diff --git a/src/network/objectracker.py b/src/network/objectracker.py index c352200d..07a4b675 100644 --- a/src/network/objectracker.py +++ b/src/network/objectracker.py @@ -3,6 +3,7 @@ Module for tracking objects """ import time from threading import RLock +import six import state import network.connectionpool # use long name to address recursive import @@ -75,7 +76,7 @@ class ObjectTracker(object): with self.objectsNewToThemLock: self.objectsNewToThem = { k: v - for k, v in self.objectsNewToThem.iteritems() + for k, v in six.iteritems(self.objectsNewToThem) if v >= deadline} self.lastCleaned = time.time() diff --git a/src/network/receivequeuethread.py b/src/network/receivequeuethread.py index 0e9b5d21..bf6a9eda 100644 --- a/src/network/receivequeuethread.py +++ b/src/network/receivequeuethread.py @@ -2,7 +2,7 @@ Process data incoming from network """ import errno -import Queue +from six.moves import queue as Queue import socket from network import connectionpool diff --git a/src/network/socks4a.py b/src/network/socks4a.py index 2758838a..bf0adf29 100644 --- a/src/network/socks4a.py +++ b/src/network/socks4a.py @@ -5,6 +5,7 @@ SOCKS4a proxy module import logging import socket import struct +import six from .proxy import GeneralProxyError, Proxy, ProxyError @@ -39,16 +40,16 @@ class Socks4a(Proxy): def state_pre_connect(self): """Handle feedback from SOCKS4a while it is connecting on our behalf""" # Get the response - if self.read_buf[0:1] != chr(0x00).encode(): + if self.read_buf[0:1] != six.int2byte(0x00).encode(): # bad data self.close() raise GeneralProxyError(1) - elif self.read_buf[1:2] != chr(0x5A).encode(): + elif self.read_buf[1:2] != six.int2byte(0x5A).encode(): # Connection failed self.close() - if ord(self.read_buf[1:2]) in (91, 92, 93): + if six.byte2int(self.read_buf[1:2]) in (91, 92, 93): # socks 4 error - raise Socks4aError(ord(self.read_buf[1:2]) - 90) + raise Socks4aError(six.byte2int(self.read_buf[1:2]) - 90) else: raise Socks4aError(4) # Get the bound address/port @@ -102,9 +103,9 @@ class Socks4aConnection(Socks4a): self.append_write_buf(self.ipaddr) if self._auth: self.append_write_buf(self._auth[0]) - self.append_write_buf(chr(0x00).encode()) + self.append_write_buf(six.int2byte(0x00).encode()) if rmtrslv: - self.append_write_buf(self.destination[0] + chr(0x00).encode()) + self.append_write_buf(self.destination[0] + six.int2byte(0x00).encode()) self.set_state("pre_connect", length=0, expectBytes=8) return True @@ -132,8 +133,8 @@ class Socks4aResolver(Socks4a): self.append_write_buf(struct.pack("BBBB", 0x00, 0x00, 0x00, 0x01)) if self._auth: self.append_write_buf(self._auth[0]) - self.append_write_buf(chr(0x00).encode()) - self.append_write_buf(self.host + chr(0x00).encode()) + self.append_write_buf(six.int2byte(0x00).encode()) + self.append_write_buf(self.host + six.int2byte(0x00).encode()) self.set_state("pre_connect", length=0, expectBytes=8) return True diff --git a/src/network/socks5.py b/src/network/socks5.py index 1838a737..c295480c 100644 --- a/src/network/socks5.py +++ b/src/network/socks5.py @@ -6,6 +6,7 @@ SOCKS5 proxy module import logging import socket import struct +import six from .node import Peer from .proxy import GeneralProxyError, Proxy, ProxyError @@ -97,20 +98,20 @@ class Socks5(Proxy): def state_pre_connect(self): """Handle feedback from socks5 while it is connecting on our behalf.""" # Get the response - if self.read_buf[0:1] != chr(0x05).encode(): + if self.read_buf[0:1] != six.int2byte(0x05).encode(): self.close() raise GeneralProxyError(1) - elif self.read_buf[1:2] != chr(0x00).encode(): + elif self.read_buf[1:2] != six.int2byte(0x00).encode(): # Connection failed self.close() - if ord(self.read_buf[1:2]) <= 8: - raise Socks5Error(ord(self.read_buf[1:2])) + if six.byte2int(self.read_buf[1:2]) <= 8: + raise Socks5Error(six.byte2int(self.read_buf[1:2])) else: raise Socks5Error(9) # Get the bound address/port - elif self.read_buf[3:4] == chr(0x01).encode(): + elif self.read_buf[3:4] == six.int2byte(0x01).encode(): self.set_state("proxy_addr_1", length=4, expectBytes=4) - elif self.read_buf[3:4] == chr(0x03).encode(): + elif self.read_buf[3:4] == six.int2byte(0x03).encode(): self.set_state("proxy_addr_2_1", length=4, expectBytes=1) else: self.close() @@ -129,7 +130,7 @@ class Socks5(Proxy): (e.g. IPv6, onion, ...). This is part 1 which retrieves the length of the data. """ - self.address_length = ord(self.read_buf[0:1]) + self.address_length = six.byte2int(self.read_buf[0:1]) self.set_state( "proxy_addr_2_2", length=1, expectBytes=self.address_length) return True @@ -171,19 +172,19 @@ class Socks5Connection(Socks5): # use the IPv4 address request even if remote resolving was specified. try: self.ipaddr = socket.inet_aton(self.destination[0]) - self.append_write_buf(chr(0x01).encode() + self.ipaddr) + self.append_write_buf(six.int2byte(0x01).encode() + self.ipaddr) except socket.error: # may be IPv6! # Well it's not an IP number, so it's probably a DNS name. if self._remote_dns: # Resolve remotely self.ipaddr = None - self.append_write_buf(chr(0x03).encode() + chr( + self.append_write_buf(six.int2byte(0x03).encode() + six.int2byte( len(self.destination[0])).encode() + self.destination[0]) else: # Resolve locally self.ipaddr = socket.inet_aton( socket.gethostbyname(self.destination[0])) - self.append_write_buf(chr(0x01).encode() + self.ipaddr) + self.append_write_buf(six.int2byte(0x01).encode() + self.ipaddr) self.append_write_buf(struct.pack(">H", self.destination[1])) self.set_state("pre_connect", length=0, expectBytes=4) return True @@ -208,7 +209,7 @@ class Socks5Resolver(Socks5): """Perform resolving""" # Now we can request the actual connection self.append_write_buf(struct.pack('BBB', 0x05, 0xF0, 0x00)) - self.append_write_buf(chr(0x03).encode() + chr( + self.append_write_buf(six.int2byte(0x03).encode() + six.int2byte( len(self.host)).encode() + str(self.host)) self.append_write_buf(struct.pack(">H", self.port)) self.set_state("pre_connect", length=0, expectBytes=4) diff --git a/src/network/tcp.py b/src/network/tcp.py index 831a3b11..9a01920a 100644 --- a/src/network/tcp.py +++ b/src/network/tcp.py @@ -8,6 +8,7 @@ import math import random import socket import time +import six # magic imports! import addresses @@ -191,7 +192,7 @@ class TCPConnection(BMProto, TLSDispatcher): # only if more recent than 3 hours # and having positive or neutral rating filtered = [ - (k, v) for k, v in nodes.iteritems() + (k, v) for k, v in six.iteritems(nodes) if v["lastseen"] > int(time.time()) - maximumAgeOfNodesThatIAdvertiseToOthers and v["rating"] >= 0 and not k.host.endswith('.onion') diff --git a/src/plugins/menu_qrcode.py b/src/plugins/menu_qrcode.py index ea322a49..e5d41822 100644 --- a/src/plugins/menu_qrcode.py +++ b/src/plugins/menu_qrcode.py @@ -3,7 +3,7 @@ A menu plugin showing QR-Code for bitmessage address in modal dialog. """ -import urllib +from six.moves.urllib.parse import urlencode import qrcode from PyQt4 import QtCore, QtGui @@ -93,7 +93,7 @@ def connect_plugin(form): return dialog.render( 'bitmessage:%s' % account.address + ( - '?' + urllib.urlencode({'label': label.encode('utf-8')}) + '?' + urlencode({'label': label.encode('utf-8')}) if label != account.address else '') ) dialog.exec_() diff --git a/src/protocol.py b/src/protocol.py index 7f9830e5..e300b97a 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -12,6 +12,7 @@ import sys import time from binascii import hexlify from struct import Struct, pack, unpack +import six import defaults import highlevelcrypto @@ -227,7 +228,7 @@ def checkIPv6Address(host, hostStandardFormat, private=False): logger.debug('Ignoring loopback address: %s', hostStandardFormat) return False try: - host = [ord(c) for c in host[:2]] + host = [six.byte2int(c) for c in host[:2]] except TypeError: # python3 has ints already pass if host[0] == 0xfe and host[1] & 0xc0 == 0x80: diff --git a/src/pyelliptic/arithmetic.py b/src/pyelliptic/arithmetic.py index 23c24b5e..ce66db98 100644 --- a/src/pyelliptic/arithmetic.py +++ b/src/pyelliptic/arithmetic.py @@ -3,6 +3,7 @@ Arithmetic Expressions """ import hashlib import re +import six P = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1 A = 0 @@ -34,7 +35,7 @@ def get_code_string(base): return b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' if base == 256: try: - return b''.join([chr(x) for x in range(256)]) + return b''.join([six.int2byte(x) for x in range(256)]) except TypeError: return bytes([x for x in range(256)]) diff --git a/src/pyelliptic/hash.py b/src/pyelliptic/hash.py index 70c9a6ce..51ffd623 100644 --- a/src/pyelliptic/hash.py +++ b/src/pyelliptic/hash.py @@ -4,6 +4,8 @@ Wrappers for hash functions from OpenSSL. # Copyright (C) 2011 Yann GUIBET # See LICENSE for details. +import six + from .openssl import OpenSSL @@ -22,7 +24,7 @@ def _equals_str(a, b): return False result = 0 for x, y in zip(a, b): - result |= ord(x) ^ ord(y) + result |= six.byte2int(x) ^ six.byte2int(y) return result == 0 diff --git a/src/pyelliptic/openssl.py b/src/pyelliptic/openssl.py index deb81644..f1def5d3 100644 --- a/src/pyelliptic/openssl.py +++ b/src/pyelliptic/openssl.py @@ -8,6 +8,7 @@ needed openssl functionality in class _OpenSSL. """ import ctypes import sys +import six # pylint: disable=protected-access @@ -691,7 +692,7 @@ class _OpenSSL(object): length = self.BN_num_bytes(x) data = self.malloc(0, length) OpenSSL.BN_bn2bin(x, data) - return ord(data[length - 1]) & 1 + return six.byte2int(data[length - 1]) & 1 def get_cipher(self, name): """ @@ -745,7 +746,7 @@ class _OpenSSL(object): """ buffer_ = None if data != 0: - if sys.version_info.major == 3 and isinstance(data, type('')): + if six.PY3 and isinstance(data, type('')): data = data.encode() buffer_ = self.create_string_buffer(data, size) else: diff --git a/src/shared.py b/src/shared.py index b85ddb20..64eea088 100644 --- a/src/shared.py +++ b/src/shared.py @@ -14,6 +14,7 @@ import stat import subprocess # nosec B404 import sys from binascii import hexlify +from six.moves.reprlib import repr # Project imports. import highlevelcrypto diff --git a/src/storage/storage.py b/src/storage/storage.py index 9b33eef7..d89be837 100644 --- a/src/storage/storage.py +++ b/src/storage/storage.py @@ -4,10 +4,7 @@ Storing inventory items from abc import abstractmethod from collections import namedtuple -try: - from collections import MutableMapping # pylint: disable=deprecated-class -except ImportError: - from collections.abc import MutableMapping +from six.moves.collections_abc import MutableMapping # pylint: disable=deprecated-class InventoryItem = namedtuple('InventoryItem', 'type stream payload expires tag') diff --git a/src/tests/common.py b/src/tests/common.py index 2d60c716..0cd84d2f 100644 --- a/src/tests/common.py +++ b/src/tests/common.py @@ -1,7 +1,7 @@ import os -import sys import time import unittest +import six _files = ( @@ -33,7 +33,7 @@ def checkup(): def skip_python3(): """Raise unittest.SkipTest() if detected python3""" - if sys.hexversion >= 0x3000000: + if six.PY3: raise unittest.SkipTest('Module is not ported to python3') diff --git a/src/tests/core.py b/src/tests/core.py index f1a11a06..7000223d 100644 --- a/src/tests/core.py +++ b/src/tests/core.py @@ -6,7 +6,7 @@ Tests for core and those that do not work outside import atexit import os import pickle # nosec -import Queue +from six.moves import queue as Queue import random # nosec import shutil import socket @@ -15,6 +15,7 @@ import sys import threading import time import unittest +import six import protocol import state @@ -137,8 +138,8 @@ class TestCore(unittest.TestCase): @staticmethod def _outdate_knownnodes(): with knownnodes.knownNodesLock: - for nodes in knownnodes.knownNodes.itervalues(): - for node in nodes.itervalues(): + for nodes in six.itervalues(knownnodes.knownNodes): + for node in six.itervalues(nodes): node['lastseen'] -= 2419205 # older than 28 days def test_knownnodes_pickle(self): @@ -146,9 +147,9 @@ class TestCore(unittest.TestCase): pickle_knownnodes() self._wipe_knownnodes() knownnodes.readKnownNodes() - for nodes in knownnodes.knownNodes.itervalues(): + for nodes in six.itervalues(knownnodes.knownNodes): self_count = n = 0 - for n, node in enumerate(nodes.itervalues()): + for n, node in enumerate(six.itervalues(nodes)): if node.get('self'): self_count += 1 self.assertEqual(n - self_count, 2) @@ -202,7 +203,7 @@ class TestCore(unittest.TestCase): while c > 0: time.sleep(1) c -= 2 - for peer, con in connectionpool.pool.outboundConnections.iteritems(): + for peer, con in six.iteritems(connectionpool.pool.outboundConnections): if ( peer.host.startswith('bootstrap') or peer.host == 'quzwelsuziwqgpt2.onion' @@ -223,7 +224,7 @@ class TestCore(unittest.TestCase): 'Failed to connect during %.2f sec' % (time.time() - _started)) def _check_knownnodes(self): - for stream in knownnodes.knownNodes.itervalues(): + for stream in six.itervalues(knownnodes.knownNodes): for peer in stream: if peer.host.startswith('bootstrap'): self.fail( diff --git a/src/tests/partial.py b/src/tests/partial.py index 870f6626..b5543b71 100644 --- a/src/tests/partial.py +++ b/src/tests/partial.py @@ -3,6 +3,7 @@ import os import sys import unittest +import six from pybitmessage import pathmagic @@ -22,7 +23,7 @@ class TestPartialRun(unittest.TestCase): import state from debug import logger # noqa:F401 pylint: disable=unused-variable - if sys.hexversion >= 0x3000000: + if six.PY3: # pylint: disable=no-name-in-module,relative-import from mockbm import network as network_mock import network diff --git a/src/tests/test_addressgenerator.py b/src/tests/test_addressgenerator.py index e48daef9..ea4e6e44 100644 --- a/src/tests/test_addressgenerator.py +++ b/src/tests/test_addressgenerator.py @@ -3,6 +3,7 @@ from binascii import unhexlify from six.moves import queue +import six from .partial import TestPartialRun from .samples import ( @@ -91,8 +92,8 @@ class TestAddressGenerator(TestPartialRun): self.command_queue.put(( 'createRandomAddress', 4, 1, 'test_random', 1, '', False, 0, 0)) addr = self.return_queue.get() - self.assertRegexpMatches(addr, r'^BM-') - self.assertRegexpMatches(addr[3:], r'[a-zA-Z1-9]+$') + six.assertRegex(self, addr, r'^BM-') + six.assertRegex(self, addr[3:], r'[a-zA-Z1-9]+$') self.assertLessEqual(len(addr[3:]), 40) self.assertEqual( diff --git a/src/tests/test_api.py b/src/tests/test_api.py index 2a4640fa..db52cc9c 100644 --- a/src/tests/test_api.py +++ b/src/tests/test_api.py @@ -8,6 +8,7 @@ import time from binascii import hexlify from six.moves import xmlrpc_client # nosec +import six import psutil @@ -174,28 +175,28 @@ class TestAPI(TestAPIProto): self.assertEqual( self.api.getDeterministicAddress(self._seed, 3, 1), sample_deterministic_addr3) - self.assertRegexpMatches( + six.assertRegex(self, self.api.getDeterministicAddress(self._seed, 2, 1), r'^API Error 0002:') # This is here until the streams will be implemented - self.assertRegexpMatches( + six.assertRegex(self, self.api.getDeterministicAddress(self._seed, 3, 2), r'API Error 0003:') - self.assertRegexpMatches( + six.assertRegex(self, self.api.createDeterministicAddresses(self._seed, 1, 4, 2), r'API Error 0003:') - self.assertRegexpMatches( + six.assertRegex(self, self.api.createDeterministicAddresses('', 1), r'API Error 0001:') - self.assertRegexpMatches( + six.assertRegex(self, self.api.createDeterministicAddresses(self._seed, 1, 2), r'API Error 0002:') - self.assertRegexpMatches( + six.assertRegex(self, self.api.createDeterministicAddresses(self._seed, 0), r'API Error 0004:') - self.assertRegexpMatches( + six.assertRegex(self, self.api.createDeterministicAddresses(self._seed, 1000), r'API Error 0005:') @@ -210,8 +211,8 @@ class TestAPI(TestAPIProto): def test_create_random_address(self): """API command 'createRandomAddress': basic BM-address validation""" addr = self._add_random_address('random_1') - self.assertRegexpMatches(addr, r'^BM-') - self.assertRegexpMatches(addr[3:], r'[a-zA-Z1-9]+$') + six.assertRegex(self, addr, r'^BM-') + six.assertRegex(self, addr[3:], r'[a-zA-Z1-9]+$') # Whitepaper says "around 36 character" self.assertLessEqual(len(addr[3:]), 40) self.assertEqual(self.api.deleteAddress(addr), 'success') @@ -242,7 +243,7 @@ class TestAPI(TestAPIProto): msg_subject = base64.encodestring('test_subject') result = self.api.sendMessage( sample_deterministic_addr4, addr, msg_subject, msg) - self.assertNotRegexpMatches(result, r'^API Error') + six.assertNotRegex(self, result, r'^API Error') self.api.deleteAddress(addr) # Remove known address self.api.deleteAddressBookEntry(sample_deterministic_addr4) @@ -411,7 +412,7 @@ class TestAPI(TestAPIProto): self.assertEqual(self.api.enableAddress(addr, False), 'success') result = self.api.sendBroadcast( addr, base64.encodestring('test_subject'), msg) - self.assertRegexpMatches(result, r'^API Error 0014:') + six.assertRegex(self, result, r'^API Error 0014:') finally: self.assertEqual(self.api.deleteAddress(addr), 'success') @@ -420,7 +421,7 @@ class TestAPI(TestAPIProto): result = self.api.sendBroadcast( 'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw', base64.encodestring('test_subject'), msg) - self.assertRegexpMatches(result, r'^API Error 0013:') + six.assertRegex(self, result, r'^API Error 0013:') def test_chan(self): """Testing chan creation/joining""" @@ -435,7 +436,7 @@ class TestAPI(TestAPIProto): self.assertEqual(self.api.joinChan(self._seed, addr), 'success') self.assertEqual(self.api.leaveChan(addr), 'success') # Joining with wrong address should fail - self.assertRegexpMatches( + six.assertRegex(self, self.api.joinChan(self._seed, 'BM-2cWzSnwjJ7yRP3nLEW'), r'^API Error 0008:' ) diff --git a/src/tests/test_api_thread.py b/src/tests/test_api_thread.py index 6e453b19..6fc3b66f 100644 --- a/src/tests/test_api_thread.py +++ b/src/tests/test_api_thread.py @@ -1,9 +1,9 @@ """TestAPIThread class definition""" -import sys import time from binascii import hexlify, unhexlify from struct import pack +import six from six.moves import queue, xmlrpc_client @@ -68,7 +68,7 @@ class TestAPIThread(TestPartialRun): def test_client_status(self): """Ensure the reply of clientStatus corresponds to mock""" status = self.api.clientStatus() - if sys.hexversion >= 0x3000000: + if six.PY3: self.assertEqual(status["networkConnections"], 4) self.assertEqual(status["pendingDownload"], 0) diff --git a/src/tests/test_inventory.py b/src/tests/test_inventory.py index 5978f9a5..6e698411 100644 --- a/src/tests/test_inventory.py +++ b/src/tests/test_inventory.py @@ -6,6 +6,7 @@ import struct import tempfile import time import unittest +import six from pybitmessage import highlevelcrypto from pybitmessage.storage import storage @@ -50,7 +51,7 @@ class TestStorageAbstract(unittest.TestCase): def test_inventory_storage(self): """Check inherited abstract methods""" - with self.assertRaisesRegexp( + with six.assertRaisesRegex(self, TypeError, "^Can't instantiate abstract class.*" "methods __contains__, __delitem__, __getitem__, __iter__," " __len__, __setitem__" diff --git a/src/tests/test_l10n.py b/src/tests/test_l10n.py index c6988827..a61f2a99 100644 --- a/src/tests/test_l10n.py +++ b/src/tests/test_l10n.py @@ -1,9 +1,9 @@ """Tests for l10n module""" import re -import sys import time import unittest +import six from pybitmessage import l10n @@ -16,7 +16,7 @@ class TestL10n(unittest.TestCase): self.assertFalse(re.search(r'\d', time.strftime("wrong"))) timestring_type = type(time.strftime(l10n.DEFAULT_TIME_FORMAT)) self.assertEqual(timestring_type, str) - if sys.version_info[0] == 2: + if six.PY2: self.assertEqual(timestring_type, bytes) def test_getWindowsLocale(self): diff --git a/src/tests/test_log.py b/src/tests/test_log.py index 4e74e50d..0d05fcb7 100644 --- a/src/tests/test_log.py +++ b/src/tests/test_log.py @@ -1,8 +1,8 @@ """Tests for logging""" import subprocess -import sys import unittest +import six from pybitmessage import proofofwork @@ -11,7 +11,7 @@ class TestLog(unittest.TestCase): """A test case for logging""" @unittest.skipIf( - sys.hexversion < 0x3000000, 'assertLogs is new in version 3.4') + six.PY2, 'assertLogs is new in version 3.4') def test_LogOutput(self): """Use proofofwork.LogOutput to log output of a shell command""" with self.assertLogs('default') as cm: # pylint: disable=no-member diff --git a/src/tests/test_logger.py b/src/tests/test_logger.py index d6bf33ed..636a209f 100644 --- a/src/tests/test_logger.py +++ b/src/tests/test_logger.py @@ -4,6 +4,7 @@ Testing the logger configuration import os import tempfile +import six from .test_process import TestProcessProto @@ -52,5 +53,5 @@ handlers=default self._stop_process() data = open(self.log_file).read() - self.assertRegexpMatches(data, self.pattern) - self.assertRegexpMatches(data, 'Loaded logger configuration') + six.assertRegex(self, data, self.pattern) + six.assertRegex(self, data, 'Loaded logger configuration') diff --git a/src/tests/test_protocol.py b/src/tests/test_protocol.py index e3137b25..6a7f1ee5 100644 --- a/src/tests/test_protocol.py +++ b/src/tests/test_protocol.py @@ -2,8 +2,8 @@ Tests for common protocol functions """ -import sys import unittest +import six from pybitmessage import protocol, state from pybitmessage.helper_startup import fixSocket @@ -79,7 +79,7 @@ class TestProtocol(TestSocketInet): self.assertEqual(protocol.checkIPAddress(globalhost), '8.8.8.8') @unittest.skipIf( - sys.hexversion >= 0x3000000, 'this is still not working with python3') + six.PY3, 'this is still not working with python3') def test_check_local_socks(self): """The SOCKS part of the local check""" self.assertTrue( diff --git a/src/tests/test_randomtrackingdict.py b/src/tests/test_randomtrackingdict.py index 2db3c423..528780a9 100644 --- a/src/tests/test_randomtrackingdict.py +++ b/src/tests/test_randomtrackingdict.py @@ -3,6 +3,7 @@ Tests for RandomTrackingDict Class """ import random import unittest +import six from time import time @@ -17,7 +18,7 @@ class TestRandomTrackingDict(unittest.TestCase): """helper function for tests, generates a random string""" retval = '' for _ in range(32): - retval += chr(random.randint(0, 255)) + retval += six.int2byte(random.randint(0, 255)) return retval def test_check_randomtrackingdict(self): diff --git a/src/tr.py b/src/tr.py index 66920197..4ba1f834 100644 --- a/src/tr.py +++ b/src/tr.py @@ -3,7 +3,7 @@ Translating text """ import os -from ver import ustr +from unqstr import ustr try: import state diff --git a/src/ver.py b/src/unqstr.py similarity index 51% rename from src/ver.py rename to src/unqstr.py index 50e49609..7c984df9 100644 --- a/src/ver.py +++ b/src/unqstr.py @@ -1,30 +1,21 @@ import sys - -if not hasattr(sys, "hexversion"): - sys.exit("Python version: {0}\n" - "PyBitmessage requires Python 2.7.4 or greater" - .format(sys.version)) - -if sys.hexversion < 0x3000000: - VER = 2 -else: - VER = 3 +import six def ustr(v): - if VER == 3: + if six.PY3: if isinstance(v, str): return v else: return str(v) - # assume VER == 2 + # assume six.PY2 if isinstance(v, unicode): return v.encode("utf-8", "replace") return str(v) def unic(v): - if VER == 3: + if six.PY3: return v - # assume VER == 2 + # assume six.PY2 if isinstance(v, unicode): return v return unicode(v, "utf-8", "replace") diff --git a/src/upnp.py b/src/upnp.py index 8776e0f9..fcaee6f7 100644 --- a/src/upnp.py +++ b/src/upnp.py @@ -4,13 +4,13 @@ Complete UPnP port forwarding implementation in separate thread. Reference: http://mattscodecave.com/posts/using-python-and-upnp-to-forward-a-port """ -import httplib +from six.moves import http_client as httplib import re import socket import time -import urllib2 +from six.moves.urllib.request import urlopen from random import randint -from urlparse import urlparse +from six.moves.urllib.parse import urlparse from xml.dom.minidom import Document # nosec B408 from defusedxml.minidom import parseString @@ -108,7 +108,7 @@ class Router: # pylint: disable=old-style-class logger.error("UPnP: missing location header") # get the profile xml file and read it into a variable - directory = urllib2.urlopen(header['location']).read() + directory = urlopen(header['location']).read() # create a DOM object that represents the `directory` document dom = parseString(directory) diff --git a/tests.py b/tests.py index 713b25ef..0e3adaf1 100644 --- a/tests.py +++ b/tests.py @@ -3,11 +3,12 @@ import random # noseq import sys import unittest +import six def unittest_discover(): """Explicit test suite creation""" - if sys.hexversion >= 0x3000000: + if six.PY3: from pybitmessage import pathmagic pathmagic.setup() loader = unittest.defaultTestLoader