From 74a7ec25a707c11415a3b6b5e99956cbec8b236d Mon Sep 17 00:00:00 2001
From: Inso <insomniak.fr@gmail.com>
Date: Wed, 13 May 2015 09:06:39 +0200
Subject: [PATCH] Initialized QNetworkManager API

---
 src/cutecoin/core/net/api/__init__.py         |   0
 src/cutecoin/core/net/api/bma/__init__.py     | 121 ++++++++++++++
 .../core/net/api/bma/blockchain/__init__.py   | 158 ++++++++++++++++++
 .../core/net/api/bma/network/__init__.py      |  35 ++++
 .../net/api/bma/network/peering/__init__.py   |  51 ++++++
 src/cutecoin/core/net/api/bma/tx/__init__.py  |  46 +++++
 src/cutecoin/core/net/api/bma/wot/__init__.py |  89 ++++++++++
 7 files changed, 500 insertions(+)
 create mode 100644 src/cutecoin/core/net/api/__init__.py
 create mode 100644 src/cutecoin/core/net/api/bma/__init__.py
 create mode 100644 src/cutecoin/core/net/api/bma/blockchain/__init__.py
 create mode 100644 src/cutecoin/core/net/api/bma/network/__init__.py
 create mode 100644 src/cutecoin/core/net/api/bma/network/peering/__init__.py
 create mode 100644 src/cutecoin/core/net/api/bma/tx/__init__.py
 create mode 100644 src/cutecoin/core/net/api/bma/wot/__init__.py

diff --git a/src/cutecoin/core/net/api/__init__.py b/src/cutecoin/core/net/api/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/cutecoin/core/net/api/bma/__init__.py b/src/cutecoin/core/net/api/bma/__init__.py
new file mode 100644
index 00000000..ec216c55
--- /dev/null
+++ b/src/cutecoin/core/net/api/bma/__init__.py
@@ -0,0 +1,121 @@
+__all__ = ['api']
+
+from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest
+from PyQt5.QtCore import QUrl, QUrlQuery
+import logging, json
+# import pylibscrypt
+
+logger = logging.getLogger("ucoin")
+
+
+class ConnectionHandler(object):
+    """Helper class used by other API classes to ease passing server connection information."""
+
+    def __init__(self, server, port):
+        """
+        Arguments:
+        - `server`: server hostname
+        - `port`: port number
+        """
+
+        self.server = server
+        self.port = port
+
+    def __str__(self):
+        return 'connection info: %s:%d' % (self.server, self.port)
+
+
+class API(object):
+    """APIRequest is a class used as an interface. The intermediate derivated classes are the modules and the leaf classes are the API requests."""
+
+    def __init__(self, network_manager, connection_handler, module):
+        """
+        Asks a module in order to create the url used then by derivated classes.
+
+        Arguments:
+        - `module`: module name
+        - `connection_handler`: connection handler
+        """
+
+        self.module = module
+        self.network_manager = network_manager
+        self.connection_handler = connection_handler
+        self.headers = {}
+
+    def reverse_url(self, path):
+        """
+        Reverses the url using self.url and path given in parameter.
+
+        Arguments:
+        - `path`: the request path
+        """
+
+        server, port = self.connection_handler.server, self.connection_handler.port
+
+        url = 'http://%s:%d/%s' % (server, port, self.module)
+        return url + path
+
+    def get(self, **kwargs):
+        """wrapper of overloaded __get__ method."""
+
+        return self.__get__(**kwargs)
+
+    def post(self, **kwargs):
+        """wrapper of overloaded __post__ method."""
+
+        logger.debug('do some work with')
+
+        data = self.__post__(**kwargs)
+
+        logger.debug('and send back')
+
+        return data
+
+    def __get__(self, **kwargs):
+        """interface purpose for GET request"""
+
+        pass
+
+    def __post__(self, **kwargs):
+        """interface purpose for POST request"""
+
+        pass
+
+    def requests_get(self, path, **kwargs):
+        """
+        Requests GET wrapper in order to use API parameters.
+
+        Arguments:
+        - `path`: the request path
+        """
+
+        request = QNetworkRequest(self.reverse_url(path))
+        reply = request.get(self.reverse_url(path), params=kwargs,
+                                headers=self.headers, timeout=15)
+
+        return reply
+
+    def requests_post(self, path, **kwargs):
+        """
+        Requests POST wrapper in order to use API parameters.
+
+        Arguments:
+        - `path`: the request path
+        """
+        if 'self_' in kwargs:
+            kwargs['self'] = kwargs.pop('self_')
+
+        logging.debug("POST : {0}".format(kwargs))
+        post_data = QUrlQuery()
+        for k,v in kwargs.items():
+            post_data.addQueryItem(k, v);
+
+        request = QNetworkRequest(self.reverse_url(path))
+        request.setHeader(QNetworkRequest.ContentTypeHeader,
+            "application/x-www-form-urlencoded");
+        reply = request.post(self.reverse_url(path),
+                             post_data.toString(QUrl.FullyEncoded).toUtf8())
+
+        return reply
+
+from . import network, blockchain, tx, wot
diff --git a/src/cutecoin/core/net/api/bma/blockchain/__init__.py b/src/cutecoin/core/net/api/bma/blockchain/__init__.py
new file mode 100644
index 00000000..1766de67
--- /dev/null
+++ b/src/cutecoin/core/net/api/bma/blockchain/__init__.py
@@ -0,0 +1,158 @@
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors:
+# Caner Candan <caner@candan.fr>, http://caner.candan.fr
+#
+
+from .. import API, logging
+
+logger = logging.getLogger("ucoin/blockchain")
+
+
+class Blockchain(API):
+    def __init__(self, connection_handler, module='blockchain'):
+        super(Blockchain, self).__init__(connection_handler, module)
+
+
+class Parameters(Blockchain):
+    """GET the blockchain parameters used by this node."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/parameters', **kwargs)
+
+
+class Membership(Blockchain):
+    """GET/POST a Membership document."""
+    def __init__(self, connection_handler, search=None):
+        super().__init__(connection_handler)
+        self.search = search
+
+    def __post__(self, **kwargs):
+        assert 'membership' in kwargs
+
+        return self.requests_post('/membership', **kwargs)
+
+    def __get__(self, **kwargs):
+        assert self.search is not None
+        return self.requests_get('/memberships/%s' % self.search, **kwargs)
+
+
+class Block(Blockchain):
+    """GET/POST a block from/to the blockchain."""
+
+    def __init__(self, connection_handler, number=None):
+        """
+        Use the number parameter in order to select a block number.
+
+        Arguments:
+        - `number`: block number to select
+        """
+
+        super(Block, self).__init__(connection_handler)
+
+        self.number = number
+
+    def __get__(self, **kwargs):
+        assert self.number is not None
+        return self.requests_get('/block/%d' % self.number, **kwargs)
+
+    def __post__(self, **kwargs):
+        assert 'block' in kwargs
+        assert 'signature' in kwargs
+
+        return self.requests_post('/block', **kwargs)
+
+
+class Current(Blockchain):
+    """GET, same as block/[number], but return last accepted block."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/current', **kwargs)
+
+
+class Hardship(Blockchain):
+    """GET hardship level for given member's fingerprint for writing next block."""
+
+    def __init__(self, connection_handler, fingerprint):
+        """
+        Use the number parameter in order to select a block number.
+
+        Arguments:
+        - `fingerprint`: member fingerprint
+        """
+
+        super(Hardship, self).__init__(connection_handler)
+
+        self.fingerprint = fingerprint
+
+    def __get__(self, **kwargs):
+        assert self.fingerprint is not None
+        return self.requests_get('/hardship/%s' % self.fingerprint.upper(), **kwargs)
+
+
+class Newcomers(Blockchain):
+    """GET, return block numbers containing newcomers."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/newcomers', **kwargs)
+
+
+class Certifications(Blockchain):
+    """GET, return block numbers containing certifications."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/certs', **kwargs)
+
+
+class Joiners(Blockchain):
+    """GET, return block numbers containing joiners."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/joiners', **kwargs)
+
+
+class Actives(Blockchain):
+    """GET, return block numbers containing actives."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/actives', **kwargs)
+
+
+class Leavers(Blockchain):
+    """GET, return block numbers containing leavers."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/leavers', **kwargs)
+
+
+class Excluded(Blockchain):
+    """GET, return block numbers containing excluded."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/excluded', **kwargs)
+
+
+class UD(Blockchain):
+    """GET, return block numbers containing universal dividend."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/ud', **kwargs)
+
+
+class TX(Blockchain):
+    """GET, return block numbers containing transactions."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/with/tx', **kwargs)
diff --git a/src/cutecoin/core/net/api/bma/network/__init__.py b/src/cutecoin/core/net/api/bma/network/__init__.py
new file mode 100644
index 00000000..21d2735e
--- /dev/null
+++ b/src/cutecoin/core/net/api/bma/network/__init__.py
@@ -0,0 +1,35 @@
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors:
+# Caner Candan <caner@candan.fr>, http://caner.candan.fr
+#
+
+from .. import API, logging
+
+logger = logging.getLogger("ucoin/network")
+
+
+class Network(API):
+    def __init__(self, connection_handler, module='network'):
+        super(Network, self).__init__(connection_handler, module)
+
+
+class Peering(Network):
+    """GET peering information about a peer."""
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/peering', **kwargs)
+
+from . import peering
diff --git a/src/cutecoin/core/net/api/bma/network/peering/__init__.py b/src/cutecoin/core/net/api/bma/network/peering/__init__.py
new file mode 100644
index 00000000..b31c63b3
--- /dev/null
+++ b/src/cutecoin/core/net/api/bma/network/peering/__init__.py
@@ -0,0 +1,51 @@
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors:
+# Caner Candan <caner@candan.fr>, http://caner.candan.fr
+#
+
+from .. import Network, logging
+
+logger = logging.getLogger("ucoin/network/peering")
+
+
+class Base(Network):
+    def __init__(self, connection_handler):
+        super(Base, self).__init__(connection_handler, 'network/peering')
+
+
+class Peers(Base):
+    """GET peering entries of every node inside the currency network."""
+
+    def __get__(self, **kwargs):
+        """creates a generator with one peering entry per iteration."""
+
+        return self.requests_get('/peers')
+
+    def __post__(self, **kwargs):
+        assert 'entry' in kwargs
+        assert 'signature' in kwargs
+
+        return self.requests_post('/peers', **kwargs)
+
+
+class Status(Base):
+    """POST a network status document to this node in order notify of its status."""
+
+    def __post__(self, **kwargs):
+        assert 'status' in kwargs
+        assert 'signature' in kwargs
+
+        return self.requests_post('/status', **kwargs)
diff --git a/src/cutecoin/core/net/api/bma/tx/__init__.py b/src/cutecoin/core/net/api/bma/tx/__init__.py
new file mode 100644
index 00000000..6c670fa6
--- /dev/null
+++ b/src/cutecoin/core/net/api/bma/tx/__init__.py
@@ -0,0 +1,46 @@
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors:
+# Caner Candan <caner@candan.fr>, http://caner.candan.fr
+#
+
+from .. import API, logging
+
+logger = logging.getLogger("ucoin/tx")
+
+
+class Tx(API):
+    def __init__(self, connection_handler, module='tx'):
+        super(Tx, self).__init__(connection_handler, module)
+
+
+class Process(Tx):
+    """POST a transaction."""
+
+    def __post__(self, **kwargs):
+        assert 'transaction' in kwargs
+
+        return self.requests_post('/process', **kwargs)
+
+
+class Sources(Tx):
+    """Get transaction sources."""
+    def __init__(self, connection_handler, pubkey, module='tx'):
+        super(Tx, self).__init__(connection_handler, module)
+        self.pubkey = pubkey
+
+    def __get__(self, **kwargs):
+        assert self.pubkey is not None
+        return self.requests_get('/sources/%s' % self.pubkey, **kwargs)
diff --git a/src/cutecoin/core/net/api/bma/wot/__init__.py b/src/cutecoin/core/net/api/bma/wot/__init__.py
new file mode 100644
index 00000000..2da4a525
--- /dev/null
+++ b/src/cutecoin/core/net/api/bma/wot/__init__.py
@@ -0,0 +1,89 @@
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Authors:
+# Caner Candan <caner@candan.fr>, http://caner.candan.fr
+#
+
+from .. import API, logging
+
+logger = logging.getLogger("ucoin/wot")
+
+
+class WOT(API):
+    def __init__(self, connection_handler, module='wot'):
+        super(WOT, self).__init__(connection_handler, module)
+
+
+class Add(WOT):
+    """POST Public key data."""
+
+    def __post__(self, **kwargs):
+        assert 'pubkey' in kwargs
+        assert 'self_' in kwargs
+        assert 'other' in kwargs
+
+        return self.requests_post('/add', **kwargs)
+
+
+class Lookup(WOT):
+    """GET Public key data."""
+
+    def __init__(self, connection_handler, search, module='wot'):
+        super(WOT, self).__init__(connection_handler, module)
+
+        self.search = search
+
+    def __get__(self, **kwargs):
+        assert self.search is not None
+
+        return self.requests_get('/lookup/%s' % self.search, **kwargs)
+
+
+class CertifiersOf(WOT):
+    """GET Certification data over a member."""
+
+    def __init__(self, connection_handler, search, module='wot'):
+        super(WOT, self).__init__(connection_handler, module)
+
+        self.search = search
+
+    def __get__(self, **kwargs):
+        assert self.search is not None
+
+        return self.requests_get('/certifiers-of/%s' % self.search, **kwargs)
+
+
+class CertifiedBy(WOT):
+    """GET Certification data from a member."""
+
+    def __init__(self, connection_handler, search, module='wot'):
+        super(WOT, self).__init__(connection_handler, module)
+
+        self.search = search
+
+    def __get__(self, **kwargs):
+        assert self.search is not None
+
+        return self.requests_get('/certified-by/%s' % self.search, **kwargs)
+
+
+class Members(WOT):
+    """GET List all current members of the Web of Trust."""
+
+    def __init__(self, connection_handler, module='wot'):
+        super(WOT, self).__init__(connection_handler, module)
+
+    def __get__(self, **kwargs):
+        return self.requests_get('/members', **kwargs)
-- 
GitLab