diff --git a/src/bitmessageqt/account.py b/src/bitmessageqt/account.py index 92d497f8..cf3373db 100644 --- a/src/bitmessageqt/account.py +++ b/src/bitmessageqt/account.py @@ -1,26 +1,58 @@ -from PyQt4 import QtCore, QtGui +# pylint: disable=too-many-instance-attributes,attribute-defined-outside-init +""" +account.py +========== -import queues +Account related functions. + +""" + +from __future__ import absolute_import + +import inspect import re import sys -import inspect -from helper_sql import * -from helper_ackPayload import genAckPayload -from addresses import decodeAddress -from bmconfigparser import BMConfigParser -from foldertree import AccountMixin -from pyelliptic.openssl import OpenSSL -from utils import str_broadcast_subscribers import time +from PyQt4 import QtGui + +import queues +from addresses import decodeAddress +from bmconfigparser import BMConfigParser +from helper_ackPayload import genAckPayload +from helper_sql import sqlQuery, sqlExecute +from .foldertree import AccountMixin +from .utils import str_broadcast_subscribers + + def getSortedAccounts(): + """Get a sorted list of configSections""" + configSections = BMConfigParser().addresses() - configSections.sort(cmp = - lambda x,y: cmp(unicode(BMConfigParser().get(x, 'label'), 'utf-8').lower(), unicode(BMConfigParser().get(y, 'label'), 'utf-8').lower()) - ) + configSections.sort( + cmp=lambda x, y: cmp( + unicode( + BMConfigParser().get( + x, + 'label'), + 'utf-8').lower(), + unicode( + BMConfigParser().get( + y, + 'label'), + 'utf-8').lower())) return configSections -def getSortedSubscriptions(count = False): + +def getSortedSubscriptions(count=False): + """ + Actually return a grouped dictionary rather than a sorted list + + :param count: Whether to count messages for each fromaddress in the inbox + :type count: bool, default False + :retuns: dict keys are addresses, values are dicts containing settings + :rtype: dict, default {} + """ queryreturn = sqlQuery('SELECT label, address, enabled FROM subscriptions ORDER BY label COLLATE NOCASE ASC') ret = {} for row in queryreturn: @@ -37,7 +69,7 @@ def getSortedSubscriptions(count = False): GROUP BY inbox.fromaddress, folder''', str_broadcast_subscribers) for row in queryreturn: address, folder, cnt = row - if not folder in ret[address]: + if folder not in ret[address]: ret[address][folder] = { 'label': ret[address]['inbox']['label'], 'enabled': ret[address]['inbox']['enabled'] @@ -45,9 +77,11 @@ def getSortedSubscriptions(count = False): ret[address][folder]['count'] = cnt return ret + def accountClass(address): + """Return a BMAccount for the address""" if not BMConfigParser().has_section(address): - # FIXME: This BROADCAST section makes no sense + # .. todo:: This BROADCAST section makes no sense if address == str_broadcast_subscribers: subscription = BroadcastAccount(address) if subscription.type != AccountMixin.BROADCAST: @@ -60,8 +94,7 @@ def accountClass(address): return subscription try: gateway = BMConfigParser().get(address, "gateway") - for name, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass): -# obj = g(address) + for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass): if issubclass(cls, GatewayAccount) and cls.gatewayName == gateway: return cls(address) # general gateway @@ -70,12 +103,15 @@ def accountClass(address): pass # no gateway return BMAccount(address) - -class AccountColor(AccountMixin): - def __init__(self, address, type = None): + + +class AccountColor(AccountMixin): # pylint: disable=too-few-public-methods + """Set the type of account""" + + def __init__(self, address, address_type=None): self.isEnabled = True self.address = address - if type is None: + if address_type is None: if address is None: self.type = AccountMixin.ALL elif BMConfigParser().safeGetBoolean(self.address, 'mailinglist'): @@ -83,16 +119,18 @@ class AccountColor(AccountMixin): elif BMConfigParser().safeGetBoolean(self.address, 'chan'): self.type = AccountMixin.CHAN elif sqlQuery( - '''select label from subscriptions where address=?''', self.address): + '''select label from subscriptions where address=?''', self.address): self.type = AccountMixin.SUBSCRIPTION else: self.type = AccountMixin.NORMAL else: - self.type = type + self.type = address_type + - class BMAccount(object): - def __init__(self, address = None): + """Encapsulate a Bitmessage account""" + + def __init__(self, address=None): self.address = address self.type = AccountMixin.NORMAL if BMConfigParser().has_section(address): @@ -108,7 +146,8 @@ class BMAccount(object): if queryreturn: self.type = AccountMixin.SUBSCRIPTION - def getLabel(self, address = None): + def getLabel(self, address=None): + """Get a label for this bitmessage account""" if address is None: address = self.address label = address @@ -126,8 +165,10 @@ class BMAccount(object): for row in queryreturn: label, = row return label - + def parseMessage(self, toAddress, fromAddress, subject, message): + """Set metadata and address labels on self""" + self.toAddress = toAddress self.fromAddress = fromAddress if isinstance(subject, unicode): @@ -140,36 +181,45 @@ class BMAccount(object): class NoAccount(BMAccount): - def __init__(self, address = None): + """Override the __init__ method on a BMAccount""" + + def __init__(self, address=None): # pylint: disable=super-init-not-called self.address = address self.type = AccountMixin.NORMAL - def getLabel(self, address = None): + def getLabel(self, address=None): if address is None: address = self.address return address - + class SubscriptionAccount(BMAccount): + """Encapsulate a subscription account""" pass - + class BroadcastAccount(BMAccount): + """Encapsulate a broadcast account""" pass - - + + class GatewayAccount(BMAccount): + """Encapsulate a gateway account""" + gatewayName = None ALL_OK = 0 REGISTRATION_DENIED = 1 + def __init__(self, address): super(GatewayAccount, self).__init__(address) - + def send(self): + """Override the send method for gateway accounts""" + + # pylint: disable=unused-variable status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.toAddress) stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel') ackdata = genAckPayload(streamNumber, stealthLevel) - t = () sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', '', @@ -179,47 +229,52 @@ class GatewayAccount(BMAccount): self.subject, self.message, ackdata, - int(time.time()), # sentTime (this will never change) - int(time.time()), # lastActionTime - 0, # sleepTill time. This will get set when the POW gets done. + int(time.time()), # sentTime (this will never change) + int(time.time()), # lastActionTime + 0, # sleepTill time. This will get set when the POW gets done. 'msgqueued', - 0, # retryNumber - 'sent', # folder - 2, # encodingtype - min(BMConfigParser().getint('bitmessagesettings', 'ttl'), 86400 * 2) # not necessary to have a TTL higher than 2 days + 0, # retryNumber + 'sent', # folder + 2, # encodingtype + # not necessary to have a TTL higher than 2 days + min(BMConfigParser().getint('bitmessagesettings', 'ttl'), 86400 * 2) ) queues.workerQueue.put(('sendmessage', self.toAddress)) - - def parseMessage(self, toAddress, fromAddress, subject, message): - super(GatewayAccount, self).parseMessage(toAddress, fromAddress, subject, message) + class MailchuckAccount(GatewayAccount): + """Encapsulate a particular kind of gateway account""" + # set "gateway" in keys.dat to this gatewayName = "mailchuck" registrationAddress = "BM-2cVYYrhaY5Gbi3KqrX9Eae2NRNrkfrhCSA" unregistrationAddress = "BM-2cVMAHTRjZHCTPMue75XBK5Tco175DtJ9J" relayAddress = "BM-2cWim8aZwUNqxzjMxstnUMtVEUQJeezstf" - regExpIncoming = re.compile("(.*)MAILCHUCK-FROM::(\S+) \| (.*)") - regExpOutgoing = re.compile("(\S+) (.*)") + regExpIncoming = re.compile(r"(.*)MAILCHUCK-FROM::(\S+) \| (.*)") + regExpOutgoing = re.compile(r"(\S+) (.*)") + def __init__(self, address): super(MailchuckAccount, self).__init__(address) self.feedback = self.ALL_OK - + def createMessage(self, toAddress, fromAddress, subject, message): + """createMessage specific to a MailchuckAccount""" self.subject = toAddress + " " + subject self.toAddress = self.relayAddress self.fromAddress = fromAddress self.message = message - + def register(self, email): + """register specific to a MailchuckAccount""" self.toAddress = self.registrationAddress self.subject = email self.message = "" self.fromAddress = self.address self.send() - + def unregister(self): + """unregister specific to a MailchuckAccount""" self.toAddress = self.unregistrationAddress self.subject = "" self.message = "" @@ -227,6 +282,7 @@ class MailchuckAccount(GatewayAccount): self.send() def status(self): + """status specific to a MailchuckAccount""" self.toAddress = self.registrationAddress self.subject = "status" self.message = "" @@ -234,12 +290,16 @@ class MailchuckAccount(GatewayAccount): self.send() def settings(self): + """settings specific to a MailchuckAccount""" + self.toAddress = self.registrationAddress self.subject = "config" - self.message = QtGui.QApplication.translate("Mailchuck", """# You can use this to configure your email gateway account + self.message = QtGui.QApplication.translate( + "Mailchuck", + """# You can use this to configure your email gateway account # Uncomment the setting you want to use # Here are the options: -# +# # pgp: server # The email gateway will create and maintain PGP keys for you and sign, verify, # encrypt and decrypt on your behalf. When you want to use PGP but are lazy, @@ -255,7 +315,7 @@ class MailchuckAccount(GatewayAccount): # # attachments: no # Attachments will be ignored. -# +# # archive: yes # Your incoming emails will be archived on the server. Use this if you need # help with debugging problems or you need a third party proof of emails. This @@ -279,10 +339,12 @@ class MailchuckAccount(GatewayAccount): self.fromAddress = self.address def parseMessage(self, toAddress, fromAddress, subject, message): + """parseMessage specific to a MailchuckAccount""" + super(MailchuckAccount, self).parseMessage(toAddress, fromAddress, subject, message) if fromAddress == self.relayAddress: matches = self.regExpIncoming.search(subject) - if not matches is None: + if matches is not None: self.subject = "" if not matches.group(1) is None: self.subject += matches.group(1) @@ -293,7 +355,7 @@ class MailchuckAccount(GatewayAccount): self.fromAddress = matches.group(2) if toAddress == self.relayAddress: matches = self.regExpOutgoing.search(subject) - if not matches is None: + if matches is not None: if not matches.group(2) is None: self.subject = matches.group(2) if not matches.group(1) is None: diff --git a/src/bitmessageqt/settings.py b/src/bitmessageqt/settings.py index 4342fd09..22c38a62 100644 --- a/src/bitmessageqt/settings.py +++ b/src/bitmessageqt/settings.py @@ -1,15 +1,23 @@ # -*- coding: utf-8 -*- +# pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements,attribute-defined-outside-init +""" +Form implementation generated from reading ui file 'settings.ui' -# Form implementation generated from reading ui file 'settings.ui' -# -# Created: Thu Dec 25 23:21:20 2014 -# by: PyQt4 UI code generator 4.10.3 -# -# WARNING! All changes made in this file will be lost! +Created: Thu Dec 25 23:21:20 2014 + by: PyQt4 UI code generator 4.10.3 + +WARNING! All changes made in this file will be lost! +""" + +from __future__ import absolute_import + +from sys import platform from PyQt4 import QtCore, QtGui -from languagebox import LanguageBox -from sys import platform + +from . import bitmessage_icons_rc # pylint: disable=unused-import +from .languagebox import LanguageBox + try: _fromUtf8 = QtCore.QString.fromUtf8 @@ -19,21 +27,27 @@ except AttributeError: try: _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig, _encoding) except AttributeError: def _translate(context, text, disambig): return QtGui.QApplication.translate(context, text, disambig) + class Ui_settingsDialog(object): + """Encapsulate a UI settings dialog object""" + def setupUi(self, settingsDialog): + """Set up the UI""" + settingsDialog.setObjectName(_fromUtf8("settingsDialog")) settingsDialog.resize(521, 413) self.gridLayout = QtGui.QGridLayout(settingsDialog) self.gridLayout.setObjectName(_fromUtf8("gridLayout")) self.buttonBox = QtGui.QDialogButtonBox(settingsDialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok) self.buttonBox.setObjectName(_fromUtf8("buttonBox")) self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1) self.tabWidgetSettings = QtGui.QTabWidget(settingsDialog) @@ -64,7 +78,8 @@ class Ui_settingsDialog(object): self.formLayout.setWidget(1, QtGui.QFormLayout.SpanningRole, self.groupBoxTray) self.checkBoxHideTrayConnectionNotifications = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxHideTrayConnectionNotifications.setChecked(False) - self.checkBoxHideTrayConnectionNotifications.setObjectName(_fromUtf8("checkBoxHideTrayConnectionNotifications")) + self.checkBoxHideTrayConnectionNotifications.setObjectName( + _fromUtf8("checkBoxHideTrayConnectionNotifications")) self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.checkBoxHideTrayConnectionNotifications) self.checkBoxShowTrayNotifications = QtGui.QCheckBox(self.tabUserInterface) self.checkBoxShowTrayNotifications.setObjectName(_fromUtf8("checkBoxShowTrayNotifications")) @@ -96,7 +111,7 @@ class Ui_settingsDialog(object): self.formLayout_2.setObjectName(_fromUtf8("formLayout_2")) self.languageComboBox = LanguageBox(self.groupBox) self.languageComboBox.setMinimumSize(QtCore.QSize(100, 0)) - self.languageComboBox.setObjectName(_fromUtf8("languageComboBox")) + self.languageComboBox.setObjectName(_fromUtf8("languageComboBox")) # pylint: disable=not-callable self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.languageComboBox) self.formLayout.setWidget(9, QtGui.QFormLayout.FieldRole, self.groupBox) self.tabWidgetSettings.addTab(self.tabUserInterface, _fromUtf8("")) @@ -108,8 +123,6 @@ class Ui_settingsDialog(object): self.groupBox1.setObjectName(_fromUtf8("groupBox1")) self.gridLayout_3 = QtGui.QGridLayout(self.groupBox1) self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) - #spacerItem = QtGui.QSpacerItem(125, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - #self.gridLayout_3.addItem(spacerItem, 0, 0, 1, 1) self.label = QtGui.QLabel(self.groupBox1) self.label.setObjectName(_fromUtf8("label")) self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1, QtCore.Qt.AlignRight) @@ -165,7 +178,8 @@ class Ui_settingsDialog(object): self.lineEditMaxOutboundConnections.setSizePolicy(sizePolicy) self.lineEditMaxOutboundConnections.setMaximumSize(QtCore.QSize(60, 16777215)) self.lineEditMaxOutboundConnections.setObjectName(_fromUtf8("lineEditMaxOutboundConnections")) - self.lineEditMaxOutboundConnections.setValidator(QtGui.QIntValidator(0, 8, self.lineEditMaxOutboundConnections)) + self.lineEditMaxOutboundConnections.setValidator( + QtGui.QIntValidator(0, 8, self.lineEditMaxOutboundConnections)) self.gridLayout_9.addWidget(self.lineEditMaxOutboundConnections, 2, 2, 1, 1) self.gridLayout_4.addWidget(self.groupBox_3, 2, 0, 1, 1) self.groupBox_2 = QtGui.QGroupBox(self.tabNetworkSettings) @@ -207,7 +221,8 @@ class Ui_settingsDialog(object): self.gridLayout_2.addWidget(self.label_6, 2, 4, 1, 1) self.lineEditSocksPassword = QtGui.QLineEdit(self.groupBox_2) self.lineEditSocksPassword.setEnabled(False) - self.lineEditSocksPassword.setInputMethodHints(QtCore.Qt.ImhHiddenText|QtCore.Qt.ImhNoAutoUppercase|QtCore.Qt.ImhNoPredictiveText) + self.lineEditSocksPassword.setInputMethodHints( + QtCore.Qt.ImhHiddenText | QtCore.Qt.ImhNoAutoUppercase | QtCore.Qt.ImhNoPredictiveText) self.lineEditSocksPassword.setEchoMode(QtGui.QLineEdit.Password) self.lineEditSocksPassword.setObjectName(_fromUtf8("lineEditSocksPassword")) self.gridLayout_2.addWidget(self.lineEditSocksPassword, 2, 5, 1, 1) @@ -215,7 +230,7 @@ class Ui_settingsDialog(object): self.checkBoxSocksListen.setObjectName(_fromUtf8("checkBoxSocksListen")) self.gridLayout_2.addWidget(self.checkBoxSocksListen, 3, 1, 1, 4) self.comboBoxProxyType = QtGui.QComboBox(self.groupBox_2) - self.comboBoxProxyType.setObjectName(_fromUtf8("comboBoxProxyType")) + self.comboBoxProxyType.setObjectName(_fromUtf8("comboBoxProxyType")) # pylint: disable=not-callable self.comboBoxProxyType.addItem(_fromUtf8("")) self.comboBoxProxyType.addItem(_fromUtf8("")) self.comboBoxProxyType.addItem(_fromUtf8("")) @@ -229,7 +244,7 @@ class Ui_settingsDialog(object): self.gridLayout_6 = QtGui.QGridLayout(self.tabDemandedDifficulty) self.gridLayout_6.setObjectName(_fromUtf8("gridLayout_6")) self.label_9 = QtGui.QLabel(self.tabDemandedDifficulty) - self.label_9.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_9.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_9.setObjectName(_fromUtf8("label_9")) self.gridLayout_6.addWidget(self.label_9, 1, 1, 1, 1) self.label_10 = QtGui.QLabel(self.tabDemandedDifficulty) @@ -237,7 +252,7 @@ class Ui_settingsDialog(object): self.label_10.setObjectName(_fromUtf8("label_10")) self.gridLayout_6.addWidget(self.label_10, 2, 0, 1, 3) self.label_11 = QtGui.QLabel(self.tabDemandedDifficulty) - self.label_11.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_11.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_11.setObjectName(_fromUtf8("label_11")) self.gridLayout_6.addWidget(self.label_11, 3, 1, 1, 1) self.label_8 = QtGui.QLabel(self.tabDemandedDifficulty) @@ -285,7 +300,7 @@ class Ui_settingsDialog(object): self.gridLayout_7.addItem(spacerItem6, 1, 0, 1, 1) self.label_13 = QtGui.QLabel(self.tabMaxAcceptableDifficulty) self.label_13.setLayoutDirection(QtCore.Qt.LeftToRight) - self.label_13.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_13.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_13.setObjectName(_fromUtf8("label_13")) self.gridLayout_7.addWidget(self.label_13, 1, 1, 1, 1) self.lineEditMaxAcceptableTotalDifficulty = QtGui.QLineEdit(self.tabMaxAcceptableDifficulty) @@ -300,7 +315,7 @@ class Ui_settingsDialog(object): spacerItem7 = QtGui.QSpacerItem(102, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.gridLayout_7.addItem(spacerItem7, 2, 0, 1, 1) self.label_14 = QtGui.QLabel(self.tabMaxAcceptableDifficulty) - self.label_14.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_14.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_14.setObjectName(_fromUtf8("label_14")) self.gridLayout_7.addWidget(self.label_14, 2, 1, 1, 1) self.lineEditMaxAcceptableSmallMessageDifficulty = QtGui.QLineEdit(self.tabMaxAcceptableDifficulty) @@ -310,7 +325,8 @@ class Ui_settingsDialog(object): sizePolicy.setHeightForWidth(self.lineEditMaxAcceptableSmallMessageDifficulty.sizePolicy().hasHeightForWidth()) self.lineEditMaxAcceptableSmallMessageDifficulty.setSizePolicy(sizePolicy) self.lineEditMaxAcceptableSmallMessageDifficulty.setMaximumSize(QtCore.QSize(70, 16777215)) - self.lineEditMaxAcceptableSmallMessageDifficulty.setObjectName(_fromUtf8("lineEditMaxAcceptableSmallMessageDifficulty")) + self.lineEditMaxAcceptableSmallMessageDifficulty.setObjectName( + _fromUtf8("lineEditMaxAcceptableSmallMessageDifficulty")) self.gridLayout_7.addWidget(self.lineEditMaxAcceptableSmallMessageDifficulty, 2, 2, 1, 1) spacerItem8 = QtGui.QSpacerItem(20, 147, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.gridLayout_7.addItem(spacerItem8, 3, 1, 1, 1) @@ -332,7 +348,7 @@ class Ui_settingsDialog(object): self.label_16.setObjectName(_fromUtf8("label_16")) self.gridLayout_8.addWidget(self.label_16, 0, 0, 1, 3) self.label_17 = QtGui.QLabel(self.tabNamecoin) - self.label_17.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_17.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_17.setObjectName(_fromUtf8("label_17")) self.gridLayout_8.addWidget(self.label_17, 2, 1, 1, 1) self.lineEditNamecoinHost = QtGui.QLineEdit(self.tabNamecoin) @@ -344,7 +360,7 @@ class Ui_settingsDialog(object): self.gridLayout_8.addItem(spacerItem11, 4, 0, 1, 1) self.label_18 = QtGui.QLabel(self.tabNamecoin) self.label_18.setEnabled(True) - self.label_18.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_18.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_18.setObjectName(_fromUtf8("label_18")) self.gridLayout_8.addWidget(self.label_18, 3, 1, 1, 1) self.lineEditNamecoinPort = QtGui.QLineEdit(self.tabNamecoin) @@ -353,7 +369,7 @@ class Ui_settingsDialog(object): spacerItem12 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.gridLayout_8.addItem(spacerItem12, 8, 1, 1, 1) self.labelNamecoinUser = QtGui.QLabel(self.tabNamecoin) - self.labelNamecoinUser.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.labelNamecoinUser.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.labelNamecoinUser.setObjectName(_fromUtf8("labelNamecoinUser")) self.gridLayout_8.addWidget(self.labelNamecoinUser, 4, 1, 1, 1) self.lineEditNamecoinUser = QtGui.QLineEdit(self.tabNamecoin) @@ -362,11 +378,13 @@ class Ui_settingsDialog(object): spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.gridLayout_8.addItem(spacerItem13, 5, 0, 1, 1) self.labelNamecoinPassword = QtGui.QLabel(self.tabNamecoin) - self.labelNamecoinPassword.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.labelNamecoinPassword.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.labelNamecoinPassword.setObjectName(_fromUtf8("labelNamecoinPassword")) self.gridLayout_8.addWidget(self.labelNamecoinPassword, 5, 1, 1, 1) self.lineEditNamecoinPassword = QtGui.QLineEdit(self.tabNamecoin) - self.lineEditNamecoinPassword.setInputMethodHints(QtCore.Qt.ImhHiddenText|QtCore.Qt.ImhNoAutoUppercase|QtCore.Qt.ImhNoPredictiveText) + self.lineEditNamecoinPassword.setInputMethodHints( + QtCore.Qt.ImhHiddenText | QtCore.Qt.ImhNoAutoUppercase | QtCore.Qt.ImhNoPredictiveText) self.lineEditNamecoinPassword.setEchoMode(QtGui.QLineEdit.Password) self.lineEditNamecoinPassword.setObjectName(_fromUtf8("lineEditNamecoinPassword")) self.gridLayout_8.addWidget(self.lineEditNamecoinPassword, 5, 2, 1, 1) @@ -405,11 +423,11 @@ class Ui_settingsDialog(object): self.widget.setObjectName(_fromUtf8("widget")) self.label_19 = QtGui.QLabel(self.widget) self.label_19.setGeometry(QtCore.QRect(10, 20, 101, 20)) - self.label_19.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_19.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_19.setObjectName(_fromUtf8("label_19")) self.label_20 = QtGui.QLabel(self.widget) self.label_20.setGeometry(QtCore.QRect(30, 40, 80, 16)) - self.label_20.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_20.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter) self.label_20.setObjectName(_fromUtf8("label_20")) self.lineEditDays = QtGui.QLineEdit(self.widget) self.lineEditDays.setGeometry(QtCore.QRect(113, 20, 51, 20)) @@ -431,10 +449,20 @@ class Ui_settingsDialog(object): self.retranslateUi(settingsDialog) self.tabWidgetSettings.setCurrentIndex(0) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), settingsDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), settingsDialog.reject) - QtCore.QObject.connect(self.checkBoxAuthentication, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.lineEditSocksUsername.setEnabled) - QtCore.QObject.connect(self.checkBoxAuthentication, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.lineEditSocksPassword.setEnabled) + QtCore.QObject.connect( # pylint: disable=no-member + self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), settingsDialog.accept) + QtCore.QObject.connect( # pylint: disable=no-member + self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), settingsDialog.reject) + QtCore.QObject.connect( # pylint: disable=no-member + self.checkBoxAuthentication, + QtCore.SIGNAL( + _fromUtf8("toggled(bool)")), + self.lineEditSocksUsername.setEnabled) + QtCore.QObject.connect( # pylint: disable=no-member + self.checkBoxAuthentication, + QtCore.SIGNAL( + _fromUtf8("toggled(bool)")), + self.lineEditSocksPassword.setEnabled) QtCore.QMetaObject.connectSlotsByName(settingsDialog) settingsDialog.setTabOrder(self.tabWidgetSettings, self.checkBoxStartOnLogon) settingsDialog.setTabOrder(self.checkBoxStartOnLogon, self.checkBoxStartInTray) @@ -450,22 +478,47 @@ class Ui_settingsDialog(object): settingsDialog.setTabOrder(self.checkBoxSocksListen, self.buttonBox) def retranslateUi(self, settingsDialog): + """Re-translate the UI into the supported languages""" + settingsDialog.setWindowTitle(_translate("settingsDialog", "Settings", None)) self.checkBoxStartOnLogon.setText(_translate("settingsDialog", "Start Bitmessage on user login", None)) self.groupBoxTray.setTitle(_translate("settingsDialog", "Tray", None)) - self.checkBoxStartInTray.setText(_translate("settingsDialog", "Start Bitmessage in the tray (don\'t show main window)", None)) + self.checkBoxStartInTray.setText( + _translate( + "settingsDialog", + "Start Bitmessage in the tray (don\'t show main window)", + None)) self.checkBoxMinimizeToTray.setText(_translate("settingsDialog", "Minimize to tray", None)) self.checkBoxTrayOnClose.setText(_translate("settingsDialog", "Close to tray", None)) - self.checkBoxHideTrayConnectionNotifications.setText(_translate("settingsDialog", "Hide connection notifications", None)) - self.checkBoxShowTrayNotifications.setText(_translate("settingsDialog", "Show notification when message received", None)) + self.checkBoxHideTrayConnectionNotifications.setText( + _translate("settingsDialog", "Hide connection notifications", None)) + self.checkBoxShowTrayNotifications.setText( + _translate( + "settingsDialog", + "Show notification when message received", + None)) self.checkBoxPortableMode.setText(_translate("settingsDialog", "Run in Portable Mode", None)) - self.PortableModeDescription.setText(_translate("settingsDialog", "In Portable Mode, messages and config files are stored in the same directory as the program rather than the normal application-data folder. This makes it convenient to run Bitmessage from a USB thumb drive.", None)) - self.checkBoxWillinglySendToMobile.setText(_translate("settingsDialog", "Willingly include unencrypted destination address when sending to a mobile device", None)) + self.PortableModeDescription.setText( + _translate( + "settingsDialog", + "In Portable Mode, messages and config files are stored in the same directory as the" + " program rather than the normal application-data folder. This makes it convenient to" + " run Bitmessage from a USB thumb drive.", + None)) + self.checkBoxWillinglySendToMobile.setText( + _translate( + "settingsDialog", + "Willingly include unencrypted destination address when sending to a mobile device", + None)) self.checkBoxUseIdenticons.setText(_translate("settingsDialog", "Use Identicons", None)) self.checkBoxReplyBelow.setText(_translate("settingsDialog", "Reply below Quote", None)) self.groupBox.setTitle(_translate("settingsDialog", "Interface Language", None)) self.languageComboBox.setItemText(0, _translate("settingsDialog", "System Settings", "system")) - self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabUserInterface), _translate("settingsDialog", "User Interface", None)) + self.tabWidgetSettings.setTabText( + self.tabWidgetSettings.indexOf( + self.tabUserInterface), + _translate( + "settingsDialog", "User Interface", None)) self.groupBox1.setTitle(_translate("settingsDialog", "Listening port", None)) self.label.setText(_translate("settingsDialog", "Listen for connections on port:", None)) self.labelUPnP.setText(_translate("settingsDialog", "UPnP:", None)) @@ -480,23 +533,70 @@ class Ui_settingsDialog(object): self.checkBoxAuthentication.setText(_translate("settingsDialog", "Authentication", None)) self.label_5.setText(_translate("settingsDialog", "Username:", None)) self.label_6.setText(_translate("settingsDialog", "Pass:", None)) - self.checkBoxSocksListen.setText(_translate("settingsDialog", "Listen for incoming connections when using proxy", None)) + self.checkBoxSocksListen.setText( + _translate( + "settingsDialog", + "Listen for incoming connections when using proxy", + None)) self.comboBoxProxyType.setItemText(0, _translate("settingsDialog", "none", None)) self.comboBoxProxyType.setItemText(1, _translate("settingsDialog", "SOCKS4a", None)) self.comboBoxProxyType.setItemText(2, _translate("settingsDialog", "SOCKS5", None)) - self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabNetworkSettings), _translate("settingsDialog", "Network Settings", None)) + self.tabWidgetSettings.setTabText( + self.tabWidgetSettings.indexOf( + self.tabNetworkSettings), + _translate( + "settingsDialog", "Network Settings", None)) self.label_9.setText(_translate("settingsDialog", "Total difficulty:", None)) - self.label_10.setText(_translate("settingsDialog", "The \'Total difficulty\' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.", None)) + self.label_10.setText( + _translate( + "settingsDialog", + "The \'Total difficulty\' affects the absolute amount of work the sender must complete." + " Doubling this value doubles the amount of work.", + None)) self.label_11.setText(_translate("settingsDialog", "Small message difficulty:", None)) - self.label_8.setText(_translate("settingsDialog", "When someone sends you a message, their computer must first complete some work. The difficulty of this work, by default, is 1. You may raise this default for new addresses you create by changing the values here. Any new addresses you create will require senders to meet the higher difficulty. There is one exception: if you add a friend or acquaintance to your address book, Bitmessage will automatically notify them when you next send a message that they need only complete the minimum amount of work: difficulty 1. ", None)) - self.label_12.setText(_translate("settingsDialog", "The \'Small message difficulty\' mostly only affects the difficulty of sending small messages. Doubling this value makes it almost twice as difficult to send a small message but doesn\'t really affect large messages.", None)) - self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabDemandedDifficulty), _translate("settingsDialog", "Demanded difficulty", None)) - self.label_15.setText(_translate("settingsDialog", "Here you may set the maximum amount of work you are willing to do to send a message to another person. Setting these values to 0 means that any value is acceptable.", None)) + self.label_8.setText(_translate( + "settingsDialog", + "When someone sends you a message, their computer must first complete some work. The difficulty of this" + " work, by default, is 1. You may raise this default for new addresses you create by changing the values" + " here. Any new addresses you create will require senders to meet the higher difficulty. There is one" + " exception: if you add a friend or acquaintance to your address book, Bitmessage will automatically" + " notify them when you next send a message that they need only complete the minimum amount of" + " work: difficulty 1. ", + None)) + self.label_12.setText( + _translate( + "settingsDialog", + "The \'Small message difficulty\' mostly only affects the difficulty of sending small messages." + " Doubling this value makes it almost twice as difficult to send a small message but doesn\'t really" + " affect large messages.", + None)) + self.tabWidgetSettings.setTabText( + self.tabWidgetSettings.indexOf( + self.tabDemandedDifficulty), + _translate( + "settingsDialog", "Demanded difficulty", None)) + self.label_15.setText( + _translate( + "settingsDialog", + "Here you may set the maximum amount of work you are willing to do to send a message to another" + " person. Setting these values to 0 means that any value is acceptable.", + None)) self.label_13.setText(_translate("settingsDialog", "Maximum acceptable total difficulty:", None)) self.label_14.setText(_translate("settingsDialog", "Maximum acceptable small message difficulty:", None)) - self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabMaxAcceptableDifficulty), _translate("settingsDialog", "Max acceptable difficulty", None)) + self.tabWidgetSettings.setTabText( + self.tabWidgetSettings.indexOf( + self.tabMaxAcceptableDifficulty), + _translate( + "settingsDialog", "Max acceptable difficulty", None)) self.labelOpenCL.setText(_translate("settingsDialog", "Hardware GPU acceleration (OpenCL):", None)) - self.label_16.setText(_translate("settingsDialog", "

Bitmessage can utilize a different Bitcoin-based program called Namecoin to make addresses human-friendly. For example, instead of having to tell your friend your long Bitmessage address, you can simply tell him to send a message to test.

(Getting your own Bitmessage address into Namecoin is still rather difficult).

Bitmessage can use either namecoind directly or a running nmcontrol instance.

", None)) + self.label_16.setText(_translate( + "settingsDialog", + "

Bitmessage can utilize a different Bitcoin-based program called Namecoin to make" + " addresses human-friendly. For example, instead of having to tell your friend your long Bitmessage" + " address, you can simply tell him to send a message to test." + "

(Getting your own Bitmessage address into Namecoin is still rather difficult).

" + "

Bitmessage can use either namecoind directly or a running nmcontrol instance.

", + None)) self.label_17.setText(_translate("settingsDialog", "Host:", None)) self.label_18.setText(_translate("settingsDialog", "Port:", None)) self.labelNamecoinUser.setText(_translate("settingsDialog", "Username:", None)) @@ -505,12 +605,26 @@ class Ui_settingsDialog(object): self.label_21.setText(_translate("settingsDialog", "Connect to:", None)) self.radioButtonNamecoinNamecoind.setText(_translate("settingsDialog", "Namecoind", None)) self.radioButtonNamecoinNmcontrol.setText(_translate("settingsDialog", "NMControl", None)) - self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabNamecoin), _translate("settingsDialog", "Namecoin integration", None)) - self.label_7.setText(_translate("settingsDialog", "

By default, if you send a message to someone and he is offline for more than two days, Bitmessage will send the message again after an additional two days. This will be continued with exponential backoff forever; messages will be resent after 5, 10, 20 days ect. until the receiver acknowledges them. Here you may change that behavior by having Bitmessage give up after a certain number of days or months.

Leave these input fields blank for the default behavior.

", None)) + self.tabWidgetSettings.setTabText( + self.tabWidgetSettings.indexOf( + self.tabNamecoin), + _translate( + "settingsDialog", "Namecoin integration", None)) + self.label_7.setText(_translate( + "settingsDialog", + "

By default, if you send a message to someone and he is offline for more than two" + " days, Bitmessage will send the message again after an additional two days. This will be continued with" + " exponential backoff forever; messages will be resent after 5, 10, 20 days ect. until the receiver" + " acknowledges them. Here you may change that behavior by having Bitmessage give up after a certain" + " number of days or months.

Leave these input fields blank for the default behavior." + "

", + None)) self.label_19.setText(_translate("settingsDialog", "Give up after", None)) self.label_20.setText(_translate("settingsDialog", "and", None)) self.label_22.setText(_translate("settingsDialog", "days", None)) self.label_23.setText(_translate("settingsDialog", "months.", None)) - self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabResendsExpire), _translate("settingsDialog", "Resends Expire", None)) - -import bitmessage_icons_rc + self.tabWidgetSettings.setTabText( + self.tabWidgetSettings.indexOf( + self.tabResendsExpire), + _translate( + "settingsDialog", "Resends Expire", None)) diff --git a/src/namecoin.py b/src/namecoin.py index 9b3c3c3e..7f081bc6 100644 --- a/src/namecoin.py +++ b/src/namecoin.py @@ -1,54 +1,64 @@ -# Copyright (C) 2013 by Daniel Kraft -# This file is part of the Bitmessage project. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. +# pylint: disable=too-many-branches,protected-access +""" +Copyright (C) 2013 by Daniel Kraft +This file is part of the Bitmessage project. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +.. todo:: from debug import logger crashes PyBitmessage due to a circular dependency. The debug module will also +override/disable logging.getLogger() # loggers so module level logging functions are used instead +""" + +from __future__ import absolute_import import base64 import httplib import json +import os import socket import sys -import os -from bmconfigparser import BMConfigParser -import defaults -import tr # translate - -# FIXME: from debug import logger crashes PyBitmessage due to a circular -# dependency. The debug module will also override/disable logging.getLogger() -# loggers so module level logging functions are used instead import logging as logger +import defaults +import tr # translate +from bmconfigparser import BMConfigParser + configSection = "bitmessagesettings" -# Error thrown when the RPC call returns an error. -class RPCError (Exception): + +class RPCError(Exception): + """Error thrown when the RPC call returns an error.""" + error = None - def __init__ (self, data): + def __init__(self, data): + super(RPCError, self).__init__() self.error = data - + def __str__(self): return '{0}: {1}'.format(type(self).__name__, self.error) -# This class handles the Namecoin identity integration. -class namecoinConnection (object): + +class namecoinConnection(object): + """This class handles the Namecoin identity integration.""" + user = None password = None host = None @@ -58,47 +68,51 @@ class namecoinConnection (object): queryid = 1 con = None - # Initialise. If options are given, take the connection settings from - # them instead of loading from the configs. This can be used to test - # currently entered connection settings in the config dialog without - # actually changing the values (yet). - def __init__ (self, options = None): + def __init__(self, options=None): + """ + Initialise. If options are given, take the connection settings from + them instead of loading from the configs. This can be used to test + currently entered connection settings in the config dialog without + actually changing the values (yet). + """ if options is None: - self.nmctype = BMConfigParser().get (configSection, "namecoinrpctype") - self.host = BMConfigParser().get (configSection, "namecoinrpchost") - self.port = int(BMConfigParser().get (configSection, "namecoinrpcport")) - self.user = BMConfigParser().get (configSection, "namecoinrpcuser") - self.password = BMConfigParser().get (configSection, - "namecoinrpcpassword") + self.nmctype = BMConfigParser().get(configSection, "namecoinrpctype") + self.host = BMConfigParser().get(configSection, "namecoinrpchost") + self.port = int(BMConfigParser().get(configSection, "namecoinrpcport")) + self.user = BMConfigParser().get(configSection, "namecoinrpcuser") + self.password = BMConfigParser().get(configSection, + "namecoinrpcpassword") else: - self.nmctype = options["type"] - self.host = options["host"] - self.port = int(options["port"]) - self.user = options["user"] - self.password = options["password"] + self.nmctype = options["type"] + self.host = options["host"] + self.port = int(options["port"]) + self.user = options["user"] + self.password = options["password"] assert self.nmctype == "namecoind" or self.nmctype == "nmcontrol" if self.nmctype == "namecoind": - self.con = httplib.HTTPConnection(self.host, self.port, timeout = 3) + self.con = httplib.HTTPConnection(self.host, self.port, timeout=3) - # Query for the bitmessage address corresponding to the given identity - # string. If it doesn't contain a slash, id/ is prepended. We return - # the result as (Error, Address) pair, where the Error is an error - # message to display or None in case of success. - def query (self, string): - slashPos = string.find ("/") + def query(self, string): + """ + Query for the bitmessage address corresponding to the given identity + string. If it doesn't contain a slash, id/ is prepended. We return + the result as (Error, Address) pair, where the Error is an error + message to display or None in case of success. + """ + slashPos = string.find("/") if slashPos < 0: string = "id/" + string try: if self.nmctype == "namecoind": - res = self.callRPC ("name_show", [string]) + res = self.callRPC("name_show", [string]) res = res["value"] elif self.nmctype == "nmcontrol": - res = self.callRPC ("data", ["getValue", string]) + res = self.callRPC("data", ["getValue", string]) res = res["reply"] - if res == False: - return (tr._translate("MainWindow",'The name %1 was not found.').arg(unicode(string)), None) + if not res: + return (tr._translate("MainWindow", 'The name %1 was not found.').arg(unicode(string)), None) else: assert False except RPCError as exc: @@ -107,16 +121,16 @@ class namecoinConnection (object): errmsg = exc.error["message"] else: errmsg = exc.error - return (tr._translate("MainWindow",'The namecoin query failed (%1)').arg(unicode(errmsg)), None) - except Exception as exc: + return (tr._translate("MainWindow", 'The namecoin query failed (%1)').arg(unicode(errmsg)), None) + except Exception: logger.exception("Namecoin query exception") - return (tr._translate("MainWindow",'The namecoin query failed.'), None) + return (tr._translate("MainWindow", 'The namecoin query failed.'), None) try: - val = json.loads (res) + val = json.loads(res) except: logger.exception("Namecoin query json exception") - return (tr._translate("MainWindow",'The name %1 has no valid JSON data.').arg(unicode(string)), None) + return (tr._translate("MainWindow", 'The name %1 has no valid JSON data.').arg(unicode(string)), None) if "bitmessage" in val: if "name" in val: @@ -124,12 +138,19 @@ class namecoinConnection (object): else: ret = val["bitmessage"] return (None, ret) - return (tr._translate("MainWindow",'The name %1 has no associated Bitmessage address.').arg(unicode(string)), None) + return ( + tr._translate( + "MainWindow", + 'The name %1 has no associated Bitmessage address.').arg( + unicode(string)), + None) - # Test the connection settings. This routine tries to query a "getinfo" - # command, and builds either an error message or a success message with - # some info from it. def test(self): + """ + Test the connection settings. This routine tries to query a "getinfo" + command, and builds either an error message or a success message with + some info from it. + """ try: if self.nmctype == "namecoind": try: @@ -143,22 +164,30 @@ class namecoinConnection (object): vers = vers / 100 v1 = vers if v3 == 0: - versStr = "0.%d.%d" % (v1, v2) + versStr = "0.%d.%d" % (v1, v2) else: - versStr = "0.%d.%d.%d" % (v1, v2, v3) - return ('success', tr._translate("MainWindow",'Success! Namecoind version %1 running.').arg(unicode(versStr)) ) + versStr = "0.%d.%d.%d" % (v1, v2, v3) + message = ( + 'success', + tr._translate( + "MainWindow", + 'Success! Namecoind version %1 running.').arg( + unicode(versStr))) elif self.nmctype == "nmcontrol": - res = self.callRPC ("data", ["status"]) + res = self.callRPC("data", ["status"]) prefix = "Plugin data running" if ("reply" in res) and res["reply"][:len(prefix)] == prefix: - return ('success', tr._translate("MainWindow",'Success! NMControll is up and running.')) + return ('success', tr._translate("MainWindow", 'Success! NMControll is up and running.')) logger.error("Unexpected nmcontrol reply: %s", res) - return ('failed', tr._translate("MainWindow",'Couldn\'t understand NMControl.')) + message = ('failed', tr._translate("MainWindow", 'Couldn\'t understand NMControl.')) else: - assert False + print "Unsupported Namecoin type" + sys.exit(1) + + return message except Exception: logger.info("Namecoin connection test failure") @@ -168,20 +197,21 @@ class namecoinConnection (object): "MainWindow", "The connection to namecoin failed.") ) - # Helper routine that actually performs an JSON RPC call. - def callRPC (self, method, params): + def callRPC(self, method, params): + """Helper routine that actually performs an JSON RPC call.""" + data = {"method": method, "params": params, "id": self.queryid} if self.nmctype == "namecoind": - resp = self.queryHTTP (json.dumps (data)) + resp = self.queryHTTP(json.dumps(data)) elif self.nmctype == "nmcontrol": - resp = self.queryServer (json.dumps (data)) + resp = self.queryServer(json.dumps(data)) else: - assert False - val = json.loads (resp) + assert False + val = json.loads(resp) if val["id"] != self.queryid: - raise Exception ("ID mismatch in JSON RPC answer.") - + raise Exception("ID mismatch in JSON RPC answer.") + if self.nmctype == "namecoind": self.queryid = self.queryid + 1 @@ -190,11 +220,12 @@ class namecoinConnection (object): return val["result"] if isinstance(error, bool): - raise RPCError (val["result"]) - raise RPCError (error) + raise RPCError(val["result"]) + raise RPCError(error) + + def queryHTTP(self, data): + """Query the server via HTTP.""" - # Query the server via HTTP. - def queryHTTP (self, data): result = None try: @@ -206,14 +237,14 @@ class namecoinConnection (object): self.con.putheader("Content-Length", str(len(data))) self.con.putheader("Accept", "application/json") authstr = "%s:%s" % (self.user, self.password) - self.con.putheader("Authorization", "Basic %s" % base64.b64encode (authstr)) + self.con.putheader("Authorization", "Basic %s" % base64.b64encode(authstr)) self.con.endheaders() self.con.send(data) try: resp = self.con.getresponse() result = resp.read() if resp.status != 200: - raise Exception ("Namecoin returned status %i: %s", resp.status, resp.reason) + raise Exception("Namecoin returned status %i: %s" % resp.status, resp.reason) except: logger.info("HTTP receive error") except: @@ -221,41 +252,49 @@ class namecoinConnection (object): return result - # Helper routine sending data to the RPC server and returning the result. - def queryServer (self, data): + def queryServer(self, data): + """Helper routine sending data to the RPC server and returning the result.""" + try: - s = socket.socket (socket.AF_INET, socket.SOCK_STREAM) - s.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.settimeout(3) - s.connect ((self.host, self.port)) - s.sendall (data) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.settimeout(3) + s.connect((self.host, self.port)) + s.sendall(data) result = "" while True: - tmp = s.recv (self.bufsize) + tmp = s.recv(self.bufsize) if not tmp: - break + break result += tmp - s.close () + s.close() return result except socket.error as exc: - raise Exception ("Socket error in RPC connection: %s" % str (exc)) + raise Exception("Socket error in RPC connection: %s" % str(exc)) + + +def lookupNamecoinFolder(): + """ + Look up the namecoin data folder. + + .. todo:: Check whether this works on other platforms as well! + """ -# Look up the namecoin data folder. -# FIXME: Check whether this works on other platforms as well! -def lookupNamecoinFolder (): app = "namecoin" from os import path, environ if sys.platform == "darwin": if "HOME" in environ: - dataFolder = path.join (os.environ["HOME"], - "Library/Application Support/", app) + '/' + dataFolder = path.join(os.environ["HOME"], + "Library/Application Support/", app) + '/' else: - print ("Could not find home folder, please report this message" - + " and your OS X version to the BitMessage Github.") + print( + "Could not find home folder, please report this message" + " and your OS X version to the BitMessage Github." + ) sys.exit() elif "win32" in sys.platform or "win64" in sys.platform: @@ -265,34 +304,38 @@ def lookupNamecoinFolder (): return dataFolder -# Ensure all namecoin options are set, by setting those to default values -# that aren't there. -def ensureNamecoinOptions (): - if not BMConfigParser().has_option (configSection, "namecoinrpctype"): - BMConfigParser().set (configSection, "namecoinrpctype", "namecoind") - if not BMConfigParser().has_option (configSection, "namecoinrpchost"): - BMConfigParser().set (configSection, "namecoinrpchost", "localhost") - hasUser = BMConfigParser().has_option (configSection, "namecoinrpcuser") - hasPass = BMConfigParser().has_option (configSection, "namecoinrpcpassword") - hasPort = BMConfigParser().has_option (configSection, "namecoinrpcport") +def ensureNamecoinOptions(): + """ + Ensure all namecoin options are set, by setting those to default values + that aren't there. + """ + + if not BMConfigParser().has_option(configSection, "namecoinrpctype"): + BMConfigParser().set(configSection, "namecoinrpctype", "namecoind") + if not BMConfigParser().has_option(configSection, "namecoinrpchost"): + BMConfigParser().set(configSection, "namecoinrpchost", "localhost") + + hasUser = BMConfigParser().has_option(configSection, "namecoinrpcuser") + hasPass = BMConfigParser().has_option(configSection, "namecoinrpcpassword") + hasPort = BMConfigParser().has_option(configSection, "namecoinrpcport") # Try to read user/password from .namecoin configuration file. defaultUser = "" defaultPass = "" - nmcFolder = lookupNamecoinFolder () + nmcFolder = lookupNamecoinFolder() nmcConfig = nmcFolder + "namecoin.conf" try: - nmc = open (nmcConfig, "r") + nmc = open(nmcConfig, "r") while True: - line = nmc.readline () + line = nmc.readline() if line == "": break - parts = line.split ("=") - if len (parts) == 2: + parts = line.split("=") + if len(parts) == 2: key = parts[0] - val = parts[1].rstrip () + val = parts[1].rstrip() if key == "rpcuser" and not hasUser: defaultUser = val @@ -300,20 +343,20 @@ def ensureNamecoinOptions (): defaultPass = val if key == "rpcport": defaults.namecoinDefaultRpcPort = val - - nmc.close () + + nmc.close() except IOError: logger.error("%s unreadable or missing, Namecoin support deactivated", nmcConfig) - except Exception as exc: + except Exception: logger.warning("Error processing namecoin.conf", exc_info=True) # If still nothing found, set empty at least. - if (not hasUser): - BMConfigParser().set (configSection, "namecoinrpcuser", defaultUser) - if (not hasPass): - BMConfigParser().set (configSection, "namecoinrpcpassword", defaultPass) + if not hasUser: + BMConfigParser().set(configSection, "namecoinrpcuser", defaultUser) + if not hasPass: + BMConfigParser().set(configSection, "namecoinrpcpassword", defaultPass) # Set default port now, possibly to found value. - if (not hasPort): - BMConfigParser().set (configSection, "namecoinrpcport", - defaults.namecoinDefaultRpcPort) + if not hasPort: + BMConfigParser().set(configSection, "namecoinrpcport", + defaults.namecoinDefaultRpcPort)