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)
|
|
33
checkdeps.py
33
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
|
||||||
|
@ -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
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"):
|
||||||
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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
51
setup.py
51
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=[
|
||||||
|
@ -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}
|
||||||
|
|
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:
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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(
|
||||||
(
|
"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
|
||||||
|
|
||||||
|
|
|
@ -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