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:
parent
ae5415a26b
commit
9821cc4510
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -17,3 +17,5 @@ dist
|
||||||
docs/_*/*
|
docs/_*/*
|
||||||
docs/autodoc/
|
docs/autodoc/
|
||||||
pyan/
|
pyan/
|
||||||
|
build/scripts-2.7/
|
||||||
|
desktop/icons/
|
||||||
|
|
12
INSTALL.md
12
INSTALL.md
|
@ -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/`
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
27
checkdeps.py
27
checkdeps.py
|
@ -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
|
||||||
|
|
14
fabfile/app_path.py
Normal file
14
fabfile/app_path.py
Normal 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)
|
|
@ -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"):
|
||||||
|
with settings(warn_only=True):
|
||||||
|
with hide('warnings'):
|
||||||
|
if run('stat {}'.format(os.path.abspath(line))).succeeded:
|
||||||
results.append(os.path.abspath(line))
|
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):
|
||||||
|
|
|
@ -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
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
18
setup.cfg
18
setup.cfg
|
@ -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
|
||||||
|
|
45
setup.py
45
setup.py
|
@ -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=[
|
||||||
|
@ -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}
|
||||||
|
|
50
src/api.py
50
src/api.py
|
@ -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
13
src/bitmessagecli.py
Normal file → Executable 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'
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)):
|
||||||
|
|
|
@ -7,8 +7,6 @@ Account related functions.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
14
src/pathmagic.py
Normal 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)
|
|
@ -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(
|
tr._translate(
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.'
|
'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
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
14
src/upnp.py
14
src/upnp.py
|
@ -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
|
||||||
|
|
Reference in New Issue
Block a user