From f101e2e9242b2491db30cb14f6ad971a20d96833 Mon Sep 17 00:00:00 2001 From: Inso <insomniak.fr@gmail.com> Date: Wed, 17 Dec 2014 21:53:50 +0100 Subject: [PATCH] Huge refactoring, pythonify sourcecode and clearer modeling --- lib/ucoinpy/documents/peer.py | 19 ++- res/ui/communityConfigurationDialog.ui | 4 +- src/cutecoin/__init__.py | 10 +- .../account/__init__.py => core/account.py} | 65 ++++++--- src/cutecoin/core/{__init__.py => app.py} | 14 +- src/cutecoin/core/community.py | 124 +++++++++++++++++ .../person/__init__.py => core/person.py} | 0 .../wallet/__init__.py => core/wallet.py} | 14 +- src/cutecoin/gui/addContactDialog.py | 4 +- src/cutecoin/gui/communityTabWidget.py | 4 +- src/cutecoin/gui/importAccountDialog.py | 10 +- src/cutecoin/gui/mainWindow.py | 44 +++--- src/cutecoin/gui/processConfigureAccount.py | 20 ++- src/cutecoin/gui/processConfigureCommunity.py | 47 ++++--- src/cutecoin/gui/transferMoneyDialog.py | 3 +- .../models/account/communities/__init__.py | 82 ----------- .../models/account/communities/itemModel.py | 36 ----- .../models/account/wallets/__init__.py | 74 ---------- .../listModel.py => communities.py} | 0 .../{community/itemModel.py => community.py} | 0 src/cutecoin/models/community/__init__.py | 129 ------------------ .../membersListModel.py => members.py} | 2 +- src/cutecoin/models/node/__init__.py | 76 ----------- .../models/{node/itemModel.py => peer.py} | 18 +-- .../models/{node/treeModel.py => peering.py} | 50 +++---- .../receivedListModel.py => received.py} | 0 .../{transaction/sentListModel.py => sent.py} | 0 src/cutecoin/models/transaction/__init__.py | 41 ------ .../models/{wallet/listModel.py => wallet.py} | 0 .../wallets/listModel.py => wallets.py} | 0 30 files changed, 303 insertions(+), 587 deletions(-) rename src/cutecoin/{models/account/__init__.py => core/account.py} (64%) rename src/cutecoin/core/{__init__.py => app.py} (90%) create mode 100644 src/cutecoin/core/community.py rename src/cutecoin/{models/person/__init__.py => core/person.py} (100%) rename src/cutecoin/{models/wallet/__init__.py => core/wallet.py} (85%) delete mode 100644 src/cutecoin/models/account/communities/__init__.py delete mode 100644 src/cutecoin/models/account/communities/itemModel.py delete mode 100644 src/cutecoin/models/account/wallets/__init__.py rename src/cutecoin/models/{account/communities/listModel.py => communities.py} (100%) rename src/cutecoin/models/{community/itemModel.py => community.py} (100%) delete mode 100644 src/cutecoin/models/community/__init__.py rename src/cutecoin/models/{community/membersListModel.py => members.py} (95%) delete mode 100644 src/cutecoin/models/node/__init__.py rename src/cutecoin/models/{node/itemModel.py => peer.py} (73%) rename src/cutecoin/models/{node/treeModel.py => peering.py} (64%) rename src/cutecoin/models/{transaction/receivedListModel.py => received.py} (100%) rename src/cutecoin/models/{transaction/sentListModel.py => sent.py} (100%) delete mode 100644 src/cutecoin/models/transaction/__init__.py rename src/cutecoin/models/{wallet/listModel.py => wallet.py} (100%) rename src/cutecoin/models/{account/wallets/listModel.py => wallets.py} (100%) diff --git a/lib/ucoinpy/documents/peer.py b/lib/ucoinpy/documents/peer.py index 1148785a..6733c538 100644 --- a/lib/ucoinpy/documents/peer.py +++ b/lib/ucoinpy/documents/peer.py @@ -6,6 +6,7 @@ Created on 2 déc. 2014 import re +from ..api.bma import ConnectionHandler from . import Document from .. import PROTOCOL_VERSION, MANAGED_API @@ -123,7 +124,7 @@ class UnknownEndpoint(Endpoint): class BMAEndpoint(Endpoint): - re_inline = re.compile('^BASIC_MERKLED_API(?: ([a-z_][a-z0-9-_.]+))?(?: ([0-9.]+))?(?: ([0-9a-f:]+))?(?: ([0-9]+))$') + re_inline = re.compile('^BASIC_MERKLED_API(?: ([a-z0-9-_.]*(?:.[a-zA-Z])))?(?: ((?:[0-9.]{1,4}){4}))?(?: ((?:[0-9a-f:]{4,5}){4,8}))?(?: ([0-9]+))$') @classmethod def from_inline(cls, inline): @@ -142,7 +143,15 @@ class BMAEndpoint(Endpoint): def inline(self): return "BASIC_MERKLED_API {DNS} {IPv4} {IPv6} {PORT}" \ - .format(DNS=self.server, - IPv4=self.ipv4, - IPv6=self.ipv6, - PORT=self.port) + .format(DNS=(self.server if self.server else ""), + IPv4=(self.ipv4 if self.ipv4 else ""), + IPv6=(self.ipv6 if self.ipv6 else ""), + PORT=(self.port if self.port else "")) + + def conn_handler(self): + if self.server: + return ConnectionHandler(self.server, self.port) + elif self.ipv4: + return ConnectionHandler(self.ipv4, self.port) + else: + return ConnectionHandler(self.ipv6, self.port) diff --git a/res/ui/communityConfigurationDialog.ui b/res/ui/communityConfigurationDialog.ui index c87bcab2..2ef8b8fa 100644 --- a/res/ui/communityConfigurationDialog.ui +++ b/res/ui/communityConfigurationDialog.ui @@ -101,7 +101,7 @@ </property> <layout class="QVBoxLayout" name="verticalLayout_3"> <item> - <widget class="QTreeView" name="tree_nodes"> + <widget class="QTreeView" name="tree_peers"> <property name="contextMenuPolicy"> <enum>Qt::CustomContextMenu</enum> </property> @@ -206,7 +206,7 @@ </hints> </connection> <connection> - <sender>tree_nodes</sender> + <sender>tree_peers</sender> <signal>customContextMenuRequested(QPoint)</signal> <receiver>CommunityConfigurationDialog</receiver> <slot>showContextMenu(QPoint)</slot> diff --git a/src/cutecoin/__init__.py b/src/cutecoin/__init__.py index be12c144..573fb389 100644 --- a/src/cutecoin/__init__.py +++ b/src/cutecoin/__init__.py @@ -6,13 +6,13 @@ Created on 1 févr. 2014 import sys from PyQt5.QtWidgets import QApplication, QDialog from cutecoin.gui.mainWindow import MainWindow -from cutecoin.core import Core +from cutecoin.core.app import Application if __name__ == '__main__': - app = QApplication(sys.argv) - core = Core(sys.argv) - window = MainWindow(core) + cutecoin = QApplication(sys.argv) + app = Application(sys.argv) + window = MainWindow(app) window.show() - sys.exit(app.exec_()) + sys.exit(cutecoin.exec_()) pass diff --git a/src/cutecoin/models/account/__init__.py b/src/cutecoin/core/account.py similarity index 64% rename from src/cutecoin/models/account/__init__.py rename to src/cutecoin/core/account.py index bb40ef3c..b2627b5f 100644 --- a/src/cutecoin/models/account/__init__.py +++ b/src/cutecoin/core/account.py @@ -5,15 +5,13 @@ Created on 1 févr. 2014 ''' from ucoinpy.api import bma +from ucoinpy.api.bma import ConnectionHandler +from ucoinpy.documents.peer import Peer from ucoinpy.key import SigningKey import logging -import json -import os -from cutecoin.models.account.wallets import Wallets -from cutecoin.models.account.communities import Communities -from cutecoin.models.community import Community -from cutecoin.models.transaction import Transaction -from cutecoin.models.person import Person +from .wallet import Wallet +from .community import Community +from .person import Person class Account(object): @@ -54,31 +52,54 @@ class Account(object): for contact_data in json_data['contacts']: contacts.append(Person.from_json(contact_data)) - wallets = Wallets.load(json_data['wallets']) - communities = Communities.load(json_data['communities']) + wallets = [] + for data in json_data['wallets']: + wallets.append(Wallet.load(data)) + + communities = [] + for data in json_data['communities']: + communities.append(Community.load(data)) account = cls(salt, pubkey, name, communities, wallets, contacts) return account def __eq__(self, other): if other is not None: - return other.keyid == self.keyid + return other.pubkey == self.pubkey else: return False def add_contact(self, person): self.contacts.append(person) - def add_community(self, default_node): + def add_community(self, server, port): logging.debug("Adding a community") - current = bma.blockchain.Current(default_node.connection_handler()) + current = bma.blockchain.Current(ConnectionHandler(server, port)) block_data = current.get() currency = block_data['currency'] logging.debug("Currency : {0}".format(currency)) - community = self.communities.add_community(currency, default_node) - self.wallets.add_wallet(self.wallets.nextid(), self.pubkey, currency) + + peering = bma.network.Peering(ConnectionHandler(server, port)) + peer_data = peering.get() + peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'], + peer_data['signature'])) + + community = Community.create(currency, peer) + self.communities.append(community) + + wallet = Wallet.create(self.next_walletid(), self.pubkey, + currency, "Default wallet") + self.wallets.append(wallet) + return community + def next_walletid(self): + wid = 0 + for w in self.wallets: + if w.walletid > wid: + wid = w.walletid + 1 + return wid + def sources(self): #TODO: Change the way things are displayed # Listing sources from all communities is stupid @@ -119,11 +140,23 @@ class Account(object): data.append(p.jsonify()) return data + def jsonify_wallets(self): + data = [] + for w in self.wallets: + data.append(w.jsonify()) + return data + + def jsonify_community(self): + data = [] + for c in self.communities: + data.append(c.jsonify()) + return data + def jsonify(self): data = {'name': self.name, 'salt': self.salt, 'pubkey': self.pubkey, - 'communities': self.communities.jsonify(), - 'wallets': self.wallets.jsonify(), + 'communities': self.jsonify_community(), + 'wallets': self.jsonify_wallets(), 'contacts': self.jsonify_contacts()} return data diff --git a/src/cutecoin/core/__init__.py b/src/cutecoin/core/app.py similarity index 90% rename from src/cutecoin/core/__init__.py rename to src/cutecoin/core/app.py index 1563ffb1..09b44625 100644 --- a/src/cutecoin/core/__init__.py +++ b/src/cutecoin/core/app.py @@ -12,12 +12,10 @@ import gnupg from cutecoin.core import config from cutecoin.tools.exceptions import NameAlreadyExists, BadAccountFile -from cutecoin.models.account import Account -from cutecoin.models.account.communities import Communities -from cutecoin.models.account.wallets import Wallets +from cutecoin.core.account import Account -class Core(object): +class Application(object): ''' Managing core application datas : @@ -49,8 +47,8 @@ class Core(object): logging.info("Creating account directory") os.makedirs(account_path) account = Account.create(name, - Communities.create(), - Wallets.create(), + [], + [], config.parameters) self.accounts.append(account) self.current_account = account @@ -94,7 +92,7 @@ class Core(object): with tarfile.open(file, "r") as tar: path = os.path.join(config.parameters['home'], name) - for obj in ["properties", "keyring", "secretkeyring"]: + for obj in ["properties"]: try: tar.getmember(obj) except KeyError: @@ -112,7 +110,7 @@ class Core(object): def export_account(self, file, account): with tarfile.open(file, "w") as tar: - for file in ["properties", "keyring", "secretkeyring"]: + for file in ["properties"]: path = os.path.join(config.parameters['home'], account.name, file) tar.add(path, file) diff --git a/src/cutecoin/core/community.py b/src/cutecoin/core/community.py new file mode 100644 index 00000000..03402876 --- /dev/null +++ b/src/cutecoin/core/community.py @@ -0,0 +1,124 @@ +''' +Created on 1 févr. 2014 + +@author: inso +''' + +from ucoinpy.api import bma +from ucoinpy import PROTOCOL_VERSION +from ucoinpy.documents.peer import Peer, Endpoint, BMAEndpoint +from ucoinpy.documents.block import Block +import logging + + +class Community(object): + ''' + classdocs + ''' + def __init__(self, currency, peers): + ''' + A community is a group of nodes using the same currency. + ''' + self.currency = currency + self.peers = peers + + @classmethod + def create(cls, currency, peer): + return cls(currency, [peer]) + + @classmethod + def load(cls, json_data): + peers = [] + + currency = json_data['currency'] + + for data in json_data['peers']: + endpoint_inline = next(e for e in data['endpoints'] + if Endpoint.from_inline(e) is not None) + endpoint = Endpoint.from_inline(endpoint_inline) + peering = bma.network.Peering(endpoint.conn_handler()) + peer_data = peering.get() + peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'], + peer_data['signature'])) + peers.append(peer) + + community = cls(currency, peers) + + return community + + def name(self): + return self.currency + + def __eq__(self, other): + return (other.currency == self.currency) + + def dividend(self): + return 100 + + def send_pubkey(self, account): + pass + + def send_membership(self, account, membership): + pass + + def peering(self): + peers = [] + peering_data = self.request(bma.network.peering.Peers) + logging.debug(peering_data) + for peer in peering_data: + logging.debug(peer) + #peers.append(Peer.from_signed_raw("{0}{1}\n".format(peer['value']['raw'], + # peer['value']['signature']))) + return peers + + def get_block(self, number=None): + if number is None: + data = self.request(bma.blockchain.Current) + else: + data = self.request(bma.blockchain.Block, + req_args={'number': number}) + + return Block.from_signed_raw("{0}{1}\n".format(data['raw'], + data['signature'])) + + def members_pubkeys(self): + ''' + Listing members pubkeys of a community + ''' + memberships = self.request(bma.wot.Members) + members = [] + logging.debug(memberships) + for m in memberships["results"]: + members.append(m['pubkey']) + return members + + def request(self, request, req_args={}, get_args={}): + logging.debug("Peers : {0}".format(self.peers)) + for peer in self.peers: + e = next(e for e in peer.endpoints if type(e) is BMAEndpoint) + logging.debug("Trying to connect to : " + peer.pubkey) + req = request(e.conn_handler(), **req_args) + data = req.get(**get_args) + return data + + def post(self, request, req_args={}, post_args={}): + for peer in self.peers: + e = next(e for e in peer.endpoints if type(e) is BMAEndpoint) + logging.debug("Trying to connect to : " + peer.pubkey) + req = request(e.conn_handler(), **req_args) + req.post(**post_args) + + def jsonify_peers_list(self): + data = [] + for peer in self.peers: + endpoints_data = [] + for e in peer.endpoints: + endpoints_data.append(e.inline()) + data.append({'endpoints': endpoints_data, + 'pubkey': peer.pubkey}) + return data + + def jsonify(self): + data = {'currency': self.currency, + 'peers': self.jsonify_peers_list()} + return data diff --git a/src/cutecoin/models/person/__init__.py b/src/cutecoin/core/person.py similarity index 100% rename from src/cutecoin/models/person/__init__.py rename to src/cutecoin/core/person.py diff --git a/src/cutecoin/models/wallet/__init__.py b/src/cutecoin/core/wallet.py similarity index 85% rename from src/cutecoin/models/wallet/__init__.py rename to src/cutecoin/core/wallet.py index ac2957a9..8d61ed0c 100644 --- a/src/cutecoin/models/wallet/__init__.py +++ b/src/cutecoin/core/wallet.py @@ -7,16 +7,6 @@ Created on 1 févr. 2014 from ucoinpy.api import bma from ucoinpy.documents.transaction import InputSource from ucoinpy.key import SigningKey -import logging -import gnupg -import json -import time -import hashlib -import importlib -from decimal import Decimal -from cutecoin.models.node import Node -from cutecoin.models.transaction import Transaction -from cutecoin.tools.exceptions import AlgorithmNotImplemented class Wallet(object): @@ -53,8 +43,8 @@ class Wallet(object): def relative_value(self, community): value = self.value(community) - block = community.get_block() - relative_value = value / float(block.ud) + ud = community.dividend() + relative_value = value / float(ud) return relative_value def value(self, community): diff --git a/src/cutecoin/gui/addContactDialog.py b/src/cutecoin/gui/addContactDialog.py index 1946e1dc..157ad339 100644 --- a/src/cutecoin/gui/addContactDialog.py +++ b/src/cutecoin/gui/addContactDialog.py @@ -7,7 +7,7 @@ import re from PyQt5.QtWidgets import QDialog, QDialogButtonBox -from cutecoin.models.person import Person +from cutecoin.core.person import Person from cutecoin.gen_resources.addContactDialog_uic import Ui_AddContactDialog @@ -22,7 +22,7 @@ class AddContactDialog(QDialog, Ui_AddContactDialog): ''' Constructor ''' - super(AddContactDialog, self).__init__() + super().__init__() self.setupUi(self) self.account = account self.main_window = parent diff --git a/src/cutecoin/gui/communityTabWidget.py b/src/cutecoin/gui/communityTabWidget.py index 905ceef4..de492dea 100644 --- a/src/cutecoin/gui/communityTabWidget.py +++ b/src/cutecoin/gui/communityTabWidget.py @@ -6,7 +6,7 @@ Created on 2 févr. 2014 import logging from PyQt5.QtWidgets import QWidget, QErrorMessage -from cutecoin.models.community.membersListModel import MembersListModel +from cutecoin.models.members import MembersListModel from cutecoin.gen_resources.communityTabWidget_uic import Ui_CommunityTabWidget @@ -20,7 +20,7 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): ''' Constructor ''' - super(CommunityTabWidget, self).__init__() + super().__init__() self.setupUi(self) self.community = community self.account = account diff --git a/src/cutecoin/gui/importAccountDialog.py b/src/cutecoin/gui/importAccountDialog.py index af4f6b60..6684adc0 100644 --- a/src/cutecoin/gui/importAccountDialog.py +++ b/src/cutecoin/gui/importAccountDialog.py @@ -16,20 +16,20 @@ class ImportAccountDialog(QDialog, Ui_ImportAccountDialog): classdocs ''' - def __init__(self, core, parent=None): + def __init__(self, app, parent=None): ''' Constructor ''' - super(ImportAccountDialog, self).__init__() + super().__init__() self.setupUi(self) - self.core = core + self.app = app self.main_window = parent self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) def accept(self): account_name = self.edit_name.text() try: - self.core.import_account(self.selected_file, account_name) + self.app.import_account(self.selected_file, account_name) except Error as e: QErrorMessage(self).showMessage(e.message) return @@ -56,7 +56,7 @@ class ImportAccountDialog(QDialog, Ui_ImportAccountDialog): self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.label_errors.setText("Please enter a name") return - for account in self.core.accounts: + for account in self.app.accounts: if name == account.name: self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.label_errors.setText("Name already exists") diff --git a/src/cutecoin/gui/mainWindow.py b/src/cutecoin/gui/mainWindow.py index ffef6314..bc27b203 100644 --- a/src/cutecoin/gui/mainWindow.py +++ b/src/cutecoin/gui/mainWindow.py @@ -11,9 +11,9 @@ from cutecoin.gui.transferMoneyDialog import TransferMoneyDialog from cutecoin.gui.communityTabWidget import CommunityTabWidget from cutecoin.gui.addContactDialog import AddContactDialog from cutecoin.gui.importAccountDialog import ImportAccountDialog -from cutecoin.models.account.wallets.listModel import WalletsListModel -from cutecoin.models.transaction.sentListModel import SentListModel -from cutecoin.models.transaction.receivedListModel import ReceivedListModel +from cutecoin.models.wallets import WalletsListModel +from cutecoin.models.sent import SentListModel +from cutecoin.models.received import ReceivedListModel import logging @@ -24,36 +24,36 @@ class MainWindow(QMainWindow, Ui_MainWindow): classdocs ''' - def __init__(self, core): + def __init__(self, app): ''' Constructor ''' # Set up the user interface from Designer. super(MainWindow, self).__init__() self.setupUi(self) - self.core = core + self.app = app self.refresh() def open_add_account_dialog(self): - dialog = ProcessConfigureAccount(self.core, None) + dialog = ProcessConfigureAccount(self.app, None) dialog.accepted.connect(self.refresh) dialog.exec_() def action_change_account(self, account_name): - self.core.current_account = self.core.get_account(account_name) - logging.info('Changing account to ' + self.core.current_account.name) + self.app.current_account = self.app.get_account(account_name) + logging.info('Changing account to ' + self.app.current_account.name) self.refresh() def open_transfer_money_dialog(self): - dialog = TransferMoneyDialog(self.core.current_account) + dialog = TransferMoneyDialog(self.app.current_account) dialog.accepted.connect(self.refresh_wallets) dialog.exec_() def open_add_contact_dialog(self): - AddContactDialog(self.core.current_account, self).exec_() + AddContactDialog(self.app.current_account, self).exec_() def open_configure_account_dialog(self): - dialog = ProcessConfigureAccount(self.core, self.core.current_account) + dialog = ProcessConfigureAccount(self.app, self.app.current_account) dialog.accepted.connect(self.refresh_wallets) dialog.exec_() @@ -67,14 +67,14 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.menu_change_account.clear() signal_mapper = QSignalMapper(self) - for account in self.core.accounts: + for account in self.app.accounts: action = QAction(account.name, self) self.menu_change_account.addAction(action) signal_mapper.setMapping(action, account.name) action.triggered.connect(signal_mapper.map) signal_mapper.mapped[str].connect(self.action_change_account) - if self.core.current_account is None: + if self.app.current_account is None: self.tabs_account.setEnabled(False) self.menu_contacts.setEnabled(False) self.menu_actions.setEnabled(False) @@ -84,30 +84,30 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.menu_actions.setEnabled(True) self.label_account_name.setText( "Current account : " + - self.core.current_account.name) + self.app.current_account.name) self.refresh_wallets() self.tabs_communities.clear() - for community in self.core.current_account.communities: + for community in self.app.current_account.communities: tab_community = CommunityTabWidget( - self.core.current_account, + self.app.current_account, community) self.tabs_communities.addTab(tab_community, community.name()) self.menu_contacts_list.clear() - for contact in self.core.current_account.contacts: + for contact in self.app.current_account.contacts: self.menu_contacts_list.addAction(contact.name) self.list_transactions_sent.setModel( SentListModel( - self.core.current_account)) + self.app.current_account)) self.list_transactions_received.setModel( ReceivedListModel( - self.core.current_account)) + self.app.current_account)) def refresh_wallets(self): - wallets_list_model = WalletsListModel(self.core.current_account) + wallets_list_model = WalletsListModel(self.app.current_account) self.list_wallets.setModel(wallets_list_model) self.refresh_wallet_content(QModelIndex()) @@ -115,7 +115,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): pass def import_account(self): - dialog = ImportAccountDialog(self.core, self) + dialog = ImportAccountDialog(self.app, self) dialog.accepted.connect(self.refresh) dialog.exec_() @@ -129,4 +129,4 @@ class MainWindow(QMainWindow, Ui_MainWindow): path = selected_file[0] else: path = selected_file[0] + ".acc" - self.core.export_account(path, self.core.current_account) + self.app.export_account(path, self.app.current_account) diff --git a/src/cutecoin/gui/processConfigureAccount.py b/src/cutecoin/gui/processConfigureAccount.py index 2ad208e4..c0fe26b1 100644 --- a/src/cutecoin/gui/processConfigureAccount.py +++ b/src/cutecoin/gui/processConfigureAccount.py @@ -4,12 +4,12 @@ Created on 6 mars 2014 @author: inso ''' import logging +from ucoinpy.documents.peer import Peer from ucoinpy.key import SigningKey from cutecoin.gen_resources.accountConfigurationDialog_uic import Ui_AccountConfigurationDialog from cutecoin.gui.processConfigureCommunity import ProcessConfigureCommunity -from cutecoin.models.account.communities.listModel import CommunitiesListModel +from cutecoin.models.communities import CommunitiesListModel from cutecoin.tools.exceptions import KeyAlreadyUsed, Error -from cutecoin.models.node import Node from PyQt5.QtWidgets import QDialog, QErrorMessage, QFileDialog, QMessageBox @@ -37,7 +37,7 @@ class StepPageInit(Step): def process_next(self): if self.config_dialog.account is None: name = self.config_dialog.edit_account_name.text() - self.config_dialog.account = self.config_dialog.core.create_account(name) + self.config_dialog.account = self.config_dialog.app.create_account(name) else: name = self.config_dialog.edit_account_name.text() self.config_dialog.account.name = name @@ -102,10 +102,8 @@ class StepPageCommunities(Step): logging.debug("Communities NEXT ") server = self.config_dialog.lineedit_server.text() port = self.config_dialog.spinbox_port.value() - default_node = Node.create(server, port) account = self.config_dialog.account - self.config_dialog.community = account.communities.add_community( - default_node) + self.config_dialog.community = account.add_community(server, port) account.wallets.add_wallet(0, self.config_dialog.community) self.config_dialog.refresh() @@ -123,7 +121,7 @@ class ProcessConfigureAccount(QDialog, Ui_AccountConfigurationDialog): classdocs ''' - def __init__(self, core, account): + def __init__(self, app, account): ''' Constructor ''' @@ -131,7 +129,7 @@ class ProcessConfigureAccount(QDialog, Ui_AccountConfigurationDialog): super(ProcessConfigureAccount, self).__init__() self.setupUi(self) self.account = account - self.core = core + self.app = app step_init = StepPageInit(self) step_key = StepPageKey(self) step_communities = StepPageCommunities(self) @@ -209,12 +207,12 @@ class ProcessConfigureAccount(QDialog, Ui_AccountConfigurationDialog): self.step.display_page() def accept(self): - if self.account not in self.core.accounts: + if self.account not in self.app.accounts: self.account.name = self.edit_account_name.text() try: - self.core.add_account(self.account) + self.app.add_account(self.account) except KeyAlreadyUsed as e: QErrorMessage(self).showMessage(e.message) - self.core.save(self.account) + self.app.save(self.account) self.accepted.emit() self.close() diff --git a/src/cutecoin/gui/processConfigureCommunity.py b/src/cutecoin/gui/processConfigureCommunity.py index 5c1f58d9..36990aac 100644 --- a/src/cutecoin/gui/processConfigureCommunity.py +++ b/src/cutecoin/gui/processConfigureCommunity.py @@ -6,12 +6,14 @@ Created on 8 mars 2014 import logging from ucoinpy.api import bma +from ucoinpy.api.bma import ConnectionHandler +from ucoinpy.documents.peer import Peer + from cutecoin.gen_resources.communityConfigurationDialog_uic import Ui_CommunityConfigurationDialog from PyQt5.QtWidgets import QDialog, QMenu, QMessageBox, QWidget, QAction from PyQt5.QtCore import QSignalMapper -from cutecoin.models.node.treeModel import NodesTreeModel -from cutecoin.models.node import Node -from cutecoin.models.person import Person +from cutecoin.models.peering import PeeringTreeModel +from cutecoin.core.person import Person from cutecoin.tools.exceptions import PersonNotFoundError from cutecoin.tools.exceptions import Error @@ -36,7 +38,8 @@ class StepPageInit(Step): port = self.config_dialog.spinbox_port.value() logging.debug("Is valid ? ") try: - bma.network.Peering(server, port) + peer_data = bma.network.Peering(ConnectionHandler(server, port)) + peer_data.get()['raw'] except: QMessageBox.critical(self, "Server error", "Cannot get node peering") @@ -49,18 +52,17 @@ class StepPageInit(Step): ''' server = self.config_dialog.lineedit_server.text() port = self.config_dialog.spinbox_port.value() - default_node = Node.create(server, port) account = self.config_dialog.account logging.debug("Account : {0}".format(account)) - self.config_dialog.community = account.add_community(default_node) + self.config_dialog.community = account.add_community(server, port) def display_page(self): self.config_dialog.button_previous.setEnabled(False) -class StepPageAddNodes(Step): +class StepPageAddpeers(Step): ''' - The step where the user add nodes + The step where the user add peers ''' def __init__(self, config_dialog): super().__init__(config_dialog) @@ -72,13 +74,11 @@ class StepPageAddNodes(Step): pass def display_page(self): - # We add already known nodes to the displayed list - for node in self.config_dialog.community.nodes: - if node not in self.config_dialog.nodes: - self.config_dialog.nodes.append(node) - tree_model = NodesTreeModel(self.config_dialog.nodes, - self.config_dialog.community.name()) - self.config_dialog.tree_nodes.setModel(tree_model) + # We add already known peers to the displayed list + for peer in self.config_dialog.community.peers: + self.config_dialog.peers.append(peer) + tree_model = PeeringTreeModel(self.config_dialog.community) + self.config_dialog.tree_peers.setModel(tree_model) self.config_dialog.button_previous.setEnabled(False) self.config_dialog.button_next.setText("Ok") @@ -97,20 +97,20 @@ class ProcessConfigureCommunity(QDialog, Ui_CommunityConfigurationDialog): self.community = community self.account = account self.step = None - self.nodes = [] + self.peers = [] self.wallet_edit = {} for w in self.account.wallets: self.wallet_edit[w.name] = False step_init = StepPageInit(self) - step_add_nodes = StepPageAddNodes(self) + step_add_peers = StepPageAddpeers(self) - step_init.next_step = step_add_nodes + step_init.next_step = step_add_peers if self.community is not None: self.stacked_pages.removeWidget(self.page_init) - self.step = step_add_nodes + self.step = step_add_peers self.setWindowTitle("Configure community " + self.community.currency) else: @@ -143,18 +143,17 @@ class ProcessConfigureCommunity(QDialog, Ui_CommunityConfigurationDialog): ''' server = self.lineedit_server.text() port = self.spinbox_port.value() - logging.debug("Add node : {0}".format(self.community)) if self.community is not None: - self.nodes.append(Node.create(server, port)) - self.tree_nodes.setModel(NodesTreeModel(self.community, - self.nodes)) + self.community.add_peer(server, port) + self.tree_peers.setModel(PeeringTreeModel(self.community, + self.peers)) def showContextMenu(self, point): if self.stacked_pages.currentIndex() == 1: menu = QMenu() action = menu.addAction("Delete", self.removeNode) if self.community is not None: - if len(self.nodes) == 1: + if len(self.peers) == 1: action.setEnabled(False) menu.exec_(self.mapToGlobal(point)) diff --git a/src/cutecoin/gui/transferMoneyDialog.py b/src/cutecoin/gui/transferMoneyDialog.py index 6e829ca6..7bc8eb56 100644 --- a/src/cutecoin/gui/transferMoneyDialog.py +++ b/src/cutecoin/gui/transferMoneyDialog.py @@ -6,8 +6,7 @@ Created on 2 févr. 2014 from PyQt5.QtWidgets import QDialog, QErrorMessage -from cutecoin.models.person import Person -from cutecoin.models.node import Node +from cutecoin.core.person import Person from cutecoin.gen_resources.transferDialog_uic import Ui_TransferMoneyDialog diff --git a/src/cutecoin/models/account/communities/__init__.py b/src/cutecoin/models/account/communities/__init__.py deleted file mode 100644 index d2c1fe2e..00000000 --- a/src/cutecoin/models/account/communities/__init__.py +++ /dev/null @@ -1,82 +0,0 @@ -''' -Created on 5 févr. 2014 - -@author: inso -''' -from cutecoin.models.community import Community -import logging - - -class Communities(object): - - ''' - The list of the communities an account is member of. - ''' - - def __init__(self, _communities_list): - ''' - Constructor - ''' - self._communities_list = _communities_list - - @classmethod - def create(cls): - return cls([]) - - @classmethod - def load(cls, json_data): - _communities_list = [] - for community_data in json_data: - _communities_list.append(Community.load(community_data)) - return cls(_communities_list) - - def __iter__(self): - return self._communities_list.__iter__() - - def __contains__(self, wallet): - return wallet in self._communities_list - - def __reverse__(self): - return self._communities_list.__reverse__() - - def __len__(self): - return len(self._communities_list) - - def __getitem__(self, key): - return self._communities_list[key] - - def add_community(self, currency, default_node): - ''' - Add a community with a mainNode - ''' - community = Community.create(currency, default_node) - if community not in self._communities_list: - self._communities_list.append(community) - return community - return None - - def request(self, request, get_args={}): - response = None - for community in self._communities_list: - try: - response = community.request(request, get_args) - except: - continue - return response - - def post(self, request, get_args={}): - for community in self._communities_list: - try: - response = community.post(request, get_args) - except: - continue - return response - - def jsonify(self): - ''' - Return the list of communities in a key:value form. - ''' - data = [] - for community in self._communities_list: - data.append(community.jsonify()) - return data diff --git a/src/cutecoin/models/account/communities/itemModel.py b/src/cutecoin/models/account/communities/itemModel.py deleted file mode 100644 index 18dfc872..00000000 --- a/src/cutecoin/models/account/communities/itemModel.py +++ /dev/null @@ -1,36 +0,0 @@ -''' -Created on 5 févr. 2014 - -@author: inso -''' - - -class CommunitiesItemModel(object): - - def __init__(self, account): - self.communities_text = account.key - self.community_items = [] - - def appendChild(self, community_item): - self.community_items.append(community_item) - - def child(self, row): - return self.communityItems[row] - - def childCount(self): - return len(self.community_items) - - def columnCount(self): - return 1 - - def data(self, column): - try: - return self.communities_text - except IndexError: - return None - - def parent(self): - return None - - def row(self): - return 0 diff --git a/src/cutecoin/models/account/wallets/__init__.py b/src/cutecoin/models/account/wallets/__init__.py deleted file mode 100644 index 23ccc5b6..00000000 --- a/src/cutecoin/models/account/wallets/__init__.py +++ /dev/null @@ -1,74 +0,0 @@ -''' -Created on 7 févr. 2014 - -@author: inso -''' - -import logging -from cutecoin.models.wallet import Wallet - - -class Wallets(object): - - ''' - The list of the wallets owned by an account. - ''' - - def __init__(self, wallets_list): - ''' - Constructor - ''' - self._wallets_list = wallets_list - - @classmethod - def create(cls): - return cls([]) - - @classmethod - def load(cls, json_data): - wallets_list = [] - for wallet_data in json_data: - wallets_list.append(Wallet.load(wallet_data)) - return cls(wallets_list) - - def __iter__(self): - return self._wallets_list.__iter__() - - def __contains__(self, wallet): - return wallet in self._wallets_list - - def __reverse__(self): - return self._wallets_list.__reverse__() - - def __len__(self): - return len(self._wallets_list) - - def __getitem__(self, key): - return self._wallets_list[key] - - def add_wallet(self, walletid, pubkey, currency, name="Main Wallet"): - ''' - Create a new wallet of a specific currency. - ''' - wallet = Wallet.create(walletid, pubkey, currency, name) - if wallet not in self._wallets_list: - self._wallets_list.append(wallet) - return wallet - else: - return self._wallets_list.get(wallet) - - def nextid(self): - walletid = 0 - for w in self._wallets_list: - if w.id >= id: - walletid = w.id + 1 - return walletid - - def jsonify(self): - ''' - Return the list of wallets in a key:value form. - ''' - data = [] - for wallet in self._wallets_list: - data.append(wallet.jsonify()) - return data diff --git a/src/cutecoin/models/account/communities/listModel.py b/src/cutecoin/models/communities.py similarity index 100% rename from src/cutecoin/models/account/communities/listModel.py rename to src/cutecoin/models/communities.py diff --git a/src/cutecoin/models/community/itemModel.py b/src/cutecoin/models/community.py similarity index 100% rename from src/cutecoin/models/community/itemModel.py rename to src/cutecoin/models/community.py diff --git a/src/cutecoin/models/community/__init__.py b/src/cutecoin/models/community/__init__.py deleted file mode 100644 index cf0936a8..00000000 --- a/src/cutecoin/models/community/__init__.py +++ /dev/null @@ -1,129 +0,0 @@ -''' -Created on 1 févr. 2014 - -@author: inso -''' - -from ucoinpy.api import bma -from ucoinpy.documents.block import Block -import hashlib -import json -import logging -import time -from cutecoin.models.node import Node -from cutecoin.models.account.wallets import Wallets - - -class Community(object): - ''' - classdocs - ''' - def __init__(self, currency, nodes): - ''' - A community is a group of nodes using the same currency. - ''' - self.currency = currency - self.nodes = nodes - - @classmethod - def create(cls, currency, default_node): - return cls(currency, [default_node]) - - @classmethod - def load(cls, json_data): - nodes = [] - - for node_data in json_data['nodes']: - nodes.append(Node.load(node_data)) - - currency = json_data['currency'] - - community = cls(currency, nodes) - return community - - def name(self): - return self.currency - - def __eq__(self, other): - return (other.currency == self.currency) - - def dividend(self): - current_amendment = self.request(bma.blockchain.Current()) - return int(current_amendment['du']) - - def send_pubkey(self, account): - pass - - def send_membership(self, account, membership): - pass - - def get_block(self, number=None): - if number is None: - data = self.request(bma.blockchain.Current) - else: - data = self.request(bma.blockchain.Block, req_args={'number': number}) - return Block.from_signed_raw("{0}{1}\n".format(data['raw'], data['signature'])) - - def members_pubkeys(self): - ''' - Listing members pubkeys of a community - ''' - memberships = self.request(bma.wot.Members) - members = [] - logging.debug(memberships) - for m in memberships["results"]: - members.append(m['pubkey']) - return members - - def request(self, request, req_args={}, get_args={}): - error = None - logging.debug("Nodes : {0}".format(self.nodes)) - for node in self.nodes: - logging.debug("Trying to connect to : " + node.get_text()) - req = request(node.connection_handler(), **req_args) - try: - data = req.get(**get_args) - return data - except ValueError as e: - error = str(e) - logging.debug("Error : {0}".format(error)) - - logging.debug("Leaving on error...") - return error - - def post(self, request, req_args={}, post_args={}): - error = None - for node in self.nodes: - logging.debug("Trying to connect to : " + node.get_text()) - req = request(node.connection_handler(), **req_args) - try: - req.post(**post_args) - except ValueError as e: - error = str(e) - except: - continue - return error - - def broadcast(self, nodes, request, req_args={}, post_args={}): - error = None - for node in nodes: - logging.debug("Trying to connect to : " + node.get_text()) - req = request(node.connection_handler(), **req_args) - try: - req.post(**post_args) - except ValueError as e: - error = str(e) - except: - continue - return error - - def jsonify_nodes_list(self): - data = [] - for node in self.nodes: - data.append(node.jsonify()) - return data - - def jsonify(self): - data = {'currency': self.currency, - 'nodes': self.jsonify_nodes_list()} - return data diff --git a/src/cutecoin/models/community/membersListModel.py b/src/cutecoin/models/members.py similarity index 95% rename from src/cutecoin/models/community/membersListModel.py rename to src/cutecoin/models/members.py index 6c1e80bf..11e9cd66 100644 --- a/src/cutecoin/models/community/membersListModel.py +++ b/src/cutecoin/models/members.py @@ -4,7 +4,7 @@ Created on 5 févr. 2014 @author: inso ''' -from cutecoin.models.person import Person +from cutecoin.core.person import Person from PyQt5.QtCore import QAbstractListModel, Qt diff --git a/src/cutecoin/models/node/__init__.py b/src/cutecoin/models/node/__init__.py deleted file mode 100644 index c1794258..00000000 --- a/src/cutecoin/models/node/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -''' -Created on 1 févr. 2014 - -@author: inso -''' - -import logging -from ucoinpy.api import bma -from ucoinpy.documents.peer import Endpoint, BMAEndpoint, UnknownEndpoint -import re - - -class Node(object): - - ''' - A ucoin node using BMA protocol - ''' - - def __init__(self, server, port): - ''' - Constructor - ''' - self.server = server - self.port = port - - @classmethod - def create(cls, server, port): - return cls(server, port) - - @classmethod - def load(cls, json_data): - server = json_data['server'] - port = json_data['port'] - return cls(server, port) - - @classmethod - def from_endpoint(cls, endpoint_data): - endpoint = Endpoint.from_inline(endpoint_data) - if type(endpoint) is not UnknownEndpoint: - if type(endpoint) is BMAEndpoint: - if endpoint.server: - return cls(Node(endpoint.server, endpoint.port)) - else: - return cls(Node(endpoint.ipv4, endpoint.port)) - return None - - def __eq__(self, other): - pubkey = bma.network.Peering(server=self.server, - port=self.port).get()['pubkey'] - other_pubkey = bma.network.Peering(server=other.server, - port=other.port).get()['pubkey'] - return (pubkey == other_pubkey) - - def get_text(self): - return self.server + ":" + str(self.port) - - def peering(self): - request = bma.network.Peering(self.connection_handler()) - return request.get() - - def peers(self): - request = bma.network.peering.Peers(self.connection_handler()) - peer_nodes = [] - for peer in request.get(): - logging.debug(peer) - return peer_nodes - - def connection_handler(self): - if self.server is not None: - return bma.ConnectionHandler(self.server, self.port) - else: - return bma.ConnectionHandler(self.ipv4, self.port) - - def jsonify(self): - return {'server': self.server, - 'port': self.port} diff --git a/src/cutecoin/models/node/itemModel.py b/src/cutecoin/models/peer.py similarity index 73% rename from src/cutecoin/models/node/itemModel.py rename to src/cutecoin/models/peer.py index 12ee5b31..7cca2856 100644 --- a/src/cutecoin/models/node/itemModel.py +++ b/src/cutecoin/models/peer.py @@ -38,28 +38,28 @@ class RootItem(object): return 0 -class NodeItem(object): +class PeerItem(object): - def __init__(self, main_node, root_item): - self.main_node_text = main_node.get_text() + def __init__(self, main_peer, root_item): + self.main_peer_text = main_peer.pubkey self.root_item = root_item - self.node_items = [] + self.peer_items = [] def appendChild(self, node_item): - self.node_items.append(node_item) + self.peer_items.append(node_item) def child(self, row): - return self.node_items[row] + return self.peer_items[row] def childCount(self): - return len(self.node_items) + return len(self.peer_items) def columnCount(self): return 1 def data(self, column): try: - return self.main_node_text + return self.main_peer_text except IndexError: return None @@ -68,5 +68,5 @@ class NodeItem(object): def row(self): if self.root_item: - return self.root_item.main_node_items.index(self) + return self.root_item.main_peer_items.index(self) return 0 diff --git a/src/cutecoin/models/node/treeModel.py b/src/cutecoin/models/peering.py similarity index 64% rename from src/cutecoin/models/node/treeModel.py rename to src/cutecoin/models/peering.py index 78d88f3e..758f77ea 100644 --- a/src/cutecoin/models/node/treeModel.py +++ b/src/cutecoin/models/peering.py @@ -4,25 +4,27 @@ Created on 5 févr. 2014 @author: inso ''' +from ucoinpy.api import bma +from ucoinpy.documents.peer import BMAEndpoint from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt -from cutecoin.models.node.itemModel import NodeItem, RootItem +from .peer import PeerItem, RootItem import logging -class NodesTreeModel(QAbstractItemModel): +class PeeringTreeModel(QAbstractItemModel): ''' A Qt abstract item model to display nodes of a community ''' - def __init__(self, nodes, community_name): + def __init__(self, community): ''' Constructor ''' - super(NodesTreeModel, self).__init__(None) - self.nodes = nodes - self.root_item = RootItem(community_name) - self.refresh_tree_nodes() + super().__init__(None) + self.peers = community.peering() + self.root_item = RootItem(community.currency) + self.refresh_tree() def columnCount(self, parent): return 1 @@ -46,7 +48,8 @@ class NodesTreeModel(QAbstractItemModel): return Qt.ItemIsEnabled | Qt.ItemIsSelectable def headerData(self, section, orientation, role): - if orientation == Qt.Horizontal and role == Qt.DisplayRole and section == 0: + if orientation == Qt.Horizontal \ + and role == Qt.DisplayRole and section == 0: return self.root_item.data(0) + " nodes" return None @@ -92,21 +95,22 @@ class NodesTreeModel(QAbstractItemModel): if index.column() == 0: return True - def refresh_tree_nodes(self): + def refresh_tree(self): logging.debug("root : " + self.root_item.data(0)) - for node in self.nodes: - node_item = NodeItem(node, self.root_item) + for peer in self.peers: + peer_item = PeerItem(peer, self.root_item) logging.debug( - "mainNode : " + - node.get_text() + + "main peer : " + + peer.get_text() + " / " + - node_item.data(0)) - self.root_item.appendChild(node_item) - for node in node.peers(): - child_node_item = NodeItem(node, node_item) - logging.debug( - "\t node : " + - node.get_text() + - " / " + - child_node_item.data(0)) - node_item.appendChild(child_node_item) + peer_item.data(0)) + self.root_item.appendChild(peer_item) + try: + e = next((e for e in peer.endpoints if type(e) is BMAEndpoint)) + for peer in bma.network.peering.Peers(e.conn_handler()): + child_node_item = PeerItem(peer, peer_item) + logging.debug("\t peer : " + peer.pubkey + " / " + + child_node_item.data(0)) + peer_item.appendChild(child_node_item) + except e as StopIteration: + continue diff --git a/src/cutecoin/models/transaction/receivedListModel.py b/src/cutecoin/models/received.py similarity index 100% rename from src/cutecoin/models/transaction/receivedListModel.py rename to src/cutecoin/models/received.py diff --git a/src/cutecoin/models/transaction/sentListModel.py b/src/cutecoin/models/sent.py similarity index 100% rename from src/cutecoin/models/transaction/sentListModel.py rename to src/cutecoin/models/sent.py diff --git a/src/cutecoin/models/transaction/__init__.py b/src/cutecoin/models/transaction/__init__.py deleted file mode 100644 index a092cf2b..00000000 --- a/src/cutecoin/models/transaction/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -''' -Created on 1 févr. 2014 - -@author: inso -''' - -from ucoinpy.api import bma -from ucoinpy.documents.transaction import InputSource - -from cutecoin.models.person import Person - - -class Transaction(object): - - ''' - A transaction which can be a transfer or an issuance. - At the moment the difference is not made - ''' - - def __init__(self, sender, tx_number, wallet, recipient): - self.tx_number = tx_number - self.wallet = wallet - self.sender = sender - self.recipient = recipient - - @classmethod - def create(cls, pubkey, tx_number, wallet): - return None - - def value(self): - value = 0 - return value - - def currency(self): - return "" - - def get_receiver_text(self): - return str(self.value()) + " from " + self.sender.name - - def get_sender_text(self): - return str(self.value()) + " to " + self.recipient.name diff --git a/src/cutecoin/models/wallet/listModel.py b/src/cutecoin/models/wallet.py similarity index 100% rename from src/cutecoin/models/wallet/listModel.py rename to src/cutecoin/models/wallet.py diff --git a/src/cutecoin/models/account/wallets/listModel.py b/src/cutecoin/models/wallets.py similarity index 100% rename from src/cutecoin/models/account/wallets/listModel.py rename to src/cutecoin/models/wallets.py -- GitLab