diff --git a/TODO b/TODO
index b5c8430d..89affccd 100644
--- a/TODO
+++ b/TODO
@@ -3,6 +3,7 @@ Client:
- Wizard
- Multiple wallets
- Themes
+- Extend GUI with history view (View -> Show History)
- Settings window
Server:
diff --git a/data/noface.svg b/data/noface.svg
index 9956854c..dc24f111 100644
--- a/data/noface.svg
+++ b/data/noface.svg
@@ -52,7 +52,7 @@
inkscape:groupmode="layer"
id="layer1">
.
-import re, sys
+import re
+import sys
+# import argparse
+import optparse
+
try:
from lib.util import print_error
except ImportError:
@@ -24,22 +28,19 @@ except ImportError:
try:
import ecdsa
-except:
- print_error("Error: python-ecdsa does not seem to be installed. Try 'sudo pip install ecdsa'")
- sys.exit(1)
+except ImportError:
+ sys.exit("Error: python-ecdsa does not seem to be installed. Try 'sudo pip install ecdsa'")
try:
import aes
-except:
- print_error("Error: AES does not seem to be installed. Try 'sudo pip install slowaes'")
- sys.exit(1)
+except ImportError:
+ sys.exit("Error: AES does not seem to be installed. Try 'sudo pip install slowaes'")
try:
from lib import Wallet, WalletSynchronizer, format_satoshis, mnemonic, prompt_password
except ImportError:
from electrum import Wallet, WalletSynchronizer, format_satoshis, mnemonic, prompt_password
-from optparse import OptionParser
from decimal import Decimal
known_commands = {
@@ -77,9 +78,9 @@ options:\n --fee, -f: set transaction fee\n --fromaddr, -s: send from address
'import':
'Imports a key pair\nSyntax: import
:',
'signmessage':
- 'Signs a message with a key\nSyntax: signmessage ',
+ 'Signs a message with a key\nSyntax: signmessage \nIf you want to lead or end a message with spaces, or want double spaces inside the message make sure you quote the string. I.e. " Hello This is a weird String "',
'verifymessage':
- 'Verifies a signature\nSyntax: verifymessage ',
+ 'Verifies a signature\nSyntax: verifymessage \nIf you want to lead or end a message with spaces, or want double spaces inside the message make sure you quote the string. I.e. " Hello This is a weird String "',
'eval':
"Run python eval() on an object\nSyntax: eval \nExample: eval \"wallet.aliases\"",
'deseed':
@@ -101,7 +102,7 @@ protected_commands = ['payto', 'password', 'mktx', 'seed', 'import','signmessage
if __name__ == '__main__':
usage = "usage: %prog [options] command\nCommands: "+ (', '.join(known_commands))
- parser = OptionParser(usage=usage)
+ parser = optparse.OptionParser(prog=usage)
parser.add_option("-g", "--gui", dest="gui", default="lite", help="gui")
parser.add_option("-w", "--wallet", dest="wallet_path", help="wallet path (default: electrum.dat)")
parser.add_option("-o", "--offline", action="store_true", dest="offline", default=False, help="remain offline")
@@ -128,7 +129,9 @@ if __name__ == '__main__':
else:
cmd = args[0]
firstarg = args[1] if len(args) > 1 else ''
-
+
+ #this entire if/else block is just concerned with importing the
+ #right GUI toolkit based the GUI command line option given
if cmd == 'gui':
if options.gui=='gtk':
@@ -165,16 +168,17 @@ if __name__ == '__main__':
except ImportError:
import electrum.gui_qt as gui
else:
+ #use the lite version if no toolkit specified
try:
import lib.gui_lite as gui
except ImportError:
import electrum.gui_lite as gui
else:
- print_error("Error: Unknown GUI: " + options.gui)
- exit(1)
+ sys.exit("Error: Unknown GUI: " + options.gui)
gui = gui.ElectrumGui(wallet)
- WalletSynchronizer(wallet,True).start()
+ interface = WalletSynchronizer(wallet, True, gui.server_list_changed)
+ interface.start()
try:
found = wallet.file_exists
@@ -198,15 +202,13 @@ if __name__ == '__main__':
cmd = 'help'
if not wallet.file_exists and cmd not in ['help','create','restore']:
- print_error("Error: Wallet file not found.")
- print_error("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option")
+ print "Error: Wallet file not found."
+ print "Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option"
sys.exit(0)
if cmd in ['create', 'restore']:
if wallet.file_exists:
- print_error("Error: Remove the existing wallet first!")
- sys.stderr.flush()
- sys.exit(0)
+ sys.exit("Error: Remove the existing wallet first!")
password = prompt_password("Password (hit return if you do not wish to encrypt your wallet):")
w_host, w_port, w_protocol = wallet.server.split(':')
@@ -230,8 +232,7 @@ if __name__ == '__main__':
print_error("Warning: Not hex, trying decode.")
seed = mnemonic.mn_decode( seed.split(' ') )
if not seed:
- print_error("Error: No seed")
- sys.exit(1)
+ sys.exit("Error: No seed")
wallet.seed = str(seed)
wallet.init_mpk( wallet.seed )
@@ -316,7 +317,6 @@ if __name__ == '__main__':
cmd2 = firstarg
if cmd2 not in known_commands:
parser.print_help()
- print
print "Type 'electrum help ' to see the help for a specific command"
print "Type 'electrum --help' to see the list of options"
print "List of commands:", ', '.join(known_commands)
@@ -355,17 +355,15 @@ if __name__ == '__main__':
f = open(ns,'r')
data = f.read()
f.close()
- except:
- print_error("Error: Seed file not found")
- sys.exit()
+ except IOError:
+ sys.exit("Error: Seed file not found")
try:
import ast
d = ast.literal_eval( data )
seed = d['seed']
imported_keys = d.get('imported_keys',{})
except:
- print_error("Error: Error with seed file")
- sys.exit(1)
+ sys.exit("Error: Error with seed file")
mpk = wallet.master_public_key
wallet.seed = seed
@@ -511,9 +509,8 @@ if __name__ == '__main__':
elif cmd == 'password':
try:
seed = wallet.pw_decode( wallet.seed, password)
- except:
- print_error("Error: Password does not decrypt this wallet.")
- sys.exit(1)
+ except ValueError:
+ sys.exit("Error: Password does not decrypt this wallet.")
new_password = prompt_password('New password:')
wallet.update_password(seed, password, new_password)
@@ -543,7 +540,8 @@ if __name__ == '__main__':
try:
wallet.verify_message(address, signature, message)
print True
- except:
+ except BaseException as e:
+ print "Verification error: {0}".format(e)
print False
elif cmd == 'freeze':
diff --git a/electrum.png b/electrum.png
index f47d03b0..a45fe95d 100644
Binary files a/electrum.png and b/electrum.png differ
diff --git a/lib/exchange_rate.py b/lib/exchange_rate.py
index e8c9fac2..77cbf9b1 100644
--- a/lib/exchange_rate.py
+++ b/lib/exchange_rate.py
@@ -31,7 +31,7 @@ class Exchanger(threading.Thread):
connection = httplib.HTTPSConnection('intersango.com')
connection.request("GET", "/api/ticker.php")
response = connection.getresponse()
- if response.status == 404:
+ if response.reason == httplib.responses[httplib.NOT_FOUND]:
return
response = json.loads(response.read())
# 1 = BTC:GBP
@@ -40,16 +40,16 @@ class Exchanger(threading.Thread):
# 4 = BTC:PLN
quote_currencies = {}
try:
- quote_currencies["GBP"] = self.lookup_rate(response, 1)
- quote_currencies["EUR"] = self.lookup_rate(response, 2)
- quote_currencies["USD"] = self.lookup_rate(response, 3)
+ quote_currencies["GBP"] = self._lookup_rate(response, 1)
+ quote_currencies["EUR"] = self._lookup_rate(response, 2)
+ quote_currencies["USD"] = self._lookup_rate(response, 3)
with self.lock:
self.quote_currencies = quote_currencies
self.parent.emit(SIGNAL("refresh_balance()"))
except KeyError:
pass
- def lookup_rate(self, response, quote_id):
+ def _lookup_rate(self, response, quote_id):
return decimal.Decimal(response[str(quote_id)]["last"])
if __name__ == "__main__":
diff --git a/lib/gui_lite.py b/lib/gui_lite.py
index 6112b246..f63c1812 100644
--- a/lib/gui_lite.py
+++ b/lib/gui_lite.py
@@ -4,6 +4,7 @@ from PyQt4.QtCore import *
from PyQt4.QtGui import *
from decimal import Decimal as D
+from interface import DEFAULT_SERVERS
from util import get_resource_path as rsrc
from i18n import _
import decimal
@@ -41,14 +42,18 @@ def resize_line_edit_width(line_edit, text_input):
text_input += "A"
line_edit.setMinimumWidth(metrics.width(text_input))
-class ElectrumGui:
+class ElectrumGui(QObject):
def __init__(self, wallet):
+ super(QObject, self).__init__()
+
self.wallet = wallet
self.app = QApplication(sys.argv)
def main(self, url):
actuator = MiniActuator(self.wallet)
+ self.connect(self, SIGNAL("updateservers()"),
+ actuator.update_servers_list)
# Should probably not modify the current path but instead
# change the behaviour of rsrc(...)
old_path = QDir.currentPath()
@@ -73,7 +78,11 @@ class ElectrumGui:
self.app.exec_()
+ def server_list_changed(self):
+ self.emit(SIGNAL("updateservers()"))
+
def expand(self):
+ """Hide the lite mode window and show pro-mode."""
self.mini.hide()
self.expert.show()
@@ -174,13 +183,15 @@ class MiniWindow(QDialog):
menubar = QMenuBar()
electrum_menu = menubar.addMenu(_("&Bitcoin"))
- self.servers_menu = electrum_menu.addMenu(_("&Servers"))
- self.servers_menu.addAction(_("Foo"))
+ servers_menu = electrum_menu.addMenu(_("&Servers"))
+ servers_group = QActionGroup(self)
+ self.actuator.set_servers_gui_stuff(servers_menu, servers_group)
+ self.actuator.populate_servers_menu()
electrum_menu.addSeparator()
brain_seed = electrum_menu.addAction(_("&BrainWallet Info"))
brain_seed.triggered.connect(self.actuator.show_seed_dialog)
-
- electrum_menu.addAction(_("&Quit"))
+ quit_option = electrum_menu.addAction(_("&Quit"))
+ quit_option.triggered.connect(self.close)
view_menu = menubar.addMenu(_("&View"))
expert_gui = view_menu.addAction(_("&Pro Mode"))
@@ -254,9 +265,10 @@ class MiniWindow(QDialog):
pass
def set_quote_currency(self, currency):
+ """Set and display the fiat currency country."""
assert currency in self.quote_currencies
self.quote_currencies.remove(currency)
- self.quote_currencies = [currency] + self.quote_currencies
+ self.quote_currencies.insert(0, currency)
self.refresh_balance()
def change_quote_currency(self):
@@ -274,6 +286,7 @@ class MiniWindow(QDialog):
self.amount_input_changed(self.amount_input.text())
def set_balances(self, btc_balance):
+ """Set the bitcoin balance and update the amount label accordingly."""
self.btc_balance = btc_balance
quote_text = self.create_quote_text(btc_balance)
if quote_text:
@@ -283,6 +296,7 @@ class MiniWindow(QDialog):
self.setWindowTitle("Electrum - %s BTC" % btc_balance)
def amount_input_changed(self, amount_text):
+ """Update the number of bitcoins displayed."""
self.check_button_status()
try:
@@ -298,6 +312,8 @@ class MiniWindow(QDialog):
self.balance_label.show_balance()
def create_quote_text(self, btc_balance):
+ """Return a string copy of the amount fiat currency the
+ user has in bitcoins."""
quote_currency = self.quote_currencies[0]
quote_balance = self.exchanger.exchange(btc_balance, quote_currency)
if quote_balance is None:
@@ -314,8 +330,16 @@ class MiniWindow(QDialog):
self.amount_input.setText("")
def check_button_status(self):
+ """Check that the bitcoin address is valid and that something
+ is entered in the amount before making the send button clickable."""
+ try:
+ value = D(str(self.amount_input.text())) * 10**8
+ except decimal.InvalidOperation:
+ value = None
+ # self.address_input.property(...) returns a qVariant, not a bool.
+ # The == is needed to properly invoke a comparison.
if (self.address_input.property("isValid") == True and
- len(self.amount_input.text()) > 0):
+ value is not None and 0 < value <= self.btc_balance):
self.send_button.setDisabled(False)
else:
self.send_button.setDisabled(True)
@@ -385,10 +409,12 @@ class BalanceLabel(QLabel):
self.amount_text = ""
def mousePressEvent(self, event):
+ """Change the fiat currency selection if window background is clicked."""
if self.state != self.SHOW_CONNECTING:
self.change_quote_currency()
def set_balance_text(self, btc_balance, quote_text):
+ """Set the amount of bitcoins in the gui."""
if self.state == self.SHOW_CONNECTING:
self.state = self.SHOW_BALANCE
self.balance_text = "%s BTC %s" % (btc_balance, quote_text)
@@ -466,7 +492,8 @@ class ReceivePopup(QDialog):
self.setMouseTracking(True)
self.setWindowTitle("Electrum - " + _("Receive Bitcoin payment"))
- self.setWindowFlags(Qt.Window|Qt.FramelessWindowHint|Qt.MSWindowsFixedSizeDialogHint)
+ self.setWindowFlags(Qt.Window|Qt.FramelessWindowHint|
+ Qt.MSWindowsFixedSizeDialogHint)
self.layout().setSizeConstraint(QLayout.SetFixedSize)
#self.setFrameStyle(QFrame.WinPanel|QFrame.Raised)
#self.setAlignment(Qt.AlignCenter)
@@ -480,33 +507,43 @@ class ReceivePopup(QDialog):
self.show()
class MiniActuator:
-
+ """Initialize the definitions relating to themes and
+ sending/recieving bitcoins."""
+
+
def __init__(self, wallet):
+ """Retrieve the gui theme used in previous session."""
self.wallet = wallet
-
self.theme_name = self.wallet.theme
self.themes = util.load_theme_paths()
def load_theme(self):
+ """Load theme retrieved from wallet file."""
try:
theme_prefix, theme_path = self.themes[self.theme_name]
except KeyError:
- util.print_error("Theme not found! ", self.theme_name)
+ util.print_error("Theme not found!", self.theme_name)
return
QDir.setCurrent(os.path.join(theme_prefix, theme_path))
with open(rsrc("style.css")) as style_file:
qApp.setStyleSheet(style_file.read())
def theme_names(self):
- return self.themes.keys()
+ """Sort themes."""
+ return sorted(self.themes.keys())
+
def selected_theme(self):
+ """Select theme."""
return self.theme_name
def change_theme(self, theme_name):
+ """Change theme."""
self.wallet.theme = self.theme_name = theme_name
self.load_theme()
def set_configured_currency(self, set_quote_currency):
+ """Set the inital fiat currency conversion country (USD/EUR/GBP) in
+ the GUI to what it was set to in the wallet."""
currency = self.wallet.conversion_currency
# currency can be none when Electrum is used for the first
# time and no setting has been created yet.
@@ -514,9 +551,70 @@ class MiniActuator:
set_quote_currency(currency)
def set_config_currency(self, conversion_currency):
+ """Change the wallet fiat currency country."""
self.wallet.conversion_currency = conversion_currency
+ def set_servers_gui_stuff(self, servers_menu, servers_group):
+ self.servers_menu = servers_menu
+ self.servers_group = servers_group
+
+ def populate_servers_menu(self):
+ interface = self.wallet.interface
+ if not interface.servers:
+ print "No servers loaded yet."
+ self.servers_list = []
+ for server_string in DEFAULT_SERVERS:
+ host, port, protocol = server_string.split(':')
+ transports = [(protocol,port)]
+ self.servers_list.append((host, transports))
+ else:
+ print "Servers loaded."
+ self.servers_list = interface.servers
+ server_names = [details[0] for details in self.servers_list]
+ current_server = self.wallet.server.split(":")[0]
+ for server_name in server_names:
+ server_action = self.servers_menu.addAction(server_name)
+ server_action.setCheckable(True)
+ if server_name == current_server:
+ server_action.setChecked(True)
+ class SelectServerFunctor:
+ def __init__(self, server_name, server_selected):
+ self.server_name = server_name
+ self.server_selected = server_selected
+ def __call__(self, checked):
+ if checked:
+ # call server_selected
+ self.server_selected(self.server_name)
+ delegate = SelectServerFunctor(server_name, self.server_selected)
+ server_action.toggled.connect(delegate)
+ self.servers_group.addAction(server_action)
+
+ def update_servers_list(self):
+ # Clear servers_group
+ for action in self.servers_group.actions():
+ self.servers_group.removeAction(action)
+ self.populate_servers_menu()
+
+ def server_selected(self, server_name):
+ match = [transports for (host, transports) in self.servers_list
+ if host == server_name]
+ assert len(match) == 1
+ match = match[0]
+ # Default to TCP if available else use anything
+ # TODO: protocol should be selectable.
+ tcp_port = [port for (protocol, port) in match if protocol == "t"]
+ if len(tcp_port) == 0:
+ protocol = match[0][0]
+ port = match[0][1]
+ else:
+ protocol = "t"
+ port = tcp_port[0]
+ server_line = "%s:%s:%s" % (server_name, port, protocol)
+ # Should this have exception handling?
+ self.wallet.set_server(server_line)
+
def copy_address(self, receive_popup):
+ """Copy the wallet addresses into the client."""
addrs = [addr for addr in self.wallet.all_addresses()
if not self.wallet.is_change(addr)]
# Select most recent addresses from gap limit
@@ -527,6 +625,7 @@ class MiniActuator:
receive_popup.popup()
def send(self, address, amount, parent_window):
+ """Send bitcoins to the target address."""
dest_address = self.fetch_destination(address)
if dest_address is None or not self.wallet.is_valid(dest_address):
@@ -589,6 +688,7 @@ class MiniActuator:
return recipient
def is_valid(self, address):
+ """Check if bitcoin address is valid."""
return self.wallet.is_valid(address)
def acceptbit(self, currency):
diff --git a/lib/gui_qt.py b/lib/gui_qt.py
index e866c066..66930735 100644
--- a/lib/gui_qt.py
+++ b/lib/gui_qt.py
@@ -23,9 +23,7 @@ from util import print_error
try:
import PyQt4
except:
- print_error("Error: Could not import PyQt4")
- print_error("on Linux systems, you may try 'sudo apt-get install python-qt4'")
- sys.exit(1)
+ sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'")
from PyQt4.QtGui import *
from PyQt4.QtCore import *
@@ -36,9 +34,7 @@ from interface import DEFAULT_SERVERS
try:
import icons_rc
except:
- print_error("Error: Could not import icons_rc.py")
- print_error("Please generate it with: 'pyrcc4 icons.qrc -o lib/icons_rc.py'")
- sys.exit(1)
+ sys.exit("Error: Could not import icons_rc.py, please generate it with: 'pyrcc4 icons.qrc -o lib/icons_rc.py'")
from wallet import format_satoshis
import bmp, mnemonic, pyqrnative, qrscanner
@@ -1434,6 +1430,9 @@ class ElectrumGui:
if app is None:
self.app = QApplication(sys.argv)
+ def server_list_changed(self):
+ pass
+
def waiting_dialog(self):
s = Timer()
diff --git a/lib/interface.py b/lib/interface.py
index 76a3e4c8..6a28cf8e 100644
--- a/lib/interface.py
+++ b/lib/interface.py
@@ -27,7 +27,7 @@ DEFAULT_TIMEOUT = 5
DEFAULT_SERVERS = [ 'ecdsa.org:50001:t',
'electrum.novit.ro:50001:t',
'uncle-enzo.info:50001:t',
- 'electrum.bytesized-hosting.com:50000:t'] # list of default servers
+ 'electrum.bytesized-hosting.com:50001:t'] # list of default servers
def replace_keys(obj, old_key, new_key):
@@ -306,12 +306,13 @@ class TcpStratumInterface(Interface):
class WalletSynchronizer(threading.Thread):
- def __init__(self, wallet, loop=False):
+ def __init__(self, wallet, loop=False, servers_loaded_callback=None):
threading.Thread.__init__(self)
self.daemon = True
self.wallet = wallet
self.loop = loop
self.init_interface()
+ self.servers_loaded_callback = servers_loaded_callback
def init_interface(self):
try:
@@ -334,7 +335,6 @@ class WalletSynchronizer(threading.Thread):
self.interface = InterfaceClass(host, port, self.wallet.debug_server)
self.wallet.interface = self.interface
-
def handle_response(self, r):
if r is None:
return
@@ -354,15 +354,19 @@ class WalletSynchronizer(threading.Thread):
host = item[1]
ports = []
version = None
- if len(item)>2:
+ if len(item) > 2:
for v in item[2]:
- if re.match("[th]\d+",v):
- ports.append((v[0],v[1:]))
- if re.match("v(.?)+",v):
+ if re.match("[th]\d+", v):
+ ports.append((v[0], v[1:]))
+ if re.match("v(.?)+", v):
version = v[1:]
if ports and version:
- servers.append( (host, ports) )
+ servers.append((host, ports))
self.interface.servers = servers
+ # servers_loaded_callback is None for commands, but should
+ # NEVER be None when using the GUI.
+ if self.servers_loaded_callback is not None:
+ self.servers_loaded_callback()
elif method == 'blockchain.address.subscribe':
addr = params[0]
@@ -425,6 +429,7 @@ class WalletSynchronizer(threading.Thread):
self.wallet.trigger_callbacks()
if self.loop:
time.sleep(5)
+ # Server has been changed. Copy callback for new interface.
self.init_interface()
self.start_interface()
continue
diff --git a/lib/util.py b/lib/util.py
index 98a820c0..2aabcedf 100644
--- a/lib/util.py
+++ b/lib/util.py
@@ -3,12 +3,13 @@ import platform
import sys
def print_error(*args):
- for item in args:
- sys.stderr.write(str(item))
- sys.stderr.write("\n")
+ # Stringify args
+ args = [str(item) for item in args]
+ sys.stderr.write(" ".join(args) + "\n")
sys.stderr.flush()
def appdata_dir():
+ """Find the path to the application data directory; add an electrum folder and return path."""
if platform.system() == "Windows":
return os.path.join(os.environ["APPDATA"], "Electrum")
elif platform.system() == "Linux":
@@ -23,6 +24,7 @@ def get_resource_path(*args):
return os.path.join(".", *args)
def local_data_dir():
+ """Return path to the data folder."""
assert sys.argv
prefix_path = os.path.dirname(sys.argv[0])
local_data = os.path.join(prefix_path, "data")
diff --git a/lib/wallet.py b/lib/wallet.py
index 8c658769..18125891 100644
--- a/lib/wallet.py
+++ b/lib/wallet.py
@@ -16,9 +16,20 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
+import sys
+import base64
+import os
+import re
+import hashlib
+import copy
+import operator
+import ast
+import threading
+import random
+import getpass
+import aes
+import ecdsa
-import sys, base64, os, re, hashlib, copy, operator, ast, threading, random, getpass
-import aes, ecdsa
from ecdsa.util import string_to_number, number_to_string
from util import print_error
@@ -65,8 +76,7 @@ __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars)
def b58encode(v):
- """ encode v, which is a string of bytes, to base58.
- """
+ """ encode v, which is a string of bytes, to base58."""
long_value = 0L
for (i, c) in enumerate(v[::-1]):
@@ -89,8 +99,7 @@ def b58encode(v):
return (__b58chars[0]*nPad) + result
def b58decode(v, length):
- """ decode v into a string of len bytes
- """
+ """ decode v into a string of len bytes."""
long_value = 0L
for (i, c) in enumerate(v[::-1]):
long_value += __b58chars.find(c) * (__b58base**i)
@@ -157,8 +166,7 @@ def prompt_password(prompt, confirm=True):
password2 = getpass.getpass("Confirm: ")
if password != password2:
- print_error("Error: Passwords do not match.")
- sys.exit(1)
+ sys.exit("Error: Passwords do not match.")
else:
password = raw_input(prompt)
@@ -282,7 +290,7 @@ class Wallet:
self.num_zeros = 0
self.master_public_key = ''
self.conversion_currency = None
- self.theme = None
+ self.theme = "Cleanlook"
# saved fields
self.use_encryption = False
@@ -342,7 +350,7 @@ class Wallet:
# raise an error if the format isnt correct
a,b,c = server.split(':')
b = int(b)
- assert c in ['t','h','n']
+ assert c in ['t', 'h', 'n']
# set the server
if server != self.server:
self.server = server
@@ -351,22 +359,24 @@ class Wallet:
self.interface.poke()
def set_path(self, wallet_path):
-
+ """Set the path of the wallet."""
if wallet_path is not None:
self.path = wallet_path
+ return
+ # Look for wallet file in the default data directory.
+ # Keeps backwards compatibility.
+ if "HOME" in os.environ:
+ wallet_dir = os.path.join(os.environ["HOME"], ".electrum")
+ elif "LOCALAPPDATA" in os.environ:
+ wallet_dir = os.path.join(os.environ["LOCALAPPDATA"], "Electrum")
+ elif "APPDATA" in os.environ:
+ wallet_dir = os.path.join(os.environ["APPDATA"], "Electrum")
else:
- # backward compatibility: look for wallet file in the default data directory
- if "HOME" in os.environ:
- wallet_dir = os.path.join( os.environ["HOME"], '.electrum')
- elif "LOCALAPPDATA" in os.environ:
- wallet_dir = os.path.join( os.environ["LOCALAPPDATA"], 'Electrum' )
- elif "APPDATA" in os.environ:
- wallet_dir = os.path.join( os.environ["APPDATA"], 'Electrum' )
- else:
- raise BaseException("No home directory found in environment variables.")
-
- if not os.path.exists( wallet_dir ): os.mkdir( wallet_dir )
- self.path = os.path.join( wallet_dir, 'electrum.dat' )
+ raise BaseException("No home directory found in environment variables.")
+ # Make wallet directory if it does not yet exist.
+ if not os.path.exists(wallet_dir):
+ os.mkdir(wallet_dir)
+ self.path = os.path.join(wallet_dir, "electrum.dat")
def import_key(self, keypair, password):
address, key = keypair.split(':')
@@ -676,19 +686,19 @@ class Wallet:
os.chmod(self.path,stat.S_IREAD | stat.S_IWRITE)
def read(self):
+ """Read the contents of the wallet file."""
import interface
- upgrade_msg = """This wallet seed is deprecated. Please run upgrade.py for a diagnostic."""
self.file_exists = False
try:
- f = open(self.path,"r")
- data = f.read()
- f.close()
- except:
+ with open(self.path, "r") as f:
+ data = f.read()
+ except IOError:
return
try:
- d = ast.literal_eval( data )
+ d = ast.literal_eval( data ) #parse raw data from reading wallet file
interface.old_to_new(d)
+
self.seed_version = d.get('seed_version')
self.master_public_key = d.get('master_public_key').decode('hex')
self.use_encryption = d.get('use_encryption')
@@ -714,12 +724,12 @@ class Wallet:
self.conversion_currency = d.get('conversion_currency', 'USD')
self.theme = d.get('theme', 'Cleanlook')
except:
- raise BaseException("cannot read wallet file")
+ raise IOError("Cannot read wallet file.")
self.update_tx_history()
if self.seed_version != SEED_VERSION:
- raise BaseException(upgrade_msg)
+ raise ValueError("This wallet seed is deprecated. Please run upgrade.py for a diagnostic.")
if self.remote_url: assert self.master_public_key.encode('hex') == self.get_remote_mpk()
@@ -838,7 +848,7 @@ class Wallet:
try:
d.decode('hex')
except:
- raise BaseException("Invalid password")
+ raise ValueError("Invalid password")
return d
else:
return s
@@ -921,10 +931,10 @@ class Wallet:
def mktx(self, to_address, amount, label, password, fee=None, change_addr=None, from_addr= None):
if not self.is_valid(to_address):
- raise BaseException("Invalid address")
+ raise ValueError("Invalid address")
inputs, total, fee = self.choose_tx_inputs( amount, fee, from_addr )
if not inputs:
- raise BaseException("Not enough funds")
+ raise ValueError("Not enough funds")
if not self.use_change and not change_addr:
change_addr = inputs[0][0]
@@ -995,7 +1005,7 @@ class Wallet:
self.verify_message(previous, signature, "alias:%s:%s"%(alias,target))
if not self.is_valid(target):
- raise BaseException("Invalid bitcoin address")
+ raise ValueError("Invalid bitcoin address")
return target, signing_addr, auth_name
diff --git a/setup.py b/setup.py
index fe3049f4..0e2fcb3b 100644
--- a/setup.py
+++ b/setup.py
@@ -7,15 +7,12 @@ from lib.version import ELECTRUM_VERSION as version
import lib.util as util
import os, sys, platform
from lib.util import print_error
-
if sys.version_info[:3] < (2,6,0):
- print_error("Error: Electrum requires Python version >= 2.6.0...")
- sys.exit(1)
-
+ sys.exit("Error: Electrum requires Python version >= 2.6.0...")
data_files = []
-
-if platform.system() != 'Windows' and platform.system() != 'Darwin':
+if (len(sys.argv) > 1 and (sys.argv[1] == "sdist")) or (platform.system() != 'Windows' and platform.system() != 'Darwin'):
+ print "Including all files"
data_files += [
('/usr/share/applications/',['electrum.desktop']),
('/usr/share/app-install/icons/',['electrum.png'])
@@ -27,10 +24,15 @@ if platform.system() != 'Windows' and platform.system() != 'Darwin':
data_files.append( ('/usr/share/locale/%s/LC_MESSAGES'%lang, ['locale/%s/LC_MESSAGES/electrum.mo'%lang]) )
data_files += [
- (util.appdata_dir(), ["data/background.png", "data/style.css"]),
- (os.path.join(util.appdata_dir(), "icons"), [
- "data/icons/confirmed.png",
- "data/icons/unconfirmed.png"
+ (util.appdata_dir(), ["data/noface.svg", "data/README"]),
+ (os.path.join(util.appdata_dir(), "cleanlook"), [
+ "data/cleanlook/name.cfg",
+ "data/cleanlook/style.css"
+ ]),
+ (os.path.join(util.appdata_dir(), "dark"), [
+ "data/dark/background.png",
+ "data/dark/name.cfg",
+ "data/dark/style.css"
])
]