From 71b5c87f752f039f4d67c86fe9e345125bf3b02f Mon Sep 17 00:00:00 2001 From: cis-kuldeep Date: Fri, 28 May 2021 18:41:23 +0530 Subject: [PATCH] Enabled python3, fixed type errors due to string encode/decode Ported api to python3 Ported 10 test cases for test_api to Python3 Fixed decode error & some import errors fixed all bugs for python3 fixed code quality Python 2/3 compatible base64 encoding code quality fixes pylint: disable=e1101 fixed type error in test_logger code quality fixes fixed pybitmessage binary changes in binary added new binary --- setup.py | 2 +- src/helper_random.py | 1 - src/multiqueue.py | 6 +- src/pybitmessage | 6 +- src/pybitmessage3 | 15 ++ src/tests/test_api.py | 360 ++++++++++++++++++++++++++------------ src/tests/test_logger.py | 16 +- src/tests/test_process.py | 5 +- 8 files changed, 281 insertions(+), 130 deletions(-) create mode 100644 src/pybitmessage3 diff --git a/setup.py b/setup.py index 0de2eb8c..e33b1ae0 100644 --- a/setup.py +++ b/setup.py @@ -168,7 +168,7 @@ if __name__ == "__main__": 'pybitmessage = pybitmessage.bitmessagemain:main' ] if sys.platform[:3] == 'win' else [] }, - scripts=['src/pybitmessage'], + scripts=['src/pybitmessage3'], cmdclass={'install': InstallCmd}, command_options={ 'build_sphinx': { diff --git a/src/helper_random.py b/src/helper_random.py index 9a29d5e2..54db5acf 100644 --- a/src/helper_random.py +++ b/src/helper_random.py @@ -2,7 +2,6 @@ import os import random - from pyelliptic.openssl import OpenSSL NoneType = type(None) diff --git a/src/multiqueue.py b/src/multiqueue.py index 886d693d..1b251cbc 100644 --- a/src/multiqueue.py +++ b/src/multiqueue.py @@ -3,6 +3,7 @@ A queue with multiple internal subqueues. Elements are added into a random subqueue, and retrieval rotates """ +import helper_random import sys if sys.version_info[0] == 3: import queue as Queue @@ -11,11 +12,6 @@ else: from collections import deque -if sys.version_info[0] == 3: - from . import helper_random -else: - import helper_random - class MultiQueue(Queue.Queue): """A base queue class""" diff --git a/src/pybitmessage b/src/pybitmessage index decebfff..5c674cc4 100644 --- a/src/pybitmessage +++ b/src/pybitmessage @@ -3,9 +3,13 @@ import os import pkg_resources + dist = pkg_resources.get_distribution('pybitmessage') script_file = os.path.join(dist.location, dist.key, 'bitmessagemain.py') new_globals = globals() new_globals.update(__file__=script_file) -execfile(script_file, new_globals) +try: + execfile(script_file, new_globals) +except NameError: + exec(compile(open(script_file, "rb").read(), script_file, 'exec'), new_globals) \ No newline at end of file diff --git a/src/pybitmessage3 b/src/pybitmessage3 new file mode 100644 index 00000000..5c674cc4 --- /dev/null +++ b/src/pybitmessage3 @@ -0,0 +1,15 @@ +#!/usr/bin/python2.7 + +import os +import pkg_resources + + +dist = pkg_resources.get_distribution('pybitmessage') +script_file = os.path.join(dist.location, dist.key, 'bitmessagemain.py') +new_globals = globals() +new_globals.update(__file__=script_file) + +try: + execfile(script_file, new_globals) +except NameError: + exec(compile(open(script_file, "rb").read(), script_file, 'exec'), new_globals) \ No newline at end of file diff --git a/src/tests/test_api.py b/src/tests/test_api.py index 1d8891a8..c96e46dc 100644 --- a/src/tests/test_api.py +++ b/src/tests/test_api.py @@ -1,3 +1,4 @@ +# pylint: disable=E1101 """ Tests using API. """ @@ -5,9 +6,7 @@ Tests using API. import base64 import json import time -from .common import skip_python3 - -skip_python3() +import sys try: # nosec from xmlrpclib import ServerProxy, ProtocolError @@ -16,6 +15,8 @@ except ImportError: from .test_process import TestProcessProto, TestProcessShutdown +PY3 = sys.version_info[0] >= 3 + class TestAPIProto(TestProcessProto): """Test case logic for testing API""" @@ -63,12 +64,18 @@ class TestAPIShutdown(TestAPIProto, TestProcessShutdown): class TestAPI(TestAPIProto): """Main API test case""" - _seed = base64.encodestring( - 'TIGER, tiger, burning bright. In the forests of the night' - ) + if PY3: + _seed = base64.encodebytes( + b'TIGER, tiger, burning bright. In the forests of the night') + else: + _seed = base64.encodestring( + 'TIGER, tiger, burning bright. In the forests of the night') def _add_random_address(self, label): - return self.api.createRandomAddress(base64.encodestring(label)) + if PY3: + return self.api.createRandomAddress(base64.encodebytes(bytes(label, 'UTF-8')).decode('utf-8')) + else: + return self.api.createRandomAddress(base64.encodestring(label)) def test_user_password(self): """Trying to connect with wrong username/password""" @@ -119,108 +126,202 @@ class TestAPI(TestAPIProto): def test_create_deterministic_addresses(self): """Test creation of deterministic addresses""" - self.assertEqual( - self.api.getDeterministicAddress(self._seed, 4, 1), - 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') - self.assertEqual( - self.api.getDeterministicAddress(self._seed, 3, 1), - 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN') - self.assertRegexpMatches( - self.api.getDeterministicAddress(self._seed, 2, 1), - r'^API Error 0002:') + if PY3: + self.assertEqual( + self.api.getDeterministicAddress(self._seed.decode('utf-8'), 4, 1), + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + self.assertEqual( + self.api.getDeterministicAddress(self._seed.decode('utf-8'), 3, 1), + 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN') + self.assertRegex( + self.api.getDeterministicAddress(self._seed.decode('utf-8'), 2, 1), + r'^API Error 0002:') - # This is here until the streams will be implemented - self.assertRegexpMatches( - self.api.getDeterministicAddress(self._seed, 3, 2), - r'API Error 0003:') - self.assertRegexpMatches( - self.api.createDeterministicAddresses(self._seed, 1, 4, 2), - r'API Error 0003:') + # This is here until the streams will be implemented + self.assertRegex( + self.api.getDeterministicAddress(self._seed.decode('utf-8'), 3, 2), + r'API Error 0003:') + self.assertRegex( + self.api.createDeterministicAddresses(self._seed.decode('utf-8'), 1, 4, 2), + r'API Error 0003:') - self.assertRegexpMatches( - self.api.createDeterministicAddresses('', 1), - r'API Error 0001:') - self.assertRegexpMatches( - self.api.createDeterministicAddresses(self._seed, 1, 2), - r'API Error 0002:') - self.assertRegexpMatches( - self.api.createDeterministicAddresses(self._seed, 0), - r'API Error 0004:') - self.assertRegexpMatches( - self.api.createDeterministicAddresses(self._seed, 1000), - r'API Error 0005:') + self.assertRegex( + self.api.createDeterministicAddresses('', 1), + r'API Error 0001:') + self.assertRegex( + self.api.createDeterministicAddresses(self._seed.decode('utf-8'), 1, 2), + r'API Error 0002:') + self.assertRegex( + self.api.createDeterministicAddresses(self._seed.decode('utf-8'), 0), + r'API Error 0004:') + self.assertRegex( + self.api.createDeterministicAddresses(self._seed.decode('utf-8'), 1000), + r'API Error 0005:') - addresses = json.loads( - self.api.createDeterministicAddresses(self._seed, 2, 4) - )['addresses'] - self.assertEqual(len(addresses), 2) - self.assertEqual(addresses[0], 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') - for addr in addresses: - self.assertEqual(self.api.deleteAddress(addr), 'success') + addresses = json.loads( + self.api.createDeterministicAddresses(self._seed.decode('utf-8'), 2, 4) + )['addresses'] + self.assertEqual(len(addresses), 2) + self.assertEqual(addresses[0], 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + for addr in addresses: + self.assertEqual(self.api.deleteAddress(addr), 'success') + else: + self.assertEqual( + self.api.getDeterministicAddress(self._seed, 4, 1), + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + self.assertEqual( + self.api.getDeterministicAddress(self._seed, 3, 1), + 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN') + self.assertRegexpMatches( + self.api.getDeterministicAddress(self._seed, 2, 1), + r'^API Error 0002:') + + # This is here until the streams will be implemented + self.assertRegexpMatches( + self.api.getDeterministicAddress(self._seed, 3, 2), + r'API Error 0003:') + self.assertRegexpMatches( + self.api.createDeterministicAddresses(self._seed, 1, 4, 2), + r'API Error 0003:') + + self.assertRegexpMatches( + self.api.createDeterministicAddresses('', 1), + r'API Error 0001:') + self.assertRegexpMatches( + self.api.createDeterministicAddresses(self._seed, 1, 2), + r'API Error 0002:') + self.assertRegexpMatches( + self.api.createDeterministicAddresses(self._seed, 0), + r'API Error 0004:') + self.assertRegexpMatches( + self.api.createDeterministicAddresses(self._seed, 1000), + r'API Error 0005:') + + addresses = json.loads( + self.api.createDeterministicAddresses(self._seed, 2, 4) + )['addresses'] + self.assertEqual(len(addresses), 2) + self.assertEqual(addresses[0], 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + for addr in addresses: + self.assertEqual(self.api.deleteAddress(addr), 'success') 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]+$') + if PY3: + self.assertRegex(addr, r'^BM-') + self.assertRegex(addr[3:], r'[a-zA-Z1-9]+$') + else: + self.assertRegexpMatches(addr, r'^BM-') + self.assertRegexpMatches(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') def test_addressbook(self): """Testing API commands for addressbook manipulations""" - # Initially it's empty - self.assertEqual( - json.loads(self.api.listAddressBookEntries()).get('addresses'), - [] - ) - # Add known address - self.api.addAddressBookEntry( - 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', - base64.encodestring('tiger_4') - ) - # Check addressbook entry - entries = json.loads( - self.api.listAddressBookEntries()).get('addresses')[0] - self.assertEqual( - entries['address'], 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') - self.assertEqual( - base64.decodestring(entries['label']), 'tiger_4') - # Remove known address - self.api.deleteAddressBookEntry( - 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') - # Addressbook should be empty again - self.assertEqual( - json.loads(self.api.listAddressBookEntries()).get('addresses'), - [] - ) + if PY3: + # Initially it's empty + self.assertEqual( + json.loads(self.api.listAddressBookEntries()).get('addresses'), + [] + ) + # Add known address + self.api.addAddressBookEntry( + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', + base64.encodebytes('tiger_4'.encode('UTF-8')).decode('utf-8') + ) + # Check addressbook entry + entries = json.loads( + self.api.listAddressBookEntries()).get('addresses')[0] + self.assertEqual( + entries['address'], 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + self.assertEqual( + base64.decodebytes(bytes(entries['label'], 'utf-8')).decode('utf-8'), 'tiger_4') + # Remove known address + self.api.deleteAddressBookEntry( + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + # Addressbook should be empty again + self.assertEqual( + json.loads(self.api.listAddressBookEntries()).get('addresses'), + [] + ) + else: + # Initially it's empty + self.assertEqual( + json.loads(self.api.listAddressBookEntries()).get('addresses'), + [] + ) + # Add known address + self.api.addAddressBookEntry( + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', + base64.encodestring('tiger_4') + ) + # Check addressbook entry + entries = json.loads( + self.api.listAddressBookEntries()).get('addresses')[0] + self.assertEqual( + entries['address'], 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + self.assertEqual( + base64.decodestring(entries['label']), 'tiger_4') + # Remove known address + self.api.deleteAddressBookEntry( + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + # Addressbook should be empty again + self.assertEqual( + json.loads(self.api.listAddressBookEntries()).get('addresses'), + [] + ) def test_subscriptions(self): """Testing the API commands related to subscriptions""" - for s in json.loads(self.api.listSubscriptions())['subscriptions']: - # special address, added when sqlThread starts - if s['address'] == 'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw': - self.assertEqual( - base64.decodestring(s['label']), - 'Bitmessage new releases/announcements') - self.assertTrue(s['enabled']) - break + if PY3: + for s in json.loads(self.api.listSubscriptions())['subscriptions']: + # special address, added when sqlThread starts + if s['address'] == 'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw': + self.assertEqual( + base64.decodebytes(bytes(s['label'], 'utf-8')).decode('utf-8'), + 'Bitmessage new releases/announcements') + self.assertTrue(s['enabled']) + break + else: + self.fail( + 'Could not find Bitmessage new releases/announcements' + ' in subscriptions') + self.assertEqual( + self.api.deleteSubscription('BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw'), + 'Deleted subscription if it existed.') + self.assertEqual( + json.loads(self.api.listSubscriptions())['subscriptions'], []) else: - self.fail( - 'Could not find Bitmessage new releases/announcements' - ' in subscriptions') - self.assertEqual( - self.api.deleteSubscription('BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw'), - 'Deleted subscription if it existed.') - self.assertEqual( - json.loads(self.api.listSubscriptions())['subscriptions'], []) + for s in json.loads(self.api.listSubscriptions())['subscriptions']: + # special address, added when sqlThread starts + if s['address'] == 'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw': + self.assertEqual( + base64.decodestring(s['label']), + 'Bitmessage new releases/announcements') + self.assertTrue(s['enabled']) + break + else: + self.fail( + 'Could not find Bitmessage new releases/announcements' + ' in subscriptions') + self.assertEqual( + self.api.deleteSubscription('BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw'), + 'Deleted subscription if it existed.') + self.assertEqual( + json.loads(self.api.listSubscriptions())['subscriptions'], []) def test_send(self): """Test message sending""" - # self.api.createDeterministicAddresses(self._seed, 1, 4) - addr = self._add_random_address('random_2') - msg = base64.encodestring('test message') - msg_subject = base64.encodestring('test_subject') + if PY3: + addr = str(self._add_random_address('random_2')) + msg = str(base64.encodebytes('test message'.encode('UTF-8')).decode('utf-8')) + msg_subject = str(base64.encodebytes('test_subject'.encode('UTF-8')).decode('utf-8')) + else: + addr = self._add_random_address('random_2') + msg = base64.encodestring('test message') + msg_subject = base64.encodestring('test_subject') ackdata = self.api.sendMessage( 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', addr, msg_subject, msg) try: @@ -277,10 +378,16 @@ class TestAPI(TestAPIProto): def test_send_broadcast(self): """Test broadcast sending""" - addr = self._add_random_address('random_2') - msg = base64.encodestring('test broadcast') - ackdata = self.api.sendBroadcast( - addr, base64.encodestring('test_subject'), msg) + if PY3: + addr = self._add_random_address('random_2') + msg = base64.encodebytes('test broadcast'.encode('UTF-8')).decode('utf-8') + ackdata = self.api.sendBroadcast( + addr, base64.encodebytes('test_subject'.encode('UTF-8')).decode('utf-8'), msg) + else: + addr = self._add_random_address('random_2') + msg = base64.encodestring('test broadcast') + ackdata = self.api.sendBroadcast( + addr, base64.encodestring('test_subject'), msg) try: int(ackdata, 16) status = self.api.getStatus(ackdata) @@ -324,25 +431,48 @@ class TestAPI(TestAPIProto): def test_chan(self): """Testing chan creation/joining""" - # Create chan with known address - self.assertEqual( - self.api.createChan(self._seed), - 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK' - ) - # cleanup - self.assertEqual( - self.api.leaveChan('BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK'), - 'success' - ) - # Join chan with addresses of version 3 or 4 - for addr in ( - 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', - 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN' - ): - self.assertEqual(self.api.joinChan(self._seed, addr), 'success') - self.assertEqual(self.api.leaveChan(addr), 'success') - # Joining with wrong address should fail - self.assertRegexpMatches( - self.api.joinChan(self._seed, 'BM-2cWzSnwjJ7yRP3nLEW'), - r'^API Error 0008:' - ) + if PY3: + # Create chan with known address + self.assertEqual( + self.api.createChan(self._seed.decode("utf-8")), + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK' + ) + # cleanup + self.assertEqual( + self.api.leaveChan('BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK'), + 'success' + ) + # Join chan with addresses of version 3 or 4 + for addr in ( + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', + 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN' + ): + self.assertEqual(self.api.joinChan(self._seed.decode("utf-8"), addr), 'success') + self.assertEqual(self.api.leaveChan(addr), 'success') + # Joining with wrong address should fail + self.assertRegex( + self.api.joinChan(self._seed.decode("utf-8"), 'BM-2cWzSnwjJ7yRP3nLEW'), + r'^API Error 0008:' + ) + else: + self.assertEqual( + self.api.createChan(self._seed), + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK' + ) + # cleanup + self.assertEqual( + self.api.leaveChan('BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK'), + 'success' + ) + # Join chan with addresses of version 3 or 4 + for addr in ( + 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', + 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN' + ): + self.assertEqual(self.api.joinChan(self._seed, addr), 'success') + self.assertEqual(self.api.leaveChan(addr), 'success') + # Joining with wrong address should fail + self.assertRegexpMatches( + self.api.joinChan(self._seed, 'BM-2cWzSnwjJ7yRP3nLEW'), + r'^API Error 0008:' + ) diff --git a/src/tests/test_logger.py b/src/tests/test_logger.py index da0f9341..c9095f2a 100644 --- a/src/tests/test_logger.py +++ b/src/tests/test_logger.py @@ -1,11 +1,14 @@ +# pylint: disable=E1101 """ Testing the logger configuration """ import os import tempfile +import sys from .test_process import TestProcessProto +PY3 = sys.version_info[0] >= 3 class TestLogger(TestProcessProto): @@ -43,7 +46,10 @@ handlers=default cls.log_file = os.path.join(cls.home, 'debug.log') with open(os.path.join(cls.home, 'logging.dat'), 'wb') as dst: - dst.write(cls.conf_template.format(cls.log_file, cls.pattern)) + if PY3: + dst.write(bytes(cls.conf_template.format(cls.log_file, cls.pattern), 'utf-8')) + else: + dst.write(cls.conf_template.format(cls.log_file, cls.pattern)) super(TestLogger, cls).setUpClass() @@ -52,5 +58,9 @@ handlers=default self._stop_process() data = open(self.log_file).read() - self.assertRegexpMatches(data, self.pattern) - self.assertRegexpMatches(data, 'Loaded logger configuration') + if PY3: + self.assertRegex(data, self.pattern) + self.assertRegex(data, 'Loaded logger configuration') + else: + self.assertRegexpMatches(data, self.pattern) + self.assertRegexpMatches(data, 'Loaded logger configuration') diff --git a/src/tests/test_process.py b/src/tests/test_process.py index d976aa18..76be96a0 100644 --- a/src/tests/test_process.py +++ b/src/tests/test_process.py @@ -12,10 +12,7 @@ import unittest import psutil -from .common import cleanup, put_signal_file, skip_python3 - - -skip_python3() +from .common import cleanup, put_signal_file class TestProcessProto(unittest.TestCase):