Respond to PR comments

* Address issues raised in PR comments
 * Add isort tool to code_quality fab task
 * Applied isort tool to changed files
 * Refactored devops dependencies install method
 * Refactored application path munging
 * Made bitmessagecli executable
 * Minor bug fixes to toolchain
 * Removed stale donation address
 * Added absolute_imports to give hints to pylint
This commit is contained in:
coffeedogs 2018-06-28 11:32:32 +01:00
parent ae5415a26b
commit 9821cc4510
No known key found for this signature in database
GPG Key ID: 9D818C503D0B7E70
24 changed files with 393 additions and 325 deletions

2
.gitignore vendored
View File

@ -17,3 +17,5 @@ dist
docs/_*/*
docs/autodoc/
pyan/
build/scripts-2.7/
desktop/icons/

View File

@ -105,4 +105,14 @@ forums for instructions on how to create a package on OS X.
Please note that some versions of OS X don't work.
#### Windows
## TODO: Create Windows package creation instructions
Run `python setup.py bdist_wininst` and this will create an appropriate installer executable in `dist/`.
# Troubleshooting
## Working in a virtualenv
If you get the error about importing PyQt4 when using a virtualenv, run these commands (adjusted to suit your venv name and site-wide PyQt4 installation)
`ln -s /usr/lib/python2.7/dist-packages/PyQt4 ~/.virtualenvs/pybitmessage-devops/lib/python2.7/site-packages/`
`ln -s /usr/lib/python2.7/dist-packages/sip.x86_64-linux-gnu.so ~/.virtualenvs/pybitmessage-devops/lib/python2.7/site-packages/`

View File

@ -15,7 +15,28 @@
### Tests
- If there has been a change to the code, there's a good possibility there should be a corresponding change to the tests
- If you can't run `fab tests` successfully, ask for someone to run it against your branch
- If you can't run `fab tests` successfully, ask for someone to run it against your branch. If you can't (and know that this fab task is not working yet), at least make sure the following commands work:
- Make sure the installer still works (this may be insufficient if files are deleted) and that the installed version
works.
- `python setup.py install --record files.txt; tr '\n' '\0' < files.txt | xargs -0 rm -f --; python setup.py install`
- `pybitmessage`
- And as root:
- `sudo python setup.py install --record files.txt; tr '\n' '\0' < files.txt | xargs -0 sudo rm -f --; sudo python setup.py install`
- `pybitmessage`
- Make sure the apps still work portably:
- `./src/bitmessagemain.py`
- `./src/bitmessagecli.py`
- Make sure the travis test still works (currently just `pybitmessage -t` but check travis.yml for changes
- Ideally, try this in a virtualenv, as a user with no venv, system-wide as root and on windows with `python setup.py bdist_wininst
; dist/Bitmessage_x64_0.6.3.2.exe` followed by uninstalling through add/remove progragrams and re-installing (actual filename may vary).
## Translations

View File

@ -1,15 +0,0 @@
#!/home/coffeedogs/.virtualenvs/pybitmessage-devops/bin/python
import os
import sys
import pkg_resources
import pybitmessage.pathmagic
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)

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python2
# pylint: disable=no-name-in-module,import-error; PyCQA/pylint/issues/73
"""
Check dependendies and give recommendations about how to satisfy them
@ -10,8 +11,14 @@ Limitations:
EXTRAS_REQUIRE. This is fine because most developers do, too.
"""
from __future__ import print_function
import os
from distutils.errors import CompileError
from importlib import import_module
from src.depends import PACKAGE_MANAGER, PACKAGES, detectOS
try:
from setuptools.dist import Distribution
from setuptools.extension import Extension
@ -23,10 +30,6 @@ except ImportError:
HAVE_SETUPTOOLS = False
EXTRAS_REQUIRE = []
from importlib import import_module
from src.depends import detectOS, PACKAGES, PACKAGE_MANAGER
COMPILING = {
"Debian": "build-essential libssl-dev",
@ -51,10 +54,23 @@ EXTRAS_REQUIRE_DEPS = {
"Guix": [""],
"Gentoo": ["dev-python/python-prctl"],
},
'devops': {
"OpenBSD": [""],
"FreeBSD": [""],
"Debian": ["libncurses5-dev"],
"Ubuntu": [""],
"Ubuntu 12": [""],
"openSUSE": [""],
"Fedora": [""],
"Guix": [""],
"Gentoo": [""],
},
}
def detectPrereqs(missing=True):
"""Detect pre-requesits of PACKAGES from src.depends"""
available = []
for module in PACKAGES:
try:
@ -68,6 +84,7 @@ def detectPrereqs(missing=True):
def prereqToPackages():
"""Detect OS-specific package depenedncies"""
if not detectPrereqs():
return
print("%s %s" % (
@ -76,6 +93,7 @@ def prereqToPackages():
def compilerToPackages():
"""Detect OS-specific compiler packages"""
if not detectOS() in COMPILING:
return
print("%s %s" % (
@ -83,6 +101,7 @@ def compilerToPackages():
def testCompiler():
"""Test the compiler and dependencies"""
if not HAVE_SETUPTOOLS:
# silent, we can't test without setuptools
return True
@ -137,9 +156,9 @@ OPSYS = detectOS()
CMD = PACKAGE_MANAGER[OPSYS] if OPSYS in PACKAGE_MANAGER else 'UNKNOWN_INSTALLER'
for lhs, rhs in EXTRAS_REQUIRE.items():
if rhs and any([
EXTRAS_REQUIRE_DEPS[x][OPSYS]
for x in rhs
if x in EXTRAS_REQUIRE_DEPS
EXTRAS_REQUIRE_DEPS[x][OPSYS]
for x in rhs
if x in EXTRAS_REQUIRE_DEPS
]):
rhs_cmd = ''.join([
CMD,

14
fabfile/app_path.py Normal file
View File

@ -0,0 +1,14 @@
"""
app_path.py
===========
Since fabfile directories are not part of the project they can't see modules such as `version` to update the
documentation versioning for example.
"""
import os
import sys
app_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'src')
sys.path.insert(0, app_dir)

View File

@ -5,15 +5,14 @@ A library of functions and constants for tasks to make use of.
"""
import os
import sys
import re
import sys
from functools import wraps
from fabric.api import run, hide, cd, env
from fabric.api import cd, env, hide, run
from fabric.context_managers import settings, shell_env
from fabvenv import virtualenv
FABRIC_ROOT = os.path.dirname(__file__)
PROJECT_ROOT = os.path.dirname(FABRIC_ROOT)
VENV_ROOT = os.path.expanduser(os.path.join('~', '.virtualenvs', 'pybitmessage-devops'))
@ -80,7 +79,12 @@ def filelist_from_git(rev=None):
clean = re.sub('\n', '', clean)
for line in clean.split('\r'):
if line.endswith(".py"):
results.append(os.path.abspath(line))
with settings(warn_only=True):
with hide('warnings'):
if run('stat {}'.format(os.path.abspath(line))).succeeded:
results.append(os.path.abspath(line))
else:
print 'Deleted file {} skipped.'.format(line)
return results
@ -133,6 +137,22 @@ def pylint(path_to_file):
)
def isort(path_to_file):
"""Run isort on a file"""
with virtualenv(VENV_ROOT):
with hide('warnings', 'running', 'stdout', 'stderr'):
with settings(warn_only=True):
with shell_env(PYTHONPATH=PYTHONPATH):
returnable = run(
'isort {0}'.format(
path_to_file,
),
)
# isort takes the view that a sorted file in is an error
returnable.return_code = not returnable.return_code
return returnable
def autopep8(path_to_file):
"""Run autopep8 on a file"""
with virtualenv(VENV_ROOT):

View File

@ -1,9 +0,0 @@
# These requirements are for the Fabric commands that support devops tasks for PyBitmessage, not for running
# PyBitmessage itself.
# TODO: Consider moving to an extra_requires group in setup.py
pycodestyle==2.3.1 # https://github.com/PyCQA/pycodestyle/issues/741
flake8
pylint
-e git://github.com/hhatto/autopep8.git@ver1.2.2#egg=autopep8 # Needed for fixing E712
pep8 # autopep8 doesn't seem to like pycodestyle

View File

@ -4,23 +4,23 @@ Fabric tasks for PyBitmessage devops operations.
Note that where tasks declare params to be bools, they use coerce_bool() and so will accept any commandline (string)
representation of true or false that coerce_bool() understands.
"""
import os
import sys
from fabric.api import run, task, hide, cd, settings, sudo
from fabric.api import cd, hide, run, settings, sudo, task
from fabric.contrib.project import rsync_project
from fabvenv import virtualenv
from fabfile.lib import (
autopep8, PROJECT_ROOT, VENV_ROOT, coerce_bool, flatten, filelist_from_git, default_hosts,
get_filtered_pycodestyle_output, get_filtered_flake8_output, get_filtered_pylint_output,
)
import fabfile.app_path # pylint: disable=unused-import
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src'))) # noqa:E402
from version import softwareVersion # pylint: disable=wrong-import-position
from version import softwareVersion
from fabfile.lib import (
PROJECT_ROOT, VENV_ROOT, autopep8, coerce_bool, default_hosts, filelist_from_git, flatten,
get_filtered_flake8_output, get_filtered_pycodestyle_output, get_filtered_pylint_output, isort
)
def get_tool_results(file_list):
@ -69,6 +69,7 @@ def print_results(results, top, verbose, details):
print line
if details:
print
print "pycodestyle:"
for detail in flatten(item['pycodestyle_violations']):
print detail
@ -107,7 +108,7 @@ def generate_file_list(filename):
if filename:
filename = os.path.abspath(filename)
if not os.path.exists(filename):
print "Bad filename, specify a Python file"
print "Bad filename {}, specify a Python file".format(filename)
sys.exit(1)
else:
file_list = [filename]
@ -201,8 +202,16 @@ def code_quality(verbose=True, details=False, fix=False, filename=None, top=10,
results = get_tool_results(file_list)
if fix:
for item in sort_and_slice(results, top):
autopep8(item['path_to_file'])
if filename:
sorted_and_sliced = [{'path_to_file': os.path.abspath(filename)}]
else:
sorted_and_sliced = sort_and_slice(results, top)
for item in sorted_and_sliced:
path_to_file = item['path_to_file']
print 'Applying automatic fixes to {}'.format(path_to_file)
isort(path_to_file)
autopep8(path_to_file)
# Recalculate results after autopep8 to surprise the user the least
results = get_tool_results(file_list)

View File

@ -7,13 +7,27 @@ ignore = E722,E402
[flake8]
max-line-length = 119
ignore = E402,E722,F841
ignore = E402,E722,F401,F841
# E402: pylint is preferred for wrong-import-position
# E722: pylint is preferred for bare-except
# F401: pylint is preferred for unused-import
# F841: pylint is preferred for unused-variable
# pylint honours the [MESSAGES CONTROL] section
[MESSAGES CONTROL]
disable=invalid-name,bare-except,broad-except
disable=invalid-name,bare-except,broad-except,ungrouped-imports
# invalid-name: needs fixing during a large, project-wide refactor
# bare-except,broad-except: Need fixing once thorough testing is easier
# ungrouped-imports: Incompatible with imports-before-froms which seems to be preferred
[isort]
# https://github.com/timothycrosley/isort/wiki/isort-Settings
combine_star = true
known_app_path = fabfile.app_path
known_pathmagic = pybitmessage.pathmagic
known_pybitmessage = version,src
known_standard_library = distutils.errors
line_length = 119
multi_line_output = 5
sections = FUTURE,STDLIB,THIRDPARTY,PATHMAGIC,APP_PATH,PYBITMESSAGE,FIRSTPARTY,LOCALFOLDER
wrap_length = 119

View File

@ -1,14 +1,21 @@
#!/usr/bin/env python2.7
"""
setup.py
========
Install the pybitmessage package and dependencies.
"""
from __future__ import print_function
import os
import shutil
from setuptools import setup, Extension
from setuptools import Extension, setup
from setuptools.command.install import install
from src.version import softwareVersion
EXTRAS_REQUIRE = {
'gir': ['pygobject'],
'notify2': ['notify2'],
@ -16,17 +23,25 @@ EXTRAS_REQUIRE = {
'prctl': ['python_prctl'], # Named threads
'qrcode': ['qrcode'],
'sound;platform_system=="Windows"': ['winsound'],
'docs': [
'sphinx', # fab build_docs
'devops': [
'autopep8', # fab code_quality
'fabric==1.14.0',
'fabric-virtualenv',
'flake8==3.4.1', # https://github.com/PyCQA/pycodestyle/issues/741
'graphviz', # fab build_docs
'curses', # src/depends.py
'python2-pythondialog', # src/depends.py
'isort', # fab code_quality
'm2r', # fab build_docs
'pycodestyle==2.3.1', # https://github.com/PyCQA/pycodestyle/issues/741
'pylint', # fab code_quality
'python2-pythondialog', # src/depends.py
'sphinx', # fab build_docs
],
}
class InstallCmd(install):
"""Install PyBitmessage"""
def run(self):
# prepare icons directories
try:
@ -46,6 +61,7 @@ class InstallCmd(install):
if __name__ == "__main__":
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'README.md')) as f:
README = f.read()
@ -63,21 +79,21 @@ if __name__ == "__main__":
'pybitmessage.bitmessagecurses',
'pybitmessage.messagetypes',
'pybitmessage.network',
'pybitmessage.plugins',
'pybitmessage.pyelliptic',
'pybitmessage.socks',
'pybitmessage.storage',
'pybitmessage.plugins'
]
# this will silently accept alternative providers of msgpack
# if they are already installed
try:
import msgpack
import msgpack # pylint: disable=unused-import
installRequires.append("msgpack-python")
except ImportError:
try:
import umsgpack
import umsgpack # pylint: disable=unused-import
installRequires.append("umsgpack")
except ImportError:
packages += ['pybitmessage.fallback', 'pybitmessage.fallback.umsgpack']
@ -89,12 +105,10 @@ if __name__ == "__main__":
"a P2P communications protocol",
long_description=README,
license='MIT',
# TODO: add author info
#author='',
#author_email='',
author='The Bitmessage Team',
author_email='surda@economicsofbitcoin.com',
url='https://bitmessage.org',
# TODO: add keywords
#keywords='',
keywords='bitmessage pybitmessage',
install_requires=installRequires,
extras_require=EXTRAS_REQUIRE,
classifiers=[
@ -114,11 +128,11 @@ if __name__ == "__main__":
]},
data_files=[
('share/applications/',
['desktop/pybitmessage.desktop']),
['desktop/pybitmessage.desktop']),
('share/icons/hicolor/scalable/apps/',
['desktop/icons/scalable/pybitmessage.svg']),
['desktop/icons/scalable/pybitmessage.svg']),
('share/icons/hicolor/24x24/apps/',
['desktop/icons/24x24/pybitmessage.png'])
['desktop/icons/24x24/pybitmessage.png'])
],
ext_modules=[bitmsghash],
zip_safe=False,
@ -141,9 +155,6 @@ if __name__ == "__main__":
'libmessaging ='
'pybitmessage.plugins.indicator_libmessaging [gir]'
],
# 'console_scripts': [
# 'pybitmessage = pybitmessage.bitmessagemain:main'
# ]
},
scripts=['src/pybitmessage'],
cmdclass={'install': InstallCmd}

View File

@ -8,41 +8,33 @@ This is not what you run to run the Bitmessage API. Instead, enable the API
( https://bitmessage.org/wiki/API ) and optionally enable daemon mode
( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py.
"""
from __future__ import absolute_import
import base64
import hashlib
import json
from struct import pack
import time
from binascii import hexlify, unhexlify
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from struct import pack
from version import softwareVersion
import shared
from addresses import (
decodeAddress, addBMIfNotPresent, decodeVarint,
calculateInventoryHash, varintDecodeError)
from bmconfigparser import BMConfigParser
import defaults
import helper_inbox
import helper_sent
import state
import queues
import shutdown
import network.stats
# Classes
from helper_sql import sqlQuery, sqlExecute, SqlBulkExecute, sqlStoredProcedure
from helper_ackPayload import genAckPayload
from debug import logger
from inventory import Inventory
from version import softwareVersion
# Helper Functions
import proofofwork
import queues
import shared
import shutdown
import state
from addresses import addBMIfNotPresent, calculateInventoryHash, decodeAddress, decodeVarint, varintDecodeError
from bmconfigparser import BMConfigParser
from debug import logger
from helper_ackPayload import genAckPayload
from helper_sql import SqlBulkExecute, sqlExecute, sqlQuery, sqlStoredProcedure
from inventory import Inventory
str_chan = '[chan]'
@ -116,7 +108,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
response = self.server._marshaled_dispatch( # pylint: disable=protected-access
data, getattr(self, '_dispatch', None)
)
except: # This should only happen if the module is buggy
except BaseException: # This should only happen if the module is buggy
# internal error, report as HTTP server error
self.send_response(500)
self.end_headers()
@ -328,7 +320,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label = self._decode(label, "base64")
try:
unicode(label, 'utf-8')
except:
except BaseException:
raise APIError(17, 'Label is not valid UTF-8 data.')
queues.apiAddressGeneratorReturnQueue.queue.clear()
streamNumberForAddress = 1
@ -505,7 +497,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
try:
unicode(passphrase, 'utf-8')
label = str_chan + ' ' + passphrase
except:
except BaseException:
label = str_chan + ' ' + repr(passphrase)
addressVersionNumber = 4
@ -538,7 +530,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
try:
unicode(passphrase, 'utf-8')
label = str_chan + ' ' + passphrase
except:
except BaseException:
label = str_chan + ' ' + repr(passphrase)
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress( # pylint: disable=unused-variable
@ -925,7 +917,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
try:
fromAddressEnabled = BMConfigParser().getboolean(
fromAddress, 'enabled')
except:
except BaseException:
raise APIError(
13, 'Could not find your fromAddress in the keys.dat file.')
if not fromAddressEnabled:
@ -997,7 +989,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
self._verifyAddress(fromAddress)
try:
BMConfigParser().getboolean(fromAddress, 'enabled')
except:
except BaseException:
raise APIError(
13, 'could not find your fromAddress in the keys.dat file.')
streamNumber = decodeAddress(fromAddress)[2]
@ -1060,7 +1052,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label = self._decode(label, "base64")
try:
unicode(label, 'utf-8')
except:
except BaseException:
raise APIError(17, 'Label is not valid UTF-8 data.')
if len(params) > 2:
raise APIError(0, 'I need either 1 or 2 parameters!')
@ -1147,7 +1139,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
'POW took', int(time.time() - powStartTime), 'seconds.',
nonce / (time.time() - powStartTime), 'nonce trials per second.',
)
except:
except BaseException:
pass
encryptedPayload = pack('>Q', nonce) + encryptedPayload
toStreamNumber = decodeVarint(encryptedPayload[16:26])[0]

13
src/bitmessagecli.py Normal file → Executable file
View File

@ -12,20 +12,21 @@ This is an example of a daemon client for PyBitmessage 0.6.2, by .dok (Version 0
TODO: fix the following (currently ignored) violations:
"""
from __future__ import absolute_import
import xmlrpclib
import datetime
import imghdr
import ntpath
import json
import socket
import time
import sys
import ntpath
import os
import socket
import sys
import time
import xmlrpclib
import pathmagic
from bmconfigparser import BMConfigParser
api = ''
keysName = 'keys.dat'
keysPath = 'keys.dat'

View File

@ -31,49 +31,32 @@ from struct import pack
from subprocess import call
from time import sleep
app_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(app_dir)
sys.path.insert(0, app_dir)
# Used to capture a Ctrl-C keypress so that Bitmessage can shutdown gracefully.
# The next 3 are used for the API
from singleinstance import singleinstance
from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer
from helper_startup import (
isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
)
import defaults
import depends
import shared
import knownnodes
import state
import shutdown
# Classes
from class_sqlThread import sqlThread
from class_singleCleaner import singleCleaner
from class_objectProcessor import objectProcessor
from class_singleWorker import singleWorker
from class_addressGenerator import addressGenerator
from bmconfigparser import BMConfigParser
from inventory import Inventory
from network.connectionpool import BMConnectionPool
from network.dandelion import Dandelion
from network.networkthread import BMNetworkThread
from network.receivequeuethread import ReceiveQueueThread
from network.announcethread import AnnounceThread
from network.invthread import InvThread
from network.addrthread import AddrThread
from network.downloadthread import DownloadThread
# Helper Functions
import helper_bootstrap
import helper_generic
import helper_threading
import knownnodes
import shared
import shutdown
import state
from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer
from bmconfigparser import BMConfigParser
from class_addressGenerator import addressGenerator
from class_objectProcessor import objectProcessor
from class_singleCleaner import singleCleaner
from class_singleWorker import singleWorker
from class_sqlThread import sqlThread
from helper_startup import isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
from inventory import Inventory
from network.addrthread import AddrThread
from network.announcethread import AnnounceThread
from network.connectionpool import BMConnectionPool
from network.dandelion import Dandelion
from network.downloadthread import DownloadThread
from network.invthread import InvThread
from network.networkthread import BMNetworkThread
from network.receivequeuethread import ReceiveQueueThread
from singleinstance import singleinstance
depends.check_dependencies()
@ -95,7 +78,7 @@ def connectToStream(streamNumber):
if BMConfigParser().get(
'bitmessagesettings', 'socksproxytype') != 'none':
state.maximumNumberOfHalfOpenConnections = 4
except:
except BaseException:
pass
with knownnodes.knownNodesLock:
@ -188,7 +171,7 @@ class singleAPI(threading.Thread, helper_threading.StoppableThread):
))
s.shutdown(socket.SHUT_RDWR)
s.close()
except:
except BaseException:
pass
def run(self):
@ -364,11 +347,11 @@ class Main(object):
try:
apiNotifyPath = BMConfigParser().get(
'bitmessagesettings', 'apinotifypath')
except:
except BaseException:
apiNotifyPath = ''
if apiNotifyPath != '':
with shared.printLock:
print('Trying to call', apiNotifyPath)
print 'Trying to call', apiNotifyPath
call([apiNotifyPath, "startingUp"])
singleAPIThread = singleAPI()
@ -414,7 +397,7 @@ class Main(object):
if state.curses:
if not depends.check_curses():
sys.exit()
print('Running with curses')
print 'Running with curses'
import bitmessagecurses
bitmessagecurses.runwrapper()
elif state.kivy:

View File

@ -395,13 +395,13 @@ class MyForm(settingsmixin.SMainWindow):
treeWidget.header().setSortIndicator(
0, QtCore.Qt.AscendingOrder)
# init dictionary
db = getSortedSubscriptions(True)
for address in db:
for folder in folders:
if not folder in db[address]:
db[address][folder] = {}
if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False)
@ -413,7 +413,7 @@ class MyForm(settingsmixin.SMainWindow):
toAddress = widget.address
else:
toAddress = None
if not toAddress in db:
treeWidget.takeTopLevelItem(i)
# no increment
@ -444,7 +444,7 @@ class MyForm(settingsmixin.SMainWindow):
widget.setUnreadCount(unread)
db.pop(toAddress, None)
i += 1
i = 0
for toAddress in db:
widget = Ui_SubscriptionWidget(treeWidget, i, toAddress, db[toAddress]["inbox"]['count'], db[toAddress]["inbox"]['label'], db[toAddress]["inbox"]['enabled'])
@ -459,7 +459,7 @@ class MyForm(settingsmixin.SMainWindow):
j += 1
widget.setUnreadCount(unread)
i += 1
treeWidget.setSortingEnabled(True)
@ -468,14 +468,14 @@ class MyForm(settingsmixin.SMainWindow):
def rerenderTabTreeChans(self):
self.rerenderTabTree('chan')
def rerenderTabTree(self, tab):
if tab == 'messages':
treeWidget = self.ui.treeWidgetYourIdentities
elif tab == 'chan':
treeWidget = self.ui.treeWidgetChans
folders = Ui_FolderWidget.folderWeight.keys()
# sort ascending when creating
if treeWidget.topLevelItemCount() == 0:
treeWidget.header().setSortIndicator(
@ -483,7 +483,7 @@ class MyForm(settingsmixin.SMainWindow):
# init dictionary
db = {}
enabled = {}
for toAddress in getSortedAccounts():
isEnabled = BMConfigParser().getboolean(
toAddress, 'enabled')
@ -502,7 +502,7 @@ class MyForm(settingsmixin.SMainWindow):
db[toAddress] = {}
for folder in folders:
db[toAddress][folder] = 0
enabled[toAddress] = isEnabled
# get number of (unread) messages
@ -520,10 +520,10 @@ class MyForm(settingsmixin.SMainWindow):
db[None]["sent"] = 0
db[None]["trash"] = 0
enabled[None] = True
if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False)
widgets = {}
i = 0
while i < treeWidget.topLevelItemCount():
@ -532,7 +532,7 @@ class MyForm(settingsmixin.SMainWindow):
toAddress = widget.address
else:
toAddress = None
if not toAddress in db:
treeWidget.takeTopLevelItem(i)
# no increment
@ -565,7 +565,7 @@ class MyForm(settingsmixin.SMainWindow):
widget.setUnreadCount(unread)
db.pop(toAddress, None)
i += 1
i = 0
for toAddress in db:
widget = Ui_AddressWidget(treeWidget, i, toAddress, db[toAddress]["inbox"], enabled[toAddress])
@ -580,7 +580,7 @@ class MyForm(settingsmixin.SMainWindow):
j += 1
widget.setUnreadCount(unread)
i += 1
treeWidget.setSortingEnabled(True)
def __init__(self, parent=None):
@ -622,13 +622,13 @@ class MyForm(settingsmixin.SMainWindow):
# e.g. for editing labels
self.recurDepth = 0
# switch back to this when replying
self.replyFromTab = None
# so that quit won't loop
self.quitAccepted = False
self.init_file_menu()
self.init_inbox_popup_menu()
self.init_identities_popup_menu()
@ -730,7 +730,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.treeWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.ui.treeWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.ui.tableWidgetAddressBook.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.UISignalThread = UISignaler.get()
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
@ -784,7 +784,7 @@ class MyForm(settingsmixin.SMainWindow):
self.rerenderComboBoxSendFrom()
self.rerenderComboBoxSendFromBroadcast()
# Put the TTL slider in the correct spot
TTL = BMConfigParser().getint('bitmessagesettings', 'ttl')
if TTL < 3600: # an hour
@ -793,7 +793,7 @@ class MyForm(settingsmixin.SMainWindow):
TTL = 28*24*60*60
self.ui.horizontalSliderTTL.setSliderPosition((TTL - 3600) ** (1/3.199))
self.updateHumanFriendlyTTLDescription(TTL)
QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL(
"valueChanged(int)"), self.updateTTL)
@ -817,7 +817,7 @@ class MyForm(settingsmixin.SMainWindow):
self.updateHumanFriendlyTTLDescription(TTL)
BMConfigParser().set('bitmessagesettings', 'ttl', str(TTL))
BMConfigParser().save()
def updateHumanFriendlyTTLDescription(self, TTL):
numberOfHours = int(round(TTL / (60*60)))
font = QtGui.QFont()
@ -981,7 +981,7 @@ class MyForm(settingsmixin.SMainWindow):
for row in queryReturn:
broadcastsUnread[row[0]] = {}
broadcastsUnread[row[0]][row[1]] = row[2]
for treeWidget in widgets:
root = treeWidget.invisibleRootItem()
for i in range(root.childCount()):
@ -1100,7 +1100,7 @@ class MyForm(settingsmixin.SMainWindow):
if acct is None:
acct = BMAccount(fromAddress)
acct.parseMessage(toAddress, fromAddress, subject, "")
items = []
#to
MessageList_AddressWidget(items, toAddress, unicode(acct.toLabel, 'utf-8'), not read)
@ -1176,7 +1176,7 @@ class MyForm(settingsmixin.SMainWindow):
tableWidget.setRowCount(0)
queryreturn = helper_search.search_sql(xAddress, account, folder, where, what, unreadOnly)
for row in queryreturn:
msgfolder, msgid, toAddress, fromAddress, subject, received, read = row
self.addMessageListItemInbox(tableWidget, msgfolder, msgid, toAddress, fromAddress, subject, received, read)
@ -1934,7 +1934,7 @@ class MyForm(settingsmixin.SMainWindow):
subject = acct.subject
toAddress = acct.toAddress
else:
if QtGui.QMessageBox.question(self, "Sending an email?", _translate("MainWindow",
if QtGui.QMessageBox.question(self, "Sending an email?", _translate("MainWindow",
"You are trying to send an email instead of a bitmessage. This requires registering with a gateway. Attempt to register?"),
QtGui.QMessageBox.Yes|QtGui.QMessageBox.No) != QtGui.QMessageBox.Yes:
continue
@ -2111,17 +2111,17 @@ class MyForm(settingsmixin.SMainWindow):
ackdata = genAckPayload(streamNumber, 0)
toAddress = str_broadcast_subscribers
ripe = ''
t = ('', # msgid. We don't know what this will be until the POW is done.
toAddress,
ripe,
fromAddress,
subject,
message,
ackdata,
t = ('', # msgid. We don't know what this will be until the POW is done.
toAddress,
ripe,
fromAddress,
subject,
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.
'broadcastqueued',
'broadcastqueued',
0, # retryNumber
'sent', # folder
encoding, # encoding type
@ -2131,7 +2131,7 @@ class MyForm(settingsmixin.SMainWindow):
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', *t)
toLabel = str_broadcast_subscribers
self.displayNewSentMessage(
toAddress, toLabel, fromAddress, subject, message, ackdata)
@ -2250,7 +2250,7 @@ class MyForm(settingsmixin.SMainWindow):
continue
elif not helper_search.check_match(toAddress, fromAddress, subject, message, self.getCurrentSearchOption(tab), self.getCurrentSearchLine(tab)):
continue
self.addMessageListItemSent(sent, toAddress, fromAddress, subject, "msgqueued", ackdata, time.time())
self.getAccountTextedit(acct).setPlainText(unicode(message, 'utf-8', 'replace'))
sent.setCurrentCell(0, 0)
@ -2412,11 +2412,11 @@ class MyForm(settingsmixin.SMainWindow):
self.settingsDialogInstance.ui.checkBoxUseIdenticons.isChecked()))
BMConfigParser().set('bitmessagesettings', 'replybelow', str(
self.settingsDialogInstance.ui.checkBoxReplyBelow.isChecked()))
lang = str(self.settingsDialogInstance.ui.languageComboBox.itemData(self.settingsDialogInstance.ui.languageComboBox.currentIndex()).toString())
BMConfigParser().set('bitmessagesettings', 'userlocale', lang)
change_translation(l10n.getTranslationLanguage())
if int(BMConfigParser().get('bitmessagesettings', 'port')) != int(self.settingsDialogInstance.ui.lineEditTCPPort.text()):
if not BMConfigParser().safeGetBoolean('bitmessagesettings', 'dontconnect'):
QtGui.QMessageBox.about(self, _translate("MainWindow", "Restart"), _translate(
@ -2481,7 +2481,7 @@ class MyForm(settingsmixin.SMainWindow):
self.settingsDialogInstance.ui.lineEditNamecoinUser.text()))
BMConfigParser().set('bitmessagesettings', 'namecoinrpcpassword', str(
self.settingsDialogInstance.ui.lineEditNamecoinPassword.text()))
# Demanded difficulty tab
if float(self.settingsDialogInstance.ui.lineEditTotalDifficulty.text()) >= 1:
BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(int(float(
@ -2495,7 +2495,7 @@ class MyForm(settingsmixin.SMainWindow):
queues.workerQueue.put(('resetPoW', ''))
acceptableDifficultyChanged = False
if float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) >= 1 or float(self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) == 0:
if BMConfigParser().get('bitmessagesettings','maxacceptablenoncetrialsperbyte') != str(int(float(
self.settingsDialogInstance.ui.lineEditMaxAcceptableTotalDifficulty.text()) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)):
@ -2511,13 +2511,13 @@ class MyForm(settingsmixin.SMainWindow):
BMConfigParser().set('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', str(int(float(
self.settingsDialogInstance.ui.lineEditMaxAcceptableSmallMessageDifficulty.text()) * defaults.networkDefaultPayloadLengthExtraBytes)))
if acceptableDifficultyChanged:
# It might now be possible to send msgs which were previously marked as toodifficult.
# It might now be possible to send msgs which were previously marked as toodifficult.
# Let us change them to 'msgqueued'. The singleWorker will try to send them and will again
# mark them as toodifficult if the receiver's required difficulty is still higher than
# we are willing to do.
sqlExecute('''UPDATE sent SET status='msgqueued' WHERE status='toodifficult' ''')
queues.workerQueue.put(('sendmessage', ''))
#start:UI setting to stop trying to send messages after X days/months
# I'm open to changing this UI to something else if someone has a better idea.
if ((self.settingsDialogInstance.ui.lineEditDays.text()=='') and (self.settingsDialogInstance.ui.lineEditMonths.text()=='')):#We need to handle this special case. Bitmessage has its default behavior. The input is blank/blank
@ -2718,7 +2718,7 @@ class MyForm(settingsmixin.SMainWindow):
if getPowType() == "python" and (powQueueSize() > 0 or pendingUpload() > 0):
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Proof of work pending"),
_translate("MainWindow", "%n object(s) pending proof of work", None, QtCore.QCoreApplication.CodecForTr, powQueueSize()) + ", " +
_translate("MainWindow", "%n object(s) waiting to be distributed", None, QtCore.QCoreApplication.CodecForTr, pendingUpload()) + "\n\n" +
_translate("MainWindow", "%n object(s) waiting to be distributed", None, QtCore.QCoreApplication.CodecForTr, pendingUpload()) + "\n\n" +
_translate("MainWindow", "Wait until these tasks finish?"),
QtGui.QMessageBox.Yes|QtGui.QMessageBox.No|QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.No:
@ -2807,7 +2807,7 @@ class MyForm(settingsmixin.SMainWindow):
self.updateStatusBar(_translate(
"MainWindow", "Waiting for objects to be sent... %1%").arg(50))
maxPendingUpload = max(1, pendingUpload())
while pendingUpload() > 1:
self.updateStatusBar(_translate(
"MainWindow",
@ -2936,7 +2936,7 @@ class MyForm(settingsmixin.SMainWindow):
# self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(QtCore.Qt.UserRole), self.getCurrentFolder())
# else:
# self.propagateUnreadCount(tableWidget.item(currentRow, 1 if tableWidget.item(currentRow, 1).type == AccountMixin.SUBSCRIPTION else 0).data(QtCore.Qt.UserRole), self.getCurrentFolder(), self.getCurrentTreeWidget(), 0)
# tableWidget.selectRow(currentRow + 1)
# tableWidget.selectRow(currentRow + 1)
# This doesn't de-select the last message if you try to mark it unread, but that doesn't interfere. Might not be necessary.
# We could also select upwards, but then our problem would be with the topmost message.
# tableWidget.clearSelection() manages to mark the message as read again.
@ -2980,18 +2980,18 @@ class MyForm(settingsmixin.SMainWindow):
def on_action_InboxReplyChan(self):
self.on_action_InboxReply(self.REPLY_TYPE_CHAN)
def on_action_InboxReply(self, replyType = None):
tableWidget = self.getCurrentMessagelist()
if not tableWidget:
return
if replyType is None:
replyType = self.REPLY_TYPE_SENDER
# save this to return back after reply is done
self.replyFromTab = self.ui.tabWidget.currentIndex()
currentInboxRow = tableWidget.currentRow()
toAddressAtCurrentInboxRow = tableWidget.item(
currentInboxRow, 0).address
@ -3040,7 +3040,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.lineEditTo.setText(str(acct.fromAddress))
else:
self.ui.lineEditTo.setText(tableWidget.item(currentInboxRow, 1).label + " <" + str(acct.fromAddress) + ">")
# If the previous message was to a chan then we should send our reply to the chan rather than to the particular person who sent the message.
if acct.type == AccountMixin.CHAN and replyType == self.REPLY_TYPE_CHAN:
logger.debug('original sent to a chan. Setting the to address in the reply to the chan address.')
@ -3048,9 +3048,9 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.lineEditTo.setText(str(toAddressAtCurrentInboxRow))
else:
self.ui.lineEditTo.setText(tableWidget.item(currentInboxRow, 0).label + " <" + str(acct.toAddress) + ">")
self.setSendFromComboBox(toAddressAtCurrentInboxRow)
quotedText = self.quoted_text(unicode(messageAtCurrentInboxRow, 'utf-8', 'replace'))
widget['message'].setPlainText(quotedText)
if acct.subject[0:3] in ['Re:', 'RE:']:
@ -3497,7 +3497,7 @@ class MyForm(settingsmixin.SMainWindow):
return messagelistList[currentIndex]
else:
return False
def getAccountMessagelist(self, account):
try:
if account.type == AccountMixin.CHAN:
@ -3584,7 +3584,7 @@ class MyForm(settingsmixin.SMainWindow):
if currentItem:
return currentItem
return False
def getCurrentAccount(self, treeWidget=None):
currentItem = self.getCurrentItem(treeWidget)
if currentItem:
@ -3711,7 +3711,7 @@ class MyForm(settingsmixin.SMainWindow):
def on_action_AddressBookSetAvatar(self):
self.on_action_SetAvatar(self.ui.tableWidgetAddressBook)
def on_action_SetAvatar(self, thisTableWidget):
currentRow = thisTableWidget.currentRow()
addressAtCurrentRow = thisTableWidget.item(
@ -3765,7 +3765,7 @@ class MyForm(settingsmixin.SMainWindow):
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
else:
overwrite = QtGui.QMessageBox.No
# copy the image file to the appdata folder
if (not exists) | (overwrite == QtGui.QMessageBox.Yes):
if overwrite == QtGui.QMessageBox.Yes:
@ -3983,11 +3983,7 @@ class MyForm(settingsmixin.SMainWindow):
if column != 0:
return
# only account names of normal addresses (no chans/mailinglists)
if (
not isinstance(item, Ui_AddressWidget) or
not self.getCurrentTreeWidget() or
self.getCurrentTreeWidget().currentItem() is None
):
if (not isinstance(item, Ui_AddressWidget)) or (not self.getCurrentTreeWidget()) or self.getCurrentTreeWidget().currentItem() is None:
return
# not visible
if (not self.getCurrentItem()) or (not isinstance (self.getCurrentItem(), Ui_AddressWidget)):
@ -3998,7 +3994,7 @@ class MyForm(settingsmixin.SMainWindow):
# "All accounts" can't be renamed
if item.type == AccountMixin.ALL:
return
newLabel = unicode(item.text(0), 'utf-8', 'ignore')
oldLabel = item.defaultLabel()
@ -4141,7 +4137,7 @@ class settingsDialog(QtGui.QDialog):
BMConfigParser().safeGetBoolean('bitmessagesettings', 'useidenticons'))
self.ui.checkBoxReplyBelow.setChecked(
BMConfigParser().safeGetBoolean('bitmessagesettings', 'replybelow'))
if state.appdata == paths.lookupExeFolder():
self.ui.checkBoxPortableMode.setChecked(True)
else:
@ -4266,8 +4262,8 @@ class settingsDialog(QtGui.QDialog):
BMConfigParser().get('bitmessagesettings', 'stopresendingafterxdays')))
self.ui.lineEditMonths.setText(str(
BMConfigParser().get('bitmessagesettings', 'stopresendingafterxmonths')))
#'System' tab removed for now.
"""try:
maxCores = BMConfigParser().getint('bitmessagesettings', 'maxcores')
@ -4318,7 +4314,7 @@ class settingsDialog(QtGui.QDialog):
def namecoinTypeChanged(self, checked):
nmctype = self.getNamecoinType()
assert nmctype == "namecoind" or nmctype == "nmcontrol"
isNamecoind = (nmctype == "namecoind")
self.ui.lineEditNamecoinUser.setEnabled(isNamecoind)
self.ui.labelNamecoinUser.setEnabled(isNamecoind)
@ -4442,7 +4438,7 @@ def run():
# myapp.showMigrationWizard(BMConfigParser().get('bitmessagesettings', 'mailchuck'))
# except:
# myapp.showMigrationWizard(0)
# only show after wizards and connect dialogs have completed
if not BMConfigParser().getboolean('bitmessagesettings', 'startintray'):
myapp.show()

View File

@ -7,8 +7,6 @@ Account related functions.
"""
from __future__ import absolute_import
import inspect
import re
import sys

View File

@ -1,29 +1,23 @@
# -*- coding: utf-8 -*-
# pylint: disable=too-many-locals
# pylint: disable=too-many-locals,c-extension-no-member
"""
Form implementation generated from reading ui file 'bitmessageui.ui'
bitmessageui.py
===============
Created: Mon Mar 23 22:18:07 2015
by: PyQt4 UI code generator 4.10.4
WARNING! All changes made in this file will be lost!
Originally generated from reading ui file 'bitmessageui.ui'. Since then maintained manually.
"""
from __future__ import absolute_import
import sys
from PyQt4 import QtCore, QtGui
from bitmessageqt import settingsmixin
from bitmessageqt.blacklist import Blacklist
from bitmessageqt.foldertree import AddressBookCompleter
from bitmessageqt.messagecompose import MessageCompose
from bitmessageqt.messageview import MessageView
from bitmessageqt.networkstatus import NetworkStatus
from bmconfigparser import BMConfigParser
from . import bitmessage_icons_rc # pylint: disable=unused-import
from . import settingsmixin
from .messageview import MessageView
from .messagecompose import MessageCompose
from .networkstatus import NetworkStatus
from .blacklist import Blacklist
from .foldertree import AddressBookCompleter
try:
_fromUtf8 = QtCore.QString.fromUtf8
@ -760,7 +754,7 @@ class Ui_MainWindow(object):
hours = 48
try:
hours = int(BMConfigParser().getint('bitmessagesettings', 'ttl') / 60 / 60)
except:
except BaseException:
pass
self.labelHumanFriendlyTTLDescription.setText(
_translate(

View File

@ -53,13 +53,15 @@ import select
import socket
import sys
import time
from threading import current_thread
import warnings
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ENOTSOCK, EINTR, ETIMEDOUT, \
EADDRINUSE, \
errorcode
from errno import (
EADDRINUSE, EAGAIN, EALREADY, EBADF, ECONNABORTED, ECONNREFUSED, ECONNRESET, EHOSTUNREACH, EINPROGRESS, EINTR,
EINVAL, EISCONN, ENETUNREACH, ENOTCONN, ENOTSOCK, EPIPE, ESHUTDOWN, ETIMEDOUT, EWOULDBLOCK, errorcode
)
from threading import current_thread
import helper_random
try:
from errno import WSAEWOULDBLOCK
except (ImportError, AttributeError):
@ -77,7 +79,6 @@ try:
from errno import WSAEADDRINUSE # pylint: disable=unused-import
except (ImportError, AttributeError):
WSAEADDRINUSE = EADDRINUSE
import helper_random
_DISCONNECTED = frozenset((
@ -128,7 +129,7 @@ def read(obj):
obj.handle_read_event()
except _reraised_exceptions:
raise
except:
except BaseException:
obj.handle_error()
@ -141,7 +142,7 @@ def write(obj):
obj.handle_write_event()
except _reraised_exceptions:
raise
except:
except BaseException:
obj.handle_error()
@ -209,7 +210,7 @@ def _exception(obj):
obj.handle_expt_event()
except _reraised_exceptions:
raise
except:
except BaseException:
obj.handle_error()
@ -232,7 +233,7 @@ def readwrite(obj, flags):
obj.handle_close()
except _reraised_exceptions:
raise
except:
except BaseException:
obj.handle_error()
@ -788,7 +789,7 @@ class dispatcher:
def log_info(self, message, log_type='info'):
"""Conditionally print a message"""
if log_type not in self.ignore_log_types:
print '%s: %s' % log_type, message
print '%s: %s' % (log_type, message)
def handle_read_event(self):
"""Handle a read event"""
@ -850,7 +851,7 @@ class dispatcher:
# sometimes a user repr method will crash.
try:
self_repr = repr(self)
except:
except BaseException:
self_repr = '<__repr__(self) failed for object at %0x>' % id(self)
self.log_info(
@ -975,7 +976,7 @@ def close_all(map=None, ignore_all=False):
raise
except _reraised_exceptions:
raise
except:
except BaseException:
if not ignore_all:
raise
map.clear()

View File

@ -11,25 +11,26 @@ import socket
import struct
import time
import addresses
import helper_random
import knownnodes
import network.connectionpool
import protocol
import shared
import state
from bmconfigparser import BMConfigParser
from debug import logger
from inventory import Inventory
import knownnodes
from network.advanceddispatcher import AdvancedDispatcher
from network.bmobject import (
BMObject, BMObjectAlreadyHaveError, BMObjectExpiredError, BMObjectInsufficientPOWError, BMObjectInvalidDataError,
BMObjectInvalidError, BMObjectUnwantedStreamError
)
from network.dandelion import Dandelion
from network.bmobject import BMObject, BMObjectInsufficientPOWError, BMObjectInvalidDataError, \
BMObjectExpiredError, BMObjectUnwantedStreamError, BMObjectInvalidError, BMObjectAlreadyHaveError
import network.connectionpool
from network.node import Node
from network.objectracker import ObjectTracker
from network.proxy import ProxyError
import addresses
from queues import objectProcessorQueue, portCheckerQueue, invQueue, addrQueue
import shared
import state
import protocol
import helper_random
from queues import addrQueue, invQueue, objectProcessorQueue, portCheckerQueue
class BMProtoError(ProxyError):
@ -74,7 +75,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
self.local = False
def bm_proto_reset(self):
"""TBC"""
"""Reset the bitmessage object parser"""
self.magic = None
self.command = None
self.payloadLength = 0
@ -86,7 +87,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
self.object = None
def state_bm_header(self):
"""Predicate to indicate the prescence of a header"""
"""Predicate (with logging) to indicate the prescence of a header"""
self.magic, self.command, self.payloadLength, self.checksum = protocol.Header.unpack(
self.read_buf[:protocol.Header.size])
@ -106,7 +107,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True
def state_bm_command(self):
"""TBC"""
"""Predicate (with logging) to indicate the presence of a command"""
self.payload = self.read_buf[:self.payloadLength]
if self.checksum != hashlib.sha512(self.payload).digest()[0:4]:
logger.debug("Bad checksum, ignoring")
@ -295,16 +296,16 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
raise BMProtoInsufficientDataError()
def bm_command_error(self):
"""TBC"""
"""Decode an error message and log it"""
# pylint: disable=unused-variable
fatalStatus, banTime, inventoryVector, errorText = self.decode_payload_content("vvlsls")
logger.error("%s:%i error: %i, %s", self.destination.host, self.destination.port, fatalStatus, errorText)
return True
def bm_command_getdata(self):
"""TBC"""
"""Decode object data, conditionally append a newly created object to the write buffer"""
items = self.decode_payload_content("l32s")
# ..todo:: skip?
# .. todo:: skip?
if time.time() < self.skipUntil:
return True
# .. todo:: make this more asynchronous
@ -349,13 +350,11 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True
def bm_command_inv(self):
"""TBC"""
"""Non-dandelion announce"""
return self._command_inv(False)
def bm_command_dinv(self):
"""
Dandelion stem announce
"""
"""Dandelion stem announce"""
return self._command_inv(True)
def bm_command_object(self):
@ -442,12 +441,12 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True
def bm_command_portcheck(self):
"""TBC"""
"""Add a job port of a peer"""
portCheckerQueue.put(state.Peer(self.destination, self.peerNode.port))
return True
def bm_command_ping(self):
"""TBC"""
"""Respond to a ping"""
self.append_write_buf(protocol.CreatePacket('pong'))
return True
@ -457,8 +456,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True
def bm_command_verack(self):
"""TBC"""
"""Return True if a verack has been sent, False otherwise"""
self.verackReceived = True
if self.verackSent:
if self.isSSL:
@ -469,7 +467,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True
def bm_command_version(self):
"""TBC"""
"""Determine and log protocol version and other details"""
self.remoteProtocolVersion, self.services, self.timestamp, self.sockNode, self.peerNode, self.nonce, \
self.userAgent, self.streams = self.decode_payload_content("IQQiiQlsLv")
@ -547,7 +545,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
logger.debug('Closed connection to %s because we are already connected to that IP.',
str(self.destination))
return False
except:
except BaseException:
pass
if not self.isOutbound:
# incoming from a peer we're connected to as outbound, or server full

View File

@ -4,34 +4,31 @@ tcp.py
======
"""
from __future__ import absolute_import
import math
import time
import socket
import random
import socket
import time
from debug import logger
from helper_random import randomBytes
import helper_random
from inventory import Inventory
import knownnodes
from network.advanceddispatcher import AdvancedDispatcher
from network.bmproto import BMProto
import network.connectionpool
from network.dandelion import Dandelion
import network.asyncore_pollchoose as asyncore
from network.objectracker import ObjectTracker
from network.socks5 import Socks5Connection
from network.socks4a import Socks4aConnection
from network.tls import TLSDispatcher
import addresses
from bmconfigparser import BMConfigParser
from queues import invQueue, UISignalQueue, receiveDataQueue
import helper_random
import knownnodes
import network.asyncore_pollchoose as asyncore
import network.connectionpool
import protocol
import shared
import state
import protocol
from bmconfigparser import BMConfigParser
from debug import logger
from helper_random import randomBytes
from inventory import Inventory
from network.advanceddispatcher import AdvancedDispatcher
from network.bmproto import BMProto
from network.dandelion import Dandelion
from network.objectracker import ObjectTracker
from network.socks4a import Socks4aConnection
from network.socks5 import Socks5Connection
from network.tls import TLSDispatcher
from queues import UISignalQueue, invQueue, receiveDataQueue
class TCPConnection(BMProto, TLSDispatcher): # pylint: disable=too-many-instance-attributes

14
src/pathmagic.py Normal file
View File

@ -0,0 +1,14 @@
"""
pathmagic.py
===========
Makes the app portable by adding the parent directory to the path and changing to that directory. Putting this in a
seperate module make it re-usable and does not confuse isort and friends due to code interspersed among the imports.
"""
import os
import sys
app_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(app_dir)
sys.path.insert(0, app_dir)

View File

@ -11,18 +11,17 @@ import hashlib
import os
import sys
import time
from struct import unpack, pack
from struct import pack, unpack
from subprocess import call
import paths
import openclpow
import paths
import queues
import tr
import state
import tr
from bmconfigparser import BMConfigParser
from debug import logger
bitmsglib = 'bitmsghash.so'
bmpow = None
@ -132,18 +131,13 @@ def _doGPUPoW(target, initialHash):
trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
if trialValue > target:
deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus)
queues.UISignalQueue.put(
(
'updateStatusBar',
(
tr._translate(
"MainWindow",
'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.'
),
1
)
)
)
queues.UISignalQueue.put((
'updateStatusBar', (
tr._translate(
"MainWindow",
'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.'
),
1)))
logger.error(
"Your GPUs (%s) did not calculate correctly, disabling OpenCL. Please report to the developers.",
deviceNames)
@ -198,7 +192,7 @@ def getPowType():
def notifyBuild(tried=False):
"""TBC"""
"""Notify the user of the success or otherwise of building the PoW C module"""
if bmpow:
queues.UISignalQueue.put(('updateStatusBar', (tr._translate(
@ -221,7 +215,7 @@ def notifyBuild(tried=False):
def buildCPoW():
"""TBC"""
"""Attempt to build the PoW C module"""
if bmpow is not None:
return
if paths.frozen is not None:
@ -250,7 +244,7 @@ def run(target, initialHash):
"""Run the proof of work thread"""
if state.shutdown != 0:
raise
raise # pylint: disable=misplaced-bare-raise
target = int(target)
if openclpow.openclEnabled():
try:
@ -287,7 +281,7 @@ def run(target, initialHash):
def resetPoW():
"""TBC"""
"""Initialise the OpenCL PoW"""
openclpow.initCL()
@ -295,7 +289,7 @@ def resetPoW():
def init():
"""TBC"""
"""Initialise PoW"""
# pylint: disable=global-statement
global bitmsglib, bmpow

View File

@ -1,8 +1,12 @@
#!/usr/bin/python2.7
#!/usr/bin/env python2.7
import os
import sys
import pkg_resources
import pybitmessage.pathmagic
dist = pkg_resources.get_distribution('pybitmessage')
script_file = os.path.join(dist.location, dist.key, 'bitmessagemain.py')
new_globals = globals()

View File

@ -7,23 +7,23 @@ Reference: http://mattscodecave.com/posts/using-python-and-upnp-to-forward-a-por
from __future__ import absolute_import
import httplib
from random import randint
import socket
from struct import unpack
import threading
import time
import urllib2
from random import randint
from struct import unpack
from urlparse import urlparse
from xml.dom.minidom import Document, parseString
from bmconfigparser import BMConfigParser
from debug import logger
from network.connectionpool import BMConnectionPool
from helper_threading import StoppableThread
import queues
import shared
import state
import tr
from bmconfigparser import BMConfigParser
from debug import logger
from helper_threading import StoppableThread
from network.connectionpool import BMConnectionPool
def createRequestXML(service, action, arguments=None):
@ -85,7 +85,7 @@ class UPnPError(Exception):
class Router: # pylint: disable=old-style-class
"""TBC"""
"""Encapulate routing"""
name = ""
path = ""
address = None