From 6d98a4ef4408ecab64be485d4071b83ec4b7d660 Mon Sep 17 00:00:00 2001 From: coffeedogs Date: Sun, 21 Oct 2018 17:14:20 +0100 Subject: [PATCH] Changes based on style and lint checks. (final_code_quality_17) --- dev/bloomfiltertest.py | 20 ++++-- src/bitmessageqt/dialogs.py | 34 ++++++---- src/bitmessageqt/newchandialog.py | 52 ++++++++++++--- src/helper_startup.py | 73 +++++++------------- src/highlevelcrypto.py | 106 +++++++++++++++++++----------- src/multiqueue.py | 19 ++++-- 6 files changed, 184 insertions(+), 120 deletions(-) diff --git a/dev/bloomfiltertest.py b/dev/bloomfiltertest.py index 539d00f3..8f7b5f69 100644 --- a/dev/bloomfiltertest.py +++ b/dev/bloomfiltertest.py @@ -1,10 +1,16 @@ -from math import ceil -from os import stat, getenv, path -from pybloom import BloomFilter as BloomFilter1 -from pybloomfilter import BloomFilter as BloomFilter2 +""" +dev/bloomfiltertest.py +====================== + +""" + import sqlite3 +from os import getenv, path from time import time +from pybloom import BloomFilter as BloomFilter1 # pylint: disable=import-error +from pybloomfilter import BloomFilter as BloomFilter2 # pylint: disable=import-error + # Ubuntu: apt-get install python-pybloomfiltermmap conn = sqlite3.connect(path.join(getenv("HOME"), '.config/PyBitmessage/messages.dat')) @@ -41,9 +47,9 @@ for row in cur.fetchall(): except IndexError: pass -#f = open("/home/shurdeek/tmp/bloom.dat", "wb") -#sb1.tofile(f) -#f.close() +# f = open("/home/shurdeek/tmp/bloom.dat", "wb") +# sb1.tofile(f) +# f.close() print "Item count: %i" % (itemcount) diff --git a/src/bitmessageqt/dialogs.py b/src/bitmessageqt/dialogs.py index cb82f348..0dea792f 100644 --- a/src/bitmessageqt/dialogs.py +++ b/src/bitmessageqt/dialogs.py @@ -1,17 +1,21 @@ +""" +src/bitmessageqt/dialogs.py +=========================== +""" + from PyQt4 import QtGui -from tr import _translate -from retranslateui import RetranslateMixin -import widgets -from newchandialog import NewChanDialog -from address_dialogs import ( - AddAddressDialog, NewAddressDialog, NewSubscriptionDialog, - RegenerateAddressesDialog, SpecialAddressBehaviorDialog, EmailGatewayDialog -) - -import paths from version import softwareVersion +import paths +import widgets +from address_dialogs import ( + AddAddressDialog, EmailGatewayDialog, NewAddressDialog, NewSubscriptionDialog, RegenerateAddressesDialog, + SpecialAddressBehaviorDialog +) +from newchandialog import NewChanDialog +from retranslateui import RetranslateMixin +from tr import _translate __all__ = [ "NewChanDialog", "AddAddressDialog", "NewAddressDialog", @@ -21,6 +25,7 @@ __all__ = [ class AboutDialog(QtGui.QDialog, RetranslateMixin): + """The `About` dialog""" def __init__(self, parent=None): super(AboutDialog, self).__init__(parent) widgets.load('about.ui', self) @@ -32,7 +37,7 @@ class AboutDialog(QtGui.QDialog, RetranslateMixin): self.labelVersion.setText( self.labelVersion.text().replace( ':version:', version - ).replace(':branch:', commit or 'v%s' % version) + ).replace(':branch:', commit or 'v%s' % version) ) self.labelVersion.setOpenExternalLinks(True) @@ -48,21 +53,23 @@ class AboutDialog(QtGui.QDialog, RetranslateMixin): class IconGlossaryDialog(QtGui.QDialog, RetranslateMixin): + """The `Icon Glossary` dialog, explaining the status icon colors""" def __init__(self, parent=None, config=None): super(IconGlossaryDialog, self).__init__(parent) widgets.load('iconglossary.ui', self) - # FIXME: check the window title visibility here + # .. todo:: FIXME: check the window title visibility here self.groupBox.setTitle('') self.labelPortNumber.setText(_translate( "iconGlossaryDialog", "You are using TCP port %1. (This can be changed in the settings)." - ).arg(config.getint('bitmessagesettings', 'port'))) + ).arg(config.getint('bitmessagesettings', 'port'))) self.setFixedSize(QtGui.QWidget.sizeHint(self)) class HelpDialog(QtGui.QDialog, RetranslateMixin): + """The `Help` dialog""" def __init__(self, parent=None): super(HelpDialog, self).__init__(parent) widgets.load('help.ui', self) @@ -70,6 +77,7 @@ class HelpDialog(QtGui.QDialog, RetranslateMixin): class ConnectDialog(QtGui.QDialog, RetranslateMixin): + """The `Connect` dialog""" def __init__(self, parent=None): super(ConnectDialog, self).__init__(parent) widgets.load('connect.ui', self) diff --git a/src/bitmessageqt/newchandialog.py b/src/bitmessageqt/newchandialog.py index ed683b13..8db486c1 100644 --- a/src/bitmessageqt/newchandialog.py +++ b/src/bitmessageqt/newchandialog.py @@ -1,41 +1,72 @@ +""" +src/bitmessageqt/newchandialog.py +================================= + +""" + from PyQt4 import QtCore, QtGui +import widgets from addresses import addBMIfNotPresent from addressvalidator import AddressValidator, PassPhraseValidator -from queues import apiAddressGeneratorReturnQueue, addressGeneratorQueue, UISignalQueue +from queues import UISignalQueue, addressGeneratorQueue, apiAddressGeneratorReturnQueue from retranslateui import RetranslateMixin from tr import _translate from utils import str_chan -import widgets + class NewChanDialog(QtGui.QDialog, RetranslateMixin): + """The `New Chan` dialog""" def __init__(self, parent=None): super(NewChanDialog, self).__init__(parent) widgets.load('newchandialog.ui', self) self.parent = parent - self.chanAddress.setValidator(AddressValidator(self.chanAddress, self.chanPassPhrase, self.validatorFeedback, self.buttonBox, False)) - self.chanPassPhrase.setValidator(PassPhraseValidator(self.chanPassPhrase, self.chanAddress, self.validatorFeedback, self.buttonBox, False)) + self.chanAddress.setValidator( + AddressValidator( + self.chanAddress, + self.chanPassPhrase, + self.validatorFeedback, + self.buttonBox, + False)) + self.chanPassPhrase.setValidator( + PassPhraseValidator( + self.chanPassPhrase, + self.chanAddress, + self.validatorFeedback, + self.buttonBox, + False)) self.timer = QtCore.QTimer() - QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.delayedUpdateStatus) - self.timer.start(500) # milliseconds + QtCore.QObject.connect( # pylint: disable=no-member + self.timer, QtCore.SIGNAL("timeout()"), self.delayedUpdateStatus) + self.timer.start(500) # milliseconds self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.show() def delayedUpdateStatus(self): + """Related to updating the UI for the chan passphrase validity""" self.chanPassPhrase.validator().checkQueue() def accept(self): + """Proceed in joining the chan""" self.timer.stop() self.hide() apiAddressGeneratorReturnQueue.queue.clear() if self.chanAddress.text().toUtf8() == "": - addressGeneratorQueue.put(('createChan', 4, 1, str_chan + ' ' + str(self.chanPassPhrase.text().toUtf8()), self.chanPassPhrase.text().toUtf8(), True)) + addressGeneratorQueue.put( + ('createChan', 4, 1, str_chan + ' ' + str(self.chanPassPhrase.text().toUtf8()), + self.chanPassPhrase.text().toUtf8(), + True)) else: - addressGeneratorQueue.put(('joinChan', addBMIfNotPresent(self.chanAddress.text().toUtf8()), str_chan + ' ' + str(self.chanPassPhrase.text().toUtf8()), self.chanPassPhrase.text().toUtf8(), True)) + addressGeneratorQueue.put( + ('joinChan', addBMIfNotPresent(self.chanAddress.text().toUtf8()), + str_chan + ' ' + str(self.chanPassPhrase.text().toUtf8()), + self.chanPassPhrase.text().toUtf8(), + True)) addressGeneratorReturnValue = apiAddressGeneratorReturnQueue.get(True) - if len(addressGeneratorReturnValue) > 0 and addressGeneratorReturnValue[0] != 'chan name does not match address': - UISignalQueue.put(('updateStatusBar', _translate("newchandialog", "Successfully created / joined chan %1").arg(unicode(self.chanPassPhrase.text())))) + if addressGeneratorReturnValue and addressGeneratorReturnValue[0] != 'chan name does not match address': + UISignalQueue.put(('updateStatusBar', _translate( + "newchandialog", "Successfully created / joined chan %1").arg(unicode(self.chanPassPhrase.text())))) self.parent.ui.tabWidget.setCurrentIndex( self.parent.ui.tabWidget.indexOf(self.parent.ui.chans) ) @@ -45,6 +76,7 @@ class NewChanDialog(QtGui.QDialog, RetranslateMixin): self.done(QtGui.QDialog.Rejected) def reject(self): + """Cancel joining the chan""" self.timer.stop() self.hide() UISignalQueue.put(('updateStatusBar', _translate("newchandialog", "Chan creation / joining cancelled"))) diff --git a/src/helper_startup.py b/src/helper_startup.py index 9bca8db6..98795201 100644 --- a/src/helper_startup.py +++ b/src/helper_startup.py @@ -1,16 +1,23 @@ -"""Helper Start performs all the startup operations.""" +""" +src/helper_startup.py +===================== + +Helper Start performs all the startup operations. +""" +# pylint: disable=too-many-branches,too-many-statements +from __future__ import print_function import ConfigParser -from bmconfigparser import BMConfigParser -import defaults -import sys import os import platform +import sys from distutils.version import StrictVersion +import defaults +import helper_random import paths import state -import helper_random +from bmconfigparser import BMConfigParser # The user may de-select Portable Mode in the settings if they want # the config files to stay in the application data folder. @@ -30,6 +37,7 @@ def _loadTrustedPeer(): def loadConfig(): + """Load the config""" config = BMConfigParser() if state.appdata: config.read(state.appdata + 'keys.dat') @@ -44,7 +52,7 @@ def loadConfig(): config.read(paths.lookupExeFolder() + 'keys.dat') try: config.get('bitmessagesettings', 'settingsversion') - print 'Loading config files from same directory as program.' + print('Loading config files from same directory as program.') needToCreateKeysFile = False state.appdata = paths.lookupExeFolder() except: @@ -55,7 +63,7 @@ def loadConfig(): needToCreateKeysFile = config.safeGet( 'bitmessagesettings', 'settingsversion') is None if not needToCreateKeysFile: - print 'Loading existing config files from', state.appdata + print('Loading existing config files from', state.appdata) if needToCreateKeysFile: @@ -80,7 +88,6 @@ def loadConfig(): config.set('bitmessagesettings', 'sockshostname', 'localhost') config.set('bitmessagesettings', 'socksport', '9050') config.set('bitmessagesettings', 'socksauthentication', 'false') - # config.set('bitmessagesettings', 'sockslisten', 'false') config.set('bitmessagesettings', 'socksusername', '') config.set('bitmessagesettings', 'sockspassword', '') config.set('bitmessagesettings', 'keysencrypted', 'false') @@ -92,30 +99,14 @@ def loadConfig(): 'bitmessagesettings', 'defaultpayloadlengthextrabytes', str(defaults.networkDefaultPayloadLengthExtraBytes)) config.set('bitmessagesettings', 'minimizeonclose', 'false') - # config.set( - # 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0') - # config.set( - # 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', - # '0') config.set('bitmessagesettings', 'dontconnect', 'true') - # config.set('bitmessagesettings', 'userlocale', 'system') - # config.set('bitmessagesettings', 'useidenticons', 'True') - # config.set( - # 'bitmessagesettings', 'identiconsuffix', - # ''.join(helper_random.randomchoice( - # "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" - # ) for x in range(12) - # )) # a twelve character pseudo-password to salt the identicons config.set('bitmessagesettings', 'replybelow', 'False') config.set('bitmessagesettings', 'maxdownloadrate', '0') config.set('bitmessagesettings', 'maxuploadrate', '0') - # config.set('bitmessagesettings', 'maxoutboundconnections', '8') - # config.set('bitmessagesettings', 'ttl', '367200') # UI setting to stop trying to send messages after X days/months config.set('bitmessagesettings', 'stopresendingafterxdays', '') config.set('bitmessagesettings', 'stopresendingafterxmonths', '') - # config.set('bitmessagesettings', 'timeperiod', '-1') # Are you hoping to add a new option to the keys.dat file? You're in # the right place for adding it to users who install the software for @@ -127,9 +118,9 @@ def loadConfig(): # Just use the same directory as the program and forget about # the appdata folder state.appdata = '' - print 'Creating new config files in same directory as program.' + print('Creating new config files in same directory as program.') else: - print 'Creating new config files in', state.appdata + print('Creating new config files in', state.appdata) if not os.path.exists(state.appdata): os.makedirs(state.appdata) if not sys.platform.startswith('win'): @@ -142,6 +133,7 @@ def loadConfig(): def updateConfig(): + """Save the config""" config = BMConfigParser() settingsversion = config.getint('bitmessagesettings', 'settingsversion') if settingsversion == 1: @@ -172,20 +164,6 @@ def updateConfig(): 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0') settingsversion = 7 - # Raise the default required difficulty from 1 to 2 - # With the change to protocol v3, this is obsolete. - # if settingsversion == 6: - # if int(shared.config.get( - # 'bitmessagesettings', 'defaultnoncetrialsperbyte' - # )) == defaults.networkDefaultProofOfWorkNonceTrialsPerByte: - # shared.config.set( - # 'bitmessagesettings', 'defaultnoncetrialsperbyte', - # str( - # defaults.networkDefaultProofOfWorkNonceTrialsPerByte - # * 2) - # ) - # settingsversion = 7 - if not config.has_option('bitmessagesettings', 'sockslisten'): config.set('bitmessagesettings', 'sockslisten', 'false') @@ -200,11 +178,11 @@ def updateConfig(): if not config.has_option('bitmessagesettings', 'identiconsuffix'): # acts as a salt config.set( - 'bitmessagesettings', 'identiconsuffix', - ''.join(helper_random.randomchoice( - "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" - ) for x in range(12) - )) # a twelve character pseudo-password to salt the identicons + 'bitmessagesettings', 'identiconsuffix', ''.join( + helper_random.randomchoice("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") + for x in range(12) + ) + ) # a twelve character pseudo-password to salt the identicons # Add settings to support no longer resending messages after # a certain period of time even if we never get an ack @@ -273,9 +251,7 @@ def updateConfig(): str(defaults.ridiculousDifficulty * defaults.networkDefaultProofOfWorkNonceTrialsPerByte) ) - if config.safeGetInt( - 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes' - ) == 0: + if config.safeGetInt('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') == 0: config.set( 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', str(defaults.ridiculousDifficulty * @@ -308,6 +284,7 @@ def updateConfig(): def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections(): + """Check for (mainly XP and Vista) limitations""" try: if sys.platform[0:3] == "win": VER_THIS = StrictVersion(platform.version()) diff --git a/src/highlevelcrypto.py b/src/highlevelcrypto.py index 8729ec5c..02fb85ab 100644 --- a/src/highlevelcrypto.py +++ b/src/highlevelcrypto.py @@ -1,39 +1,65 @@ +""" +src/highlevelcrypto.py +====================== +""" + from binascii import hexlify -from bmconfigparser import BMConfigParser + import pyelliptic -from pyelliptic import arithmetic as a, OpenSSL +from bmconfigparser import BMConfigParser +from pyelliptic import OpenSSL +from pyelliptic import arithmetic as a + + def makeCryptor(privkey): + """Return a private pyelliptic.ECC() instance""" private_key = a.changebase(privkey, 16, 256, minlen=32) public_key = pointMult(private_key) privkey_bin = '\x02\xca\x00\x20' + private_key pubkey_bin = '\x02\xca\x00\x20' + public_key[1:-32] + '\x00\x20' + public_key[-32:] - cryptor = pyelliptic.ECC(curve='secp256k1',privkey=privkey_bin,pubkey=pubkey_bin) + cryptor = pyelliptic.ECC(curve='secp256k1', privkey=privkey_bin, pubkey=pubkey_bin) return cryptor + + def hexToPubkey(pubkey): - pubkey_raw = a.changebase(pubkey[2:],16,256,minlen=64) - pubkey_bin = '\x02\xca\x00 '+pubkey_raw[:32]+'\x00 '+pubkey_raw[32:] + """Convert a pubkey from hex to binary""" + pubkey_raw = a.changebase(pubkey[2:], 16, 256, minlen=64) + pubkey_bin = '\x02\xca\x00 ' + pubkey_raw[:32] + '\x00 ' + pubkey_raw[32:] return pubkey_bin + + def makePubCryptor(pubkey): + """Return a public pyelliptic.ECC() instance""" pubkey_bin = hexToPubkey(pubkey) - return pyelliptic.ECC(curve='secp256k1',pubkey=pubkey_bin) -# Converts hex private key into hex public key + return pyelliptic.ECC(curve='secp256k1', pubkey=pubkey_bin) + + def privToPub(privkey): + """Converts hex private key into hex public key""" private_key = a.changebase(privkey, 16, 256, minlen=32) public_key = pointMult(private_key) return hexlify(public_key) -# Encrypts message with hex public key -def encrypt(msg,hexPubkey): - return pyelliptic.ECC(curve='secp256k1').encrypt(msg,hexToPubkey(hexPubkey)) -# Decrypts message with hex private key -def decrypt(msg,hexPrivkey): + + +def encrypt(msg, hexPubkey): + """Encrypts message with hex public key""" + return pyelliptic.ECC(curve='secp256k1').encrypt(msg, hexToPubkey(hexPubkey)) + + +def decrypt(msg, hexPrivkey): + """Decrypts message with hex private key""" return makeCryptor(hexPrivkey).decrypt(msg) -# Decrypts message with an existing pyelliptic.ECC.ECC object -def decryptFast(msg,cryptor): + + +def decryptFast(msg, cryptor): + """Decrypts message with an existing pyelliptic.ECC.ECC object""" return cryptor.decrypt(msg) -# Signs with hex private key -def sign(msg,hexPrivkey): - # pyelliptic is upgrading from SHA1 to SHA256 for signing. We must - # upgrade PyBitmessage gracefully. + + +def sign(msg, hexPrivkey): + """Signs with hex private key""" + # pyelliptic is upgrading from SHA1 to SHA256 for signing. We must + # upgrade PyBitmessage gracefully. # https://github.com/yann2192/pyelliptic/pull/33 # More discussion: https://github.com/yann2192/pyelliptic/issues/32 digestAlg = BMConfigParser().safeGet('bitmessagesettings', 'digestalg', 'sha1') @@ -45,57 +71,61 @@ def sign(msg,hexPrivkey): return makeCryptor(hexPrivkey).sign(msg, digest_alg=OpenSSL.EVP_sha256) else: raise ValueError("Unknown digest algorithm %s" % (digestAlg)) -# Verifies with hex public key -def verify(msg,sig,hexPubkey): + + +def verify(msg, sig, hexPubkey): + """Verifies with hex public key""" # As mentioned above, we must upgrade gracefully to use SHA256. So # let us check the signature using both SHA1 and SHA256 and if one - # of them passes then we will be satisfied. Eventually this can - # be simplified and we'll only check with SHA256. + # of them passes then we will be satisfied. Eventually this can + # be simplified and we'll only check with SHA256. try: - sigVerifyPassed = makePubCryptor(hexPubkey).verify(sig,msg,digest_alg=OpenSSL.digest_ecdsa_sha1) # old SHA1 algorithm. + # old SHA1 algorithm. + sigVerifyPassed = makePubCryptor(hexPubkey).verify(sig, msg, digest_alg=OpenSSL.digest_ecdsa_sha1) except: sigVerifyPassed = False if sigVerifyPassed: # The signature check passed using SHA1 return True - # The signature check using SHA1 failed. Let us try it with SHA256. + # The signature check using SHA1 failed. Let us try it with SHA256. try: - return makePubCryptor(hexPubkey).verify(sig,msg,digest_alg=OpenSSL.EVP_sha256) + return makePubCryptor(hexPubkey).verify(sig, msg, digest_alg=OpenSSL.EVP_sha256) except: return False -# Does an EC point multiplication; turns a private key into a public key. + def pointMult(secret): + """ + Does an EC point multiplication; turns a private key into a public key. + + Evidently, this type of error can occur very rarely: + + File "highlevelcrypto.py", line 54, in pointMult + group = OpenSSL.EC_KEY_get0_group(k) + WindowsError: exception: access violation reading 0x0000000000000008 + """ while True: try: - """ - Evidently, this type of error can occur very rarely: - - File "highlevelcrypto.py", line 54, in pointMult - group = OpenSSL.EC_KEY_get0_group(k) - WindowsError: exception: access violation reading 0x0000000000000008 - """ k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1')) priv_key = OpenSSL.BN_bin2bn(secret, 32, None) group = OpenSSL.EC_KEY_get0_group(k) pub_key = OpenSSL.EC_POINT_new(group) - + OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, None) OpenSSL.EC_KEY_set_private_key(k, priv_key) OpenSSL.EC_KEY_set_public_key(k, pub_key) - + size = OpenSSL.i2o_ECPublicKey(k, None) mb = OpenSSL.create_string_buffer(size) OpenSSL.i2o_ECPublicKey(k, OpenSSL.byref(OpenSSL.pointer(mb))) - + OpenSSL.EC_POINT_free(pub_key) OpenSSL.BN_free(priv_key) OpenSSL.EC_KEY_free(k) return mb.raw - except Exception as e: + except Exception: import traceback import time traceback.print_exc() time.sleep(0.2) - diff --git a/src/multiqueue.py b/src/multiqueue.py index be5ce44f..8c64d33d 100644 --- a/src/multiqueue.py +++ b/src/multiqueue.py @@ -1,10 +1,19 @@ -from collections import deque +""" +src/multiqueue.py +================= +""" + import Queue -import random +from collections import deque + import helper_random + class MultiQueue(Queue.Queue): + """A base queue class""" + # pylint: disable=redefined-builtin,attribute-defined-outside-init defaultQueueCount = 10 + def __init__(self, maxsize=0, count=0): if not count: self.queueCount = MultiQueue.defaultQueueCount @@ -16,7 +25,7 @@ class MultiQueue(Queue.Queue): def _init(self, maxsize): self.iter = 0 self.queues = [] - for i in range(self.queueCount): + for _ in range(self.queueCount): self.queues.append(deque()) def _qsize(self, len=len): @@ -24,7 +33,7 @@ class MultiQueue(Queue.Queue): # Put a new item in the queue def _put(self, item): - #self.queue.append(item) + # self.queue.append(item) self.queues[helper_random.randomrandrange(self.queueCount)].append((item)) # Get an item from the queue @@ -32,7 +41,9 @@ class MultiQueue(Queue.Queue): return self.queues[self.iter].popleft() def iterate(self): + """Increment the iteration counter""" self.iter = (self.iter + 1) % self.queueCount def totalSize(self): + """Return the total number of items in all the queues""" return sum(len(x) for x in self.queues)