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/_*/*
docs/autodoc/ docs/autodoc/
pyan/ 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. Please note that some versions of OS X don't work.
#### Windows #### 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 ### 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 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 ## 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 #!/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 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. EXTRAS_REQUIRE. This is fine because most developers do, too.
""" """
from __future__ import print_function
import os import os
from distutils.errors import CompileError from distutils.errors import CompileError
from importlib import import_module
from src.depends import PACKAGE_MANAGER, PACKAGES, detectOS
try: try:
from setuptools.dist import Distribution from setuptools.dist import Distribution
from setuptools.extension import Extension from setuptools.extension import Extension
@ -23,10 +30,6 @@ except ImportError:
HAVE_SETUPTOOLS = False HAVE_SETUPTOOLS = False
EXTRAS_REQUIRE = [] EXTRAS_REQUIRE = []
from importlib import import_module
from src.depends import detectOS, PACKAGES, PACKAGE_MANAGER
COMPILING = { COMPILING = {
"Debian": "build-essential libssl-dev", "Debian": "build-essential libssl-dev",
@ -51,10 +54,23 @@ EXTRAS_REQUIRE_DEPS = {
"Guix": [""], "Guix": [""],
"Gentoo": ["dev-python/python-prctl"], "Gentoo": ["dev-python/python-prctl"],
}, },
'devops': {
"OpenBSD": [""],
"FreeBSD": [""],
"Debian": ["libncurses5-dev"],
"Ubuntu": [""],
"Ubuntu 12": [""],
"openSUSE": [""],
"Fedora": [""],
"Guix": [""],
"Gentoo": [""],
},
} }
def detectPrereqs(missing=True): def detectPrereqs(missing=True):
"""Detect pre-requesits of PACKAGES from src.depends"""
available = [] available = []
for module in PACKAGES: for module in PACKAGES:
try: try:
@ -68,6 +84,7 @@ def detectPrereqs(missing=True):
def prereqToPackages(): def prereqToPackages():
"""Detect OS-specific package depenedncies"""
if not detectPrereqs(): if not detectPrereqs():
return return
print("%s %s" % ( print("%s %s" % (
@ -76,6 +93,7 @@ def prereqToPackages():
def compilerToPackages(): def compilerToPackages():
"""Detect OS-specific compiler packages"""
if not detectOS() in COMPILING: if not detectOS() in COMPILING:
return return
print("%s %s" % ( print("%s %s" % (
@ -83,6 +101,7 @@ def compilerToPackages():
def testCompiler(): def testCompiler():
"""Test the compiler and dependencies"""
if not HAVE_SETUPTOOLS: if not HAVE_SETUPTOOLS:
# silent, we can't test without setuptools # silent, we can't test without setuptools
return True return True
@ -137,9 +156,9 @@ OPSYS = detectOS()
CMD = PACKAGE_MANAGER[OPSYS] if OPSYS in PACKAGE_MANAGER else 'UNKNOWN_INSTALLER' CMD = PACKAGE_MANAGER[OPSYS] if OPSYS in PACKAGE_MANAGER else 'UNKNOWN_INSTALLER'
for lhs, rhs in EXTRAS_REQUIRE.items(): for lhs, rhs in EXTRAS_REQUIRE.items():
if rhs and any([ if rhs and any([
EXTRAS_REQUIRE_DEPS[x][OPSYS] EXTRAS_REQUIRE_DEPS[x][OPSYS]
for x in rhs for x in rhs
if x in EXTRAS_REQUIRE_DEPS if x in EXTRAS_REQUIRE_DEPS
]): ]):
rhs_cmd = ''.join([ rhs_cmd = ''.join([
CMD, 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 os
import sys
import re import re
import sys
from functools import wraps 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 fabric.context_managers import settings, shell_env
from fabvenv import virtualenv from fabvenv import virtualenv
FABRIC_ROOT = os.path.dirname(__file__) FABRIC_ROOT = os.path.dirname(__file__)
PROJECT_ROOT = os.path.dirname(FABRIC_ROOT) PROJECT_ROOT = os.path.dirname(FABRIC_ROOT)
VENV_ROOT = os.path.expanduser(os.path.join('~', '.virtualenvs', 'pybitmessage-devops')) 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) clean = re.sub('\n', '', clean)
for line in clean.split('\r'): for line in clean.split('\r'):
if line.endswith(".py"): 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 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): def autopep8(path_to_file):
"""Run autopep8 on a file""" """Run autopep8 on a file"""
with virtualenv(VENV_ROOT): 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) 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. representation of true or false that coerce_bool() understands.
""" """
import os import os
import sys 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 fabric.contrib.project import rsync_project
from fabvenv import virtualenv from fabvenv import virtualenv
from fabfile.lib import ( import fabfile.app_path # pylint: disable=unused-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,
)
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src'))) # noqa:E402 from version import softwareVersion
from version import softwareVersion # pylint: disable=wrong-import-position
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): def get_tool_results(file_list):
@ -69,6 +69,7 @@ def print_results(results, top, verbose, details):
print line print line
if details: if details:
print
print "pycodestyle:" print "pycodestyle:"
for detail in flatten(item['pycodestyle_violations']): for detail in flatten(item['pycodestyle_violations']):
print detail print detail
@ -107,7 +108,7 @@ def generate_file_list(filename):
if filename: if filename:
filename = os.path.abspath(filename) filename = os.path.abspath(filename)
if not os.path.exists(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) sys.exit(1)
else: else:
file_list = [filename] 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) results = get_tool_results(file_list)
if fix: if fix:
for item in sort_and_slice(results, top): if filename:
autopep8(item['path_to_file']) 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 # Recalculate results after autopep8 to surprise the user the least
results = get_tool_results(file_list) results = get_tool_results(file_list)

View File

@ -7,13 +7,27 @@ ignore = E722,E402
[flake8] [flake8]
max-line-length = 119 max-line-length = 119
ignore = E402,E722,F841 ignore = E402,E722,F401,F841
# E402: pylint is preferred for wrong-import-position # E402: pylint is preferred for wrong-import-position
# E722: pylint is preferred for bare-except # E722: pylint is preferred for bare-except
# F401: pylint is preferred for unused-import
# F841: pylint is preferred for unused-variable # F841: pylint is preferred for unused-variable
# pylint honours the [MESSAGES CONTROL] section # pylint honours the [MESSAGES CONTROL] section
[MESSAGES CONTROL] [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 # invalid-name: needs fixing during a large, project-wide refactor
# bare-except,broad-except: Need fixing once thorough testing is easier # 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 #!/usr/bin/env python2.7
"""
setup.py
========
Install the pybitmessage package and dependencies.
"""
from __future__ import print_function
import os import os
import shutil import shutil
from setuptools import setup, Extension from setuptools import Extension, setup
from setuptools.command.install import install from setuptools.command.install import install
from src.version import softwareVersion from src.version import softwareVersion
EXTRAS_REQUIRE = { EXTRAS_REQUIRE = {
'gir': ['pygobject'], 'gir': ['pygobject'],
'notify2': ['notify2'], 'notify2': ['notify2'],
@ -16,17 +23,25 @@ EXTRAS_REQUIRE = {
'prctl': ['python_prctl'], # Named threads 'prctl': ['python_prctl'], # Named threads
'qrcode': ['qrcode'], 'qrcode': ['qrcode'],
'sound;platform_system=="Windows"': ['winsound'], 'sound;platform_system=="Windows"': ['winsound'],
'docs': [ 'devops': [
'sphinx', # fab build_docs '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 'graphviz', # fab build_docs
'curses', # src/depends.py 'isort', # fab code_quality
'python2-pythondialog', # src/depends.py
'm2r', # fab build_docs '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): class InstallCmd(install):
"""Install PyBitmessage"""
def run(self): def run(self):
# prepare icons directories # prepare icons directories
try: try:
@ -46,6 +61,7 @@ class InstallCmd(install):
if __name__ == "__main__": if __name__ == "__main__":
here = os.path.abspath(os.path.dirname(__file__)) here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'README.md')) as f: with open(os.path.join(here, 'README.md')) as f:
README = f.read() README = f.read()
@ -63,21 +79,21 @@ if __name__ == "__main__":
'pybitmessage.bitmessagecurses', 'pybitmessage.bitmessagecurses',
'pybitmessage.messagetypes', 'pybitmessage.messagetypes',
'pybitmessage.network', 'pybitmessage.network',
'pybitmessage.plugins',
'pybitmessage.pyelliptic', 'pybitmessage.pyelliptic',
'pybitmessage.socks', 'pybitmessage.socks',
'pybitmessage.storage', 'pybitmessage.storage',
'pybitmessage.plugins'
] ]
# this will silently accept alternative providers of msgpack # this will silently accept alternative providers of msgpack
# if they are already installed # if they are already installed
try: try:
import msgpack import msgpack # pylint: disable=unused-import
installRequires.append("msgpack-python") installRequires.append("msgpack-python")
except ImportError: except ImportError:
try: try:
import umsgpack import umsgpack # pylint: disable=unused-import
installRequires.append("umsgpack") installRequires.append("umsgpack")
except ImportError: except ImportError:
packages += ['pybitmessage.fallback', 'pybitmessage.fallback.umsgpack'] packages += ['pybitmessage.fallback', 'pybitmessage.fallback.umsgpack']
@ -89,12 +105,10 @@ if __name__ == "__main__":
"a P2P communications protocol", "a P2P communications protocol",
long_description=README, long_description=README,
license='MIT', license='MIT',
# TODO: add author info author='The Bitmessage Team',
#author='', author_email='surda@economicsofbitcoin.com',
#author_email='',
url='https://bitmessage.org', url='https://bitmessage.org',
# TODO: add keywords keywords='bitmessage pybitmessage',
#keywords='',
install_requires=installRequires, install_requires=installRequires,
extras_require=EXTRAS_REQUIRE, extras_require=EXTRAS_REQUIRE,
classifiers=[ classifiers=[
@ -114,11 +128,11 @@ if __name__ == "__main__":
]}, ]},
data_files=[ data_files=[
('share/applications/', ('share/applications/',
['desktop/pybitmessage.desktop']), ['desktop/pybitmessage.desktop']),
('share/icons/hicolor/scalable/apps/', ('share/icons/hicolor/scalable/apps/',
['desktop/icons/scalable/pybitmessage.svg']), ['desktop/icons/scalable/pybitmessage.svg']),
('share/icons/hicolor/24x24/apps/', ('share/icons/hicolor/24x24/apps/',
['desktop/icons/24x24/pybitmessage.png']) ['desktop/icons/24x24/pybitmessage.png'])
], ],
ext_modules=[bitmsghash], ext_modules=[bitmsghash],
zip_safe=False, zip_safe=False,
@ -141,9 +155,6 @@ if __name__ == "__main__":
'libmessaging =' 'libmessaging ='
'pybitmessage.plugins.indicator_libmessaging [gir]' 'pybitmessage.plugins.indicator_libmessaging [gir]'
], ],
# 'console_scripts': [
# 'pybitmessage = pybitmessage.bitmessagemain:main'
# ]
}, },
scripts=['src/pybitmessage'], scripts=['src/pybitmessage'],
cmdclass={'install': InstallCmd} 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/API ) and optionally enable daemon mode
( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py. ( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py.
""" """
from __future__ import absolute_import from __future__ import absolute_import
import base64 import base64
import hashlib import hashlib
import json import json
from struct import pack
import time import time
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer 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 defaults
import helper_inbox import helper_inbox
import helper_sent import helper_sent
import state
import queues
import shutdown
import network.stats 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 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]' str_chan = '[chan]'
@ -116,7 +108,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
response = self.server._marshaled_dispatch( # pylint: disable=protected-access response = self.server._marshaled_dispatch( # pylint: disable=protected-access
data, getattr(self, '_dispatch', None) 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 # internal error, report as HTTP server error
self.send_response(500) self.send_response(500)
self.end_headers() self.end_headers()
@ -328,7 +320,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label = self._decode(label, "base64") label = self._decode(label, "base64")
try: try:
unicode(label, 'utf-8') unicode(label, 'utf-8')
except: except BaseException:
raise APIError(17, 'Label is not valid UTF-8 data.') raise APIError(17, 'Label is not valid UTF-8 data.')
queues.apiAddressGeneratorReturnQueue.queue.clear() queues.apiAddressGeneratorReturnQueue.queue.clear()
streamNumberForAddress = 1 streamNumberForAddress = 1
@ -505,7 +497,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
try: try:
unicode(passphrase, 'utf-8') unicode(passphrase, 'utf-8')
label = str_chan + ' ' + passphrase label = str_chan + ' ' + passphrase
except: except BaseException:
label = str_chan + ' ' + repr(passphrase) label = str_chan + ' ' + repr(passphrase)
addressVersionNumber = 4 addressVersionNumber = 4
@ -538,7 +530,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
try: try:
unicode(passphrase, 'utf-8') unicode(passphrase, 'utf-8')
label = str_chan + ' ' + passphrase label = str_chan + ' ' + passphrase
except: except BaseException:
label = str_chan + ' ' + repr(passphrase) label = str_chan + ' ' + repr(passphrase)
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress( # pylint: disable=unused-variable status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress( # pylint: disable=unused-variable
@ -925,7 +917,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
try: try:
fromAddressEnabled = BMConfigParser().getboolean( fromAddressEnabled = BMConfigParser().getboolean(
fromAddress, 'enabled') fromAddress, 'enabled')
except: except BaseException:
raise APIError( raise APIError(
13, 'Could not find your fromAddress in the keys.dat file.') 13, 'Could not find your fromAddress in the keys.dat file.')
if not fromAddressEnabled: if not fromAddressEnabled:
@ -997,7 +989,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
self._verifyAddress(fromAddress) self._verifyAddress(fromAddress)
try: try:
BMConfigParser().getboolean(fromAddress, 'enabled') BMConfigParser().getboolean(fromAddress, 'enabled')
except: except BaseException:
raise APIError( raise APIError(
13, 'could not find your fromAddress in the keys.dat file.') 13, 'could not find your fromAddress in the keys.dat file.')
streamNumber = decodeAddress(fromAddress)[2] streamNumber = decodeAddress(fromAddress)[2]
@ -1060,7 +1052,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label = self._decode(label, "base64") label = self._decode(label, "base64")
try: try:
unicode(label, 'utf-8') unicode(label, 'utf-8')
except: except BaseException:
raise APIError(17, 'Label is not valid UTF-8 data.') raise APIError(17, 'Label is not valid UTF-8 data.')
if len(params) > 2: if len(params) > 2:
raise APIError(0, 'I need either 1 or 2 parameters!') raise APIError(0, 'I need either 1 or 2 parameters!')
@ -1147,7 +1139,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
'POW took', int(time.time() - powStartTime), 'seconds.', 'POW took', int(time.time() - powStartTime), 'seconds.',
nonce / (time.time() - powStartTime), 'nonce trials per second.', nonce / (time.time() - powStartTime), 'nonce trials per second.',
) )
except: except BaseException:
pass pass
encryptedPayload = pack('>Q', nonce) + encryptedPayload encryptedPayload = pack('>Q', nonce) + encryptedPayload
toStreamNumber = decodeVarint(encryptedPayload[16:26])[0] 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: TODO: fix the following (currently ignored) violations:
""" """
from __future__ import absolute_import
import xmlrpclib
import datetime import datetime
import imghdr import imghdr
import ntpath
import json import json
import socket import ntpath
import time
import sys
import os import os
import socket
import sys
import time
import xmlrpclib
import pathmagic
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
api = '' api = ''
keysName = 'keys.dat' keysName = 'keys.dat'
keysPath = 'keys.dat' keysPath = 'keys.dat'

View File

@ -31,49 +31,32 @@ from struct import pack
from subprocess import call from subprocess import call
from time import sleep 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 defaults
import depends 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_generic
import helper_threading 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() depends.check_dependencies()
@ -95,7 +78,7 @@ def connectToStream(streamNumber):
if BMConfigParser().get( if BMConfigParser().get(
'bitmessagesettings', 'socksproxytype') != 'none': 'bitmessagesettings', 'socksproxytype') != 'none':
state.maximumNumberOfHalfOpenConnections = 4 state.maximumNumberOfHalfOpenConnections = 4
except: except BaseException:
pass pass
with knownnodes.knownNodesLock: with knownnodes.knownNodesLock:
@ -188,7 +171,7 @@ class singleAPI(threading.Thread, helper_threading.StoppableThread):
)) ))
s.shutdown(socket.SHUT_RDWR) s.shutdown(socket.SHUT_RDWR)
s.close() s.close()
except: except BaseException:
pass pass
def run(self): def run(self):
@ -364,11 +347,11 @@ class Main(object):
try: try:
apiNotifyPath = BMConfigParser().get( apiNotifyPath = BMConfigParser().get(
'bitmessagesettings', 'apinotifypath') 'bitmessagesettings', 'apinotifypath')
except: except BaseException:
apiNotifyPath = '' apiNotifyPath = ''
if apiNotifyPath != '': if apiNotifyPath != '':
with shared.printLock: with shared.printLock:
print('Trying to call', apiNotifyPath) print 'Trying to call', apiNotifyPath
call([apiNotifyPath, "startingUp"]) call([apiNotifyPath, "startingUp"])
singleAPIThread = singleAPI() singleAPIThread = singleAPI()
@ -414,7 +397,7 @@ class Main(object):
if state.curses: if state.curses:
if not depends.check_curses(): if not depends.check_curses():
sys.exit() sys.exit()
print('Running with curses') print 'Running with curses'
import bitmessagecurses import bitmessagecurses
bitmessagecurses.runwrapper() bitmessagecurses.runwrapper()
elif state.kivy: elif state.kivy:

View File

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

View File

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

View File

@ -1,29 +1,23 @@
# -*- coding: utf-8 -*- # -*- 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 Originally generated from reading ui file 'bitmessageui.ui'. Since then maintained manually.
by: PyQt4 UI code generator 4.10.4
WARNING! All changes made in this file will be lost!
""" """
from __future__ import absolute_import
import sys import sys
from PyQt4 import QtCore, QtGui 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 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: try:
_fromUtf8 = QtCore.QString.fromUtf8 _fromUtf8 = QtCore.QString.fromUtf8
@ -760,7 +754,7 @@ class Ui_MainWindow(object):
hours = 48 hours = 48
try: try:
hours = int(BMConfigParser().getint('bitmessagesettings', 'ttl') / 60 / 60) hours = int(BMConfigParser().getint('bitmessagesettings', 'ttl') / 60 / 60)
except: except BaseException:
pass pass
self.labelHumanFriendlyTTLDescription.setText( self.labelHumanFriendlyTTLDescription.setText(
_translate( _translate(

View File

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

View File

@ -11,25 +11,26 @@ import socket
import struct import struct
import time import time
import addresses
import helper_random
import knownnodes
import network.connectionpool
import protocol
import shared
import state
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from debug import logger from debug import logger
from inventory import Inventory from inventory import Inventory
import knownnodes
from network.advanceddispatcher import AdvancedDispatcher from network.advanceddispatcher import AdvancedDispatcher
from network.bmobject import (
BMObject, BMObjectAlreadyHaveError, BMObjectExpiredError, BMObjectInsufficientPOWError, BMObjectInvalidDataError,
BMObjectInvalidError, BMObjectUnwantedStreamError
)
from network.dandelion import Dandelion 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.node import Node
from network.objectracker import ObjectTracker from network.objectracker import ObjectTracker
from network.proxy import ProxyError from network.proxy import ProxyError
from queues import addrQueue, invQueue, objectProcessorQueue, portCheckerQueue
import addresses
from queues import objectProcessorQueue, portCheckerQueue, invQueue, addrQueue
import shared
import state
import protocol
import helper_random
class BMProtoError(ProxyError): class BMProtoError(ProxyError):
@ -74,7 +75,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
self.local = False self.local = False
def bm_proto_reset(self): def bm_proto_reset(self):
"""TBC""" """Reset the bitmessage object parser"""
self.magic = None self.magic = None
self.command = None self.command = None
self.payloadLength = 0 self.payloadLength = 0
@ -86,7 +87,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
self.object = None self.object = None
def state_bm_header(self): 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.magic, self.command, self.payloadLength, self.checksum = protocol.Header.unpack(
self.read_buf[:protocol.Header.size]) self.read_buf[:protocol.Header.size])
@ -106,7 +107,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True return True
def state_bm_command(self): def state_bm_command(self):
"""TBC""" """Predicate (with logging) to indicate the presence of a command"""
self.payload = self.read_buf[:self.payloadLength] self.payload = self.read_buf[:self.payloadLength]
if self.checksum != hashlib.sha512(self.payload).digest()[0:4]: if self.checksum != hashlib.sha512(self.payload).digest()[0:4]:
logger.debug("Bad checksum, ignoring") logger.debug("Bad checksum, ignoring")
@ -295,16 +296,16 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
raise BMProtoInsufficientDataError() raise BMProtoInsufficientDataError()
def bm_command_error(self): def bm_command_error(self):
"""TBC""" """Decode an error message and log it"""
# pylint: disable=unused-variable # pylint: disable=unused-variable
fatalStatus, banTime, inventoryVector, errorText = self.decode_payload_content("vvlsls") fatalStatus, banTime, inventoryVector, errorText = self.decode_payload_content("vvlsls")
logger.error("%s:%i error: %i, %s", self.destination.host, self.destination.port, fatalStatus, errorText) logger.error("%s:%i error: %i, %s", self.destination.host, self.destination.port, fatalStatus, errorText)
return True return True
def bm_command_getdata(self): 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") items = self.decode_payload_content("l32s")
# ..todo:: skip? # .. todo:: skip?
if time.time() < self.skipUntil: if time.time() < self.skipUntil:
return True return True
# .. todo:: make this more asynchronous # .. todo:: make this more asynchronous
@ -349,13 +350,11 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True return True
def bm_command_inv(self): def bm_command_inv(self):
"""TBC""" """Non-dandelion announce"""
return self._command_inv(False) return self._command_inv(False)
def bm_command_dinv(self): def bm_command_dinv(self):
""" """Dandelion stem announce"""
Dandelion stem announce
"""
return self._command_inv(True) return self._command_inv(True)
def bm_command_object(self): def bm_command_object(self):
@ -442,12 +441,12 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True return True
def bm_command_portcheck(self): def bm_command_portcheck(self):
"""TBC""" """Add a job port of a peer"""
portCheckerQueue.put(state.Peer(self.destination, self.peerNode.port)) portCheckerQueue.put(state.Peer(self.destination, self.peerNode.port))
return True return True
def bm_command_ping(self): def bm_command_ping(self):
"""TBC""" """Respond to a ping"""
self.append_write_buf(protocol.CreatePacket('pong')) self.append_write_buf(protocol.CreatePacket('pong'))
return True return True
@ -457,8 +456,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True return True
def bm_command_verack(self): def bm_command_verack(self):
"""TBC""" """Return True if a verack has been sent, False otherwise"""
self.verackReceived = True self.verackReceived = True
if self.verackSent: if self.verackSent:
if self.isSSL: if self.isSSL:
@ -469,7 +467,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
return True return True
def bm_command_version(self): 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.remoteProtocolVersion, self.services, self.timestamp, self.sockNode, self.peerNode, self.nonce, \
self.userAgent, self.streams = self.decode_payload_content("IQQiiQlsLv") 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.', logger.debug('Closed connection to %s because we are already connected to that IP.',
str(self.destination)) str(self.destination))
return False return False
except: except BaseException:
pass pass
if not self.isOutbound: if not self.isOutbound:
# incoming from a peer we're connected to as outbound, or server full # 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 math
import time
import socket
import random 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 import addresses
from bmconfigparser import BMConfigParser import helper_random
from queues import invQueue, UISignalQueue, receiveDataQueue import knownnodes
import network.asyncore_pollchoose as asyncore
import network.connectionpool
import protocol
import shared import shared
import state 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 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 os
import sys import sys
import time import time
from struct import unpack, pack from struct import pack, unpack
from subprocess import call from subprocess import call
import paths
import openclpow import openclpow
import paths
import queues import queues
import tr
import state import state
import tr
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from debug import logger from debug import logger
bitmsglib = 'bitmsghash.so' bitmsglib = 'bitmsghash.so'
bmpow = None 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]) trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
if trialValue > target: if trialValue > target:
deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus) deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus)
queues.UISignalQueue.put( queues.UISignalQueue.put((
( 'updateStatusBar', (
'updateStatusBar', tr._translate(
( "MainWindow",
tr._translate( 'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.'
"MainWindow", ),
'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.' 1)))
),
1
)
)
)
logger.error( logger.error(
"Your GPUs (%s) did not calculate correctly, disabling OpenCL. Please report to the developers.", "Your GPUs (%s) did not calculate correctly, disabling OpenCL. Please report to the developers.",
deviceNames) deviceNames)
@ -198,7 +192,7 @@ def getPowType():
def notifyBuild(tried=False): def notifyBuild(tried=False):
"""TBC""" """Notify the user of the success or otherwise of building the PoW C module"""
if bmpow: if bmpow:
queues.UISignalQueue.put(('updateStatusBar', (tr._translate( queues.UISignalQueue.put(('updateStatusBar', (tr._translate(
@ -221,7 +215,7 @@ def notifyBuild(tried=False):
def buildCPoW(): def buildCPoW():
"""TBC""" """Attempt to build the PoW C module"""
if bmpow is not None: if bmpow is not None:
return return
if paths.frozen is not None: if paths.frozen is not None:
@ -250,7 +244,7 @@ def run(target, initialHash):
"""Run the proof of work thread""" """Run the proof of work thread"""
if state.shutdown != 0: if state.shutdown != 0:
raise raise # pylint: disable=misplaced-bare-raise
target = int(target) target = int(target)
if openclpow.openclEnabled(): if openclpow.openclEnabled():
try: try:
@ -287,7 +281,7 @@ def run(target, initialHash):
def resetPoW(): def resetPoW():
"""TBC""" """Initialise the OpenCL PoW"""
openclpow.initCL() openclpow.initCL()
@ -295,7 +289,7 @@ def resetPoW():
def init(): def init():
"""TBC""" """Initialise PoW"""
# pylint: disable=global-statement # pylint: disable=global-statement
global bitmsglib, bmpow global bitmsglib, bmpow

View File

@ -1,8 +1,12 @@
#!/usr/bin/python2.7 #!/usr/bin/env python2.7
import os import os
import sys
import pkg_resources import pkg_resources
import pybitmessage.pathmagic
dist = pkg_resources.get_distribution('pybitmessage') dist = pkg_resources.get_distribution('pybitmessage')
script_file = os.path.join(dist.location, dist.key, 'bitmessagemain.py') script_file = os.path.join(dist.location, dist.key, 'bitmessagemain.py')
new_globals = globals() 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 from __future__ import absolute_import
import httplib import httplib
from random import randint
import socket import socket
from struct import unpack
import threading import threading
import time import time
import urllib2 import urllib2
from random import randint
from struct import unpack
from urlparse import urlparse from urlparse import urlparse
from xml.dom.minidom import Document, parseString 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 queues
import shared import shared
import state import state
import tr 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): def createRequestXML(service, action, arguments=None):
@ -85,7 +85,7 @@ class UPnPError(Exception):
class Router: # pylint: disable=old-style-class class Router: # pylint: disable=old-style-class
"""TBC""" """Encapulate routing"""
name = "" name = ""
path = "" path = ""
address = None address = None