diff --git a/beem/__init__.py b/beem/__init__.py index 1d40fed9ea0f47aea0b206ab6641a0f8a96c9ebd..dbb6c9324acba921b68f2f9b41cb219fe255632e 100644 --- a/beem/__init__.py +++ b/beem/__init__.py @@ -1,3 +1,4 @@ +""" beem.""" from .steem import Steem from .version import version as __version__ __all__ = [ diff --git a/beem/discussions.py b/beem/discussions.py index 9a7a0de82ab1d66f84dff249b268284cb63f4e42..a5af234ae8f03ad66872993d0facc28b7b726218 100644 --- a/beem/discussions.py +++ b/beem/discussions.py @@ -12,10 +12,31 @@ log = logging.getLogger(__name__) class Query(dict): - def __init__(self, limit=0, tag="", truncate_body=0): + """ + :param int limit + :param str tag + :param int truncate_body + :param array filter_tags + :param array select_authors + :param array select_tags + :param str start_author + :param str start_permlink + :param str parent_author + :param str parent_permlink + """ + def __init__(self, limit=0, tag="", truncate_body=0, + filter_tags=[""], select_authors=[""], select_tags=[""], + start_author=None, start_permlink=None, parent_author=None, parent_permlink=None): self["limit"] = limit self["truncate_body"] = truncate_body self["tag"] = tag + self["filter_tags"] = filter_tags + self["select_authors"] = select_authors + self["select_tags"] = select_tags + self["start_author"] = start_author + self["start_permlink"] = start_permlink + self["parent_author"] = parent_author + self["parent_permlink"] = parent_permlink class Discussions_by_trending(list): @@ -104,8 +125,9 @@ class Discussions_by_active(list): class Discussions_by_cashout(list): - """ get_discussions_by_cashout - + """ get_discussions_by_cashout. This query seems to be broken at the moment. + The output is always empty. + :param str discussion_query :param steem steem_instance: Steem() instance to use when accesing a RPC """ @@ -196,10 +218,16 @@ class Discussions_by_feed(list): """ def __init__(self, discussion_query, steem_instance=None): self.steem = steem_instance or shared_steem_instance() - posts = self.steem.rpc.get_discussions_by_feed(discussion_query) + + self.steem.register_apis(["follow"]) + limit = discussion_query["limit"] + account = discussion_query["tag"] + entryId = 0 + posts = self.steem.rpc.get_feed(account, entryId, limit, api='follow') + # posts = self.steem.rpc.get_discussions_by_feed(discussion_query, api='follow') super(Discussions_by_feed, self).__init__( [ - Comment(x) + Comment(x["comment"]) for x in posts ] ) @@ -213,10 +241,15 @@ class Discussions_by_blog(list): """ def __init__(self, discussion_query, steem_instance=None): self.steem = steem_instance or shared_steem_instance() - posts = self.steem.rpc.get_discussions_by_blog(discussion_query) + self.steem.register_apis(["follow"]) + limit = discussion_query["limit"] + account = discussion_query["tag"] + entryId = 0 + posts = self.steem.rpc.get_feed(account, entryId, limit, api='follow') + # posts = self.steem.rpc.get_discussions_by_blog(discussion_query) super(Discussions_by_blog, self).__init__( [ - Comment(x) + Comment(x["comment"]) for x in posts ] ) diff --git a/beem/price.py b/beem/price.py index 0e8b951293f6feaa67b11815ed5dd74574981eac..f365e5ac3291a5a139e9a243993532882078cf5e 100644 --- a/beem/price.py +++ b/beem/price.py @@ -223,6 +223,12 @@ class Price(dict): def __float__(self): return self["price"] + def _check_other(self, other): + if not other["base"]["symbol"] == self["base"]["symbol"]: + raise AssertionError() + if not other["quote"]["symbol"] == self["quote"]["symbol"]: + raise AssertionError() + def __mul__(self, other): a = self.copy() if isinstance(other, Price): @@ -323,60 +329,42 @@ class Price(dict): def __lt__(self, other): if isinstance(other, Price): - if not other["base"]["symbol"] == self["base"]["symbol"]: - raise AssertionError() - if not other["quote"]["symbol"] == self["quote"]["symbol"]: - raise AssertionError() + self._check_other(other) return self["price"] < other["price"] else: return self["price"] < float(other or 0) def __le__(self, other): if isinstance(other, Price): - if not other["base"]["symbol"] == self["base"]["symbol"]: - raise AssertionError() - if not other["quote"]["symbol"] == self["quote"]["symbol"]: - raise AssertionError() + self._check_other(other) return self["price"] <= other["price"] else: return self["price"] <= float(other or 0) def __eq__(self, other): if isinstance(other, Price): - if not other["base"]["symbol"] == self["base"]["symbol"]: - raise AssertionError() - if not other["quote"]["symbol"] == self["quote"]["symbol"]: - raise AssertionError() + self._check_other(other) return self["price"] == other["price"] else: return self["price"] == float(other or 0) def __ne__(self, other): if isinstance(other, Price): - if not other["base"]["symbol"] == self["base"]["symbol"]: - raise AssertionError() - if not other["quote"]["symbol"] == self["quote"]["symbol"]: - raise AssertionError() + self._check_other(other) return self["price"] != other["price"] else: return self["price"] != float(other or 0) def __ge__(self, other): if isinstance(other, Price): - if not other["base"]["symbol"] == self["base"]["symbol"]: - raise AssertionError() - if not other["quote"]["symbol"] == self["quote"]["symbol"]: - raise AssertionError() + self._check_other(other) return self["price"] >= other["price"] else: return self["price"] >= float(other or 0) def __gt__(self, other): if isinstance(other, Price): - if not other["base"]["symbol"] == self["base"]["symbol"]: - raise AssertionError() - if not other["quote"]["symbol"] == self["quote"]["symbol"]: - raise AssertionError() + self._check_other(other) return self["price"] > other["price"] else: return self["price"] > float(other or 0) diff --git a/beem/steem.py b/beem/steem.py index 1c3ad1d4123141483adf39bd5ef1fea870717d3a..ba14e0b1a6684f633654c1997db1ca191695fb4e 100644 --- a/beem/steem.py +++ b/beem/steem.py @@ -131,6 +131,7 @@ class Steem(object): self.register_apis() self.wallet = Wallet(self.rpc, **kwargs) + self.wallet.steem = self self.data = {'last_refresh': None, 'dynamic_global_properties': None, 'feed_history': None, 'current_median_history_price': None, 'next_scheduled_hardfork': None, diff --git a/beem/version.py b/beem/version.py index beb9d42278b3d419adc6fa5942a533dc7bcd9870..21ea10598e7caafd360a913823d3afa25cbd8973 100644 --- a/beem/version.py +++ b/beem/version.py @@ -1,4 +1,2 @@ - -""" THIS FILE IS GENERATED FROM beem SETUP.PY -""" +"""THIS FILE IS GENERATED FROM beem SETUP.PY.""" version = '0.19.11' diff --git a/beem/wallet.py b/beem/wallet.py index f4dbda02547a9488f8889b2a75e75bcefa8c9632..9857f954ff5bbbdb46b9de8e5b05ffe72e84b55d 100644 --- a/beem/wallet.py +++ b/beem/wallet.py @@ -95,6 +95,7 @@ class Wallet(object): """ keys = [] rpc = None + steem = None masterpassword = None # Keys from database @@ -436,7 +437,7 @@ class Wallet(object): """ for name in self.getAccountsFromPublicKey(pub): try: - account = Account(name) # FIXME: self.steem is not available in wallet! + account = Account(name, steem_instance=self.steem) except: continue yield {"name": account["name"], @@ -453,7 +454,7 @@ class Wallet(object): return {"name": None, "type": None, "pubkey": pub} else: try: - account = Account(name) # FIXME: self.steem is not available in wallet! + account = Account(name, steem_instance=self.steem) except: return return {"name": account["name"], diff --git a/beemapi/__init__.py b/beemapi/__init__.py index 7822133e279c3bbc7fadc71036b31780c296da56..024b915de1faef7435fad1b4485b787525c2e2a2 100644 --- a/beemapi/__init__.py +++ b/beemapi/__init__.py @@ -1,3 +1,4 @@ +""" beemapi.""" from .version import version as __version__ __all__ = [ "steemnoderpc", diff --git a/beemapi/version.py b/beemapi/version.py index beb9d42278b3d419adc6fa5942a533dc7bcd9870..21ea10598e7caafd360a913823d3afa25cbd8973 100644 --- a/beemapi/version.py +++ b/beemapi/version.py @@ -1,4 +1,2 @@ - -""" THIS FILE IS GENERATED FROM beem SETUP.PY -""" +"""THIS FILE IS GENERATED FROM beem SETUP.PY.""" version = '0.19.11' diff --git a/beemapi/websocket.py b/beemapi/websocket.py index a58ef489d69d0aaaa1094a9e4aedfd2d39e785db..c38e73a1e3f4a3f8389b8c1e8218d19200cc499f 100644 --- a/beemapi/websocket.py +++ b/beemapi/websocket.py @@ -62,11 +62,11 @@ class SteemWebsocket(Events): urls, user="", password="", - *args, only_block_id=False, on_block=None, keep_alive=25, num_retries=-1, + *args, **kwargs ): @@ -245,8 +245,13 @@ class SteemWebsocket(Events): except websocket.WebSocketException as exc: if (self.num_retries >= 0 and cnt > self.num_retries): raise NumRetriesReached() - - sleeptime = (cnt - 1) * 2 if cnt < 10 else 10 + + if cnt < 0: + seeptime = 0 + elif cnt < 10: + sleeptime = (cnt - 1) * 2 + else: + sleeptime = 10 if sleeptime: log.warning( "Lost connection to node during wsconnect(): %s (%d/%d) " diff --git a/beembase/__init__.py b/beembase/__init__.py index b1e2f416a4b7de2980e066bdae7c6257146be9e3..c132551d22f368ccab55ca8e8fea47e79874552d 100644 --- a/beembase/__init__.py +++ b/beembase/__init__.py @@ -1,3 +1,4 @@ +""" beembase.""" from .version import version as __version__ __all__ = [ 'account', diff --git a/beembase/version.py b/beembase/version.py index beb9d42278b3d419adc6fa5942a533dc7bcd9870..21ea10598e7caafd360a913823d3afa25cbd8973 100644 --- a/beembase/version.py +++ b/beembase/version.py @@ -1,4 +1,2 @@ - -""" THIS FILE IS GENERATED FROM beem SETUP.PY -""" +"""THIS FILE IS GENERATED FROM beem SETUP.PY.""" version = '0.19.11' diff --git a/beemgrapheneapi/__init__.py b/beemgrapheneapi/__init__.py index 8e97a195e06ab3a67fb26bbbcaec91744769d7ed..73b6a20704273564925c963785852483c061240b 100644 --- a/beemgrapheneapi/__init__.py +++ b/beemgrapheneapi/__init__.py @@ -1,3 +1,4 @@ +"""beemgrapheneapi.""" from .version import version as __version__ __all__ = ['grapheneapi', 'graphenewsrpc' diff --git a/beemgrapheneapi/grapheneapi.py b/beemgrapheneapi/grapheneapi.py index 834ca5801106e6493179afb0c3c5ceed0e4e2c79..50b4ad6548cfdafacb2dcdf8ca48a1360406b575 100644 --- a/beemgrapheneapi/grapheneapi.py +++ b/beemgrapheneapi/grapheneapi.py @@ -1,11 +1,13 @@ +"""graphenapi.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals + from builtins import object -import sys import json import logging +import sys log = logging.getLogger(__name__) try: @@ -15,63 +17,72 @@ except ImportError: class UnauthorizedError(Exception): + """UnauthorizedError Exception.""" + pass class RPCError(Exception): + """RPCError Exception.""" + pass class RPCConnection(Exception): + """RPCConnection Exception.""" + pass class GrapheneAPI(object): - """ Graphene JSON-HTTP-RPC API + """ + Graphene JSON-HTTP-RPC API. - This class serves as an abstraction layer for easy use of the - Grapehene API. + This class serves as an abstraction layer for easy use of the + Grapehene API. - :param str host: Host of the API server - :param int port: Port to connect to - :param str username: Username for Authentication (if required, - defaults to "") - :param str password: Password for Authentication (if required, - defaults to "") + :param str host: Host of the API server + :param int port: Port to connect to + :param str username: Username for Authentication (if required, + defaults to "") + :param str password: Password for Authentication (if required, + defaults to "") - All RPC commands of the Graphene client are exposed as methods - in the class ``grapheneapi``. Once an instance of GrapheneAPI is - created with host, port, username, and password, e.g., + All RPC commands of the Graphene client are exposed as methods + in the class ``grapheneapi``. Once an instance of GrapheneAPI is + created with host, port, username, and password, e.g., - .. code-block:: python + .. code-block:: python - from grapheneapi import GrapheneAPI - rpc = GrapheneAPI("localhost", 8092, "", "") + from grapheneapi import GrapheneAPI + rpc = GrapheneAPI("localhost", 8092, "", "") - any call available to that port can be issued using the instance - via the syntax rpc.*command*(*parameters*). Example: + any call available to that port can be issued using the instance + via the syntax rpc.*command*(*parameters*). Example: - .. code-block:: python + .. code-block:: python - rpc.info() + rpc.info() - .. note:: A distinction has to be made whether the connection is - made to a **witness/full node** which handles the - blockchain and P2P network, or a **cli-wallet** that - handles wallet related actions! The available commands - differ drastically! + .. note:: A distinction has to be made whether the connection is + made to a **witness/full node** which handles the + blockchain and P2P network, or a **cli-wallet** that + handles wallet related actions! The available commands + differ drastically! - If you are connected to a wallet, you can simply initiate a transfer with: + If you are connected to a wallet, you can simply initiate a transfer with: - .. code-block:: python + .. code-block:: python - res = client.transfer("sender","receiver","5", "USD", "memo", True); + res = client.transfer("sender","receiver","5", "USD", "memo", True); - Again, the witness node does not offer access to construct any transactions, - and hence the calls available to the witness-rpc can be seen as read-only for - the blockchain. + Again, the witness node does not offer access to construct any transactions, + and hence the calls available to the witness-rpc can be seen as read-only for + the blockchain. """ + def __init__(self, host, port, username="", password=""): + """init.""" self.host = host self.port = port self.username = username @@ -79,20 +90,21 @@ class GrapheneAPI(object): self.headers = {'content-type': 'application/json'} def rpcexec(self, payload): - """ Manual execute a command on API (internally used) + """ + Manual execute a command on API (internally used). - param str payload: The payload containing the request - return: Servers answer to the query - rtype: json - raises RPCConnection: if no connction can be made - raises UnauthorizedError: if the user is not authorized - raise ValueError: if the API returns a non-JSON formated answer + param str payload: The payload containing the request + return: Servers answer to the query + rtype: json + raises RPCConnection: if no connction can be made + raises UnauthorizedError: if the user is not authorized + raise ValueError: if the API returns a non-JSON formated answer - It is not recommended to use this method directly, unless - you know what you are doing. All calls available to the API - will be wrapped to methods directly:: + It is not recommended to use this method directly, unless + you know what you are doing. All calls available to the API + will be wrapped to methods directly:: - info -> grapheneapi.info() + info -> grapheneapi.info() """ try: response = requests.post("http://{}:{}/rpc".format(self.host, @@ -120,8 +132,7 @@ class GrapheneAPI(object): return ret["result"] def __getattr__(self, name): - """ Map all methods to RPC calls and pass through the arguments - """ + """Map all methods to RPC calls and pass through the arguments.""" def method(*args): query = {"method": name, "params": args, diff --git a/beemgrapheneapi/graphenewsrpc.py b/beemgrapheneapi/graphenewsrpc.py index 56ca52ad131d15349ad3f0142ce7d317b492fadb..7f1559e76ec0d0bd017e092e151609bb5b6c72e6 100644 --- a/beemgrapheneapi/graphenewsrpc.py +++ b/beemgrapheneapi/graphenewsrpc.py @@ -1,62 +1,73 @@ +"""graphennewsrpc.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals + from builtins import next from builtins import object +from itertools import cycle +import json +import logging +import ssl import sys import threading -import websocket -import ssl -import json import time -from itertools import cycle import warnings -import logging + +import websocket log = logging.getLogger(__name__) class RPCError(Exception): + """RPCError Exception.""" + pass class NumRetriesReached(Exception): + """NumRetriesReached Exception.""" + pass class GrapheneWebsocketRPC(object): - """ This class allows to call API methods synchronously, without - callbacks. It logs in and registers to the APIs: + """ + This class allows to call API methods synchronously, without callbacks. - * database - * history + It logs in and registers to the APIs: - :param str urls: Either a single Websocket URL, or a list of URLs - :param str user: Username for Authentication - :param str password: Password for Authentication - :param Array apis: List of APIs to register to (default: ["database", "network_broadcast"]) - :param int num_retries: Try x times to num_retries to a node on disconnect, -1 for indefinitely + * database + * history - Available APIs + :param str urls: Either a single Websocket URL, or a list of URLs + :param str user: Username for Authentication + :param str password: Password for Authentication + :param Array apis: List of APIs to register to (default: ["database", "network_broadcast"]) + :param int num_retries: Try x times to num_retries to a node on disconnect, -1 for indefinitely - * database - * network_node - * network_broadcast - * history + Available APIs - Usage: + * database + * network_node + * network_broadcast + * history - .. code-block:: python + Usage: - ws = GrapheneWebsocketRPC("ws://10.0.0.16:8090","","") - print(ws.get_account_count()) + .. code-block:: python - .. note:: This class allows to call methods available via - websocket. If you want to use the notification - subsystem, please use ``GrapheneWebsocket`` instead. + ws = GrapheneWebsocketRPC("ws://10.0.0.16:8090","","") + print(ws.get_account_count()) + + .. note:: This class allows to call methods available via + websocket. If you want to use the notification + subsystem, please use ``GrapheneWebsocket`` instead. """ + def __init__(self, urls, user="", password="", **kwargs): + """Init.""" self.api_id = {} self._request_id = 0 if isinstance(urls, list): @@ -71,10 +82,12 @@ class GrapheneWebsocketRPC(object): self.register_apis() def get_request_id(self): + """Get request id.""" self._request_id += 1 return self._request_id def wsconnect(self): + """Connect to Websocket in a loop.""" cnt = 0 while True: cnt += 1 @@ -105,17 +118,18 @@ class GrapheneWebsocketRPC(object): self.login(self.user, self.password, api_id=1) def register_apis(self): + """Register apis.""" self.api_id["database"] = self.database(api_id=1) self.api_id["history"] = self.history(api_id=1) self.api_id["network_broadcast"] = self.network_broadcast(api_id=1) - # RPC Calls def rpcexec(self, payload): - """ Execute a call by sending the payload + """ + Execute a call by sending the payload. - :param json payload: Payload data - :raises ValueError: if the server does not respond in proper JSON format - :raises RPCError: if the server returns an error + :param json payload: Payload data + :raises ValueError: if the server does not respond in proper JSON format + :raises RPCError: if the server returns an error """ log.debug(json.dumps(payload)) cnt = 0 @@ -169,8 +183,7 @@ class GrapheneWebsocketRPC(object): # End of Deprecated methods #################################################################### def __getattr__(self, name): - """ Map all methods to RPC calls and pass through the arguments - """ + """Map all methods to RPC calls and pass through the arguments.""" def method(*args, **kwargs): # Sepcify the api to talk to diff --git a/beemgrapheneapi/version.py b/beemgrapheneapi/version.py index beb9d42278b3d419adc6fa5942a533dc7bcd9870..21ea10598e7caafd360a913823d3afa25cbd8973 100644 --- a/beemgrapheneapi/version.py +++ b/beemgrapheneapi/version.py @@ -1,4 +1,2 @@ - -""" THIS FILE IS GENERATED FROM beem SETUP.PY -""" +"""THIS FILE IS GENERATED FROM beem SETUP.PY.""" version = '0.19.11' diff --git a/beemgraphenebase/__init__.py b/beemgraphenebase/__init__.py index 7f1eb8a848f956cfbf8afda353694e63d88ec646..888504f6d1f472b6a4b6ebd58b1d02a11329955f 100644 --- a/beemgraphenebase/__init__.py +++ b/beemgraphenebase/__init__.py @@ -1,3 +1,4 @@ +"""beemgraphenebase.""" from .version import version as __version__ # from . import account as Account # from .account import PrivateKey, PublicKey, Address, BrainKey diff --git a/beemgraphenebase/types.py b/beemgraphenebase/types.py index 5e81dfd3bde0de96b084cb4add899ddb623f300f..3fdd439ed61f699bbe90670ecb9f61d9003a33be 100644 --- a/beemgraphenebase/types.py +++ b/beemgraphenebase/types.py @@ -1,30 +1,32 @@ +"""types.""" # encoding=utf8 from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals -from builtins import str + from builtins import bytes +from builtins import str from builtins import object from builtins import int -from future.utils import python_2_unicode_compatible import json import struct import sys import time from calendar import timegm -from datetime import datetime from binascii import hexlify, unhexlify +from datetime import datetime from collections import OrderedDict from .objecttypes import object_type + +from future.utils import python_2_unicode_compatible from .py23 import py23_bytes timeformat = '%Y-%m-%dT%H:%M:%S%Z' def varint(n): - """ Varint encoding - """ + """Varint encoding.""" data = b'' while n >= 0x80: data += bytes([(n & 0x7f) | 0x80]) @@ -34,8 +36,7 @@ def varint(n): def varintdecode(data): - """ Varint decoding - """ + """Varint decoding.""" shift = 0 result = 0 for c in data: @@ -48,35 +49,42 @@ def varintdecode(data): def variable_buffer(s): - """ Encode variable length buffer - """ + """Encodes variable length buffer.""" return varint(len(s)) + s def JsonObj(data): - """ Returns json object from data - """ + """Returns json object from data.""" return json.loads(str(data)) @python_2_unicode_compatible class Uint8(object): + """Uint8.""" + def __init__(self, d): + """init.""" self.data = int(d) def __bytes__(self): + """Returns bytes.""" return struct.pack("<B", self.data) def __str__(self): + """Returns str""" return '%d' % self.data @python_2_unicode_compatible class Int16(object): + """Int16.""" + def __init__(self, d): + """init.""" self.data = int(d) def __bytes__(self): + """Returns bytes.""" return struct.pack("<h", int(self.data)) def __str__(self): @@ -89,6 +97,7 @@ class Uint16(object): self.data = int(d) def __bytes__(self): + """Returns bytes.""" return struct.pack("<H", self.data) def __str__(self): @@ -101,9 +110,11 @@ class Uint32(object): self.data = int(d) def __bytes__(self): + """Returns bytes.""" return struct.pack("<I", self.data) def __str__(self): + """Returns data as string.""" return '%d' % self.data @@ -113,9 +124,11 @@ class Uint64(object): self.data = int(d) def __bytes__(self): + """Returns bytes.""" return struct.pack("<Q", self.data) def __str__(self): + """Returns data as string.""" return '%d' % self.data @@ -125,9 +138,11 @@ class Varint32(object): self.data = int(d) def __bytes__(self): + """Returns bytes.""" return varint(self.data) def __str__(self): + """Returns data as string.""" return '%d' % self.data @@ -137,9 +152,11 @@ class Int64(object): self.data = int(d) def __bytes__(self): + """Returns bytes.""" return struct.pack("<q", self.data) def __str__(self): + """Returns data as string.""" return '%d' % self.data @@ -149,10 +166,12 @@ class String(object): self.data = d def __bytes__(self): + """Returns bytes representation.""" d = self.unicodify() return varint(len(d)) + d def __str__(self): + """Returns data as string.""" return '%s' % str(self.data) def unicodify(self): @@ -190,11 +209,13 @@ class Bytes(object): self.length = len(self.data) def __bytes__(self): + """Returns data as bytes.""" # FIXME constraint data to self.length d = unhexlify(bytes(self.data, 'utf-8')) return varint(len(d)) + d def __str__(self): + """Returns data as string.""" return str(self.data) @@ -204,9 +225,11 @@ class Void(object): pass def __bytes__(self): + """Returns bytes representation.""" return b'' def __str__(self): + """Returns data as string.""" return "" @@ -217,9 +240,11 @@ class Array(object): self.length = Varint32(len(self.data)) def __bytes__(self): + """Returns bytes representation.""" return py23_bytes(self.length) + b"".join([py23_bytes(a) for a in self.data]) def __str__(self): + """Returns data as string.""" r = [] for a in self.data: try: @@ -235,12 +260,14 @@ class PointInTime(object): self.data = d def __bytes__(self): + """Returns bytes representation.""" if sys.version > '3': return struct.pack("<I", timegm(time.strptime((self.data + "UTC"), timeformat))) else: return struct.pack("<I", timegm(time.strptime((self.data + "UTC"), timeformat.encode("utf-8")))) def __str__(self): + """Returns data as string.""" return self.data @@ -250,9 +277,11 @@ class Signature(object): self.data = d def __bytes__(self): + """Returns bytes representation.""" return self.data def __str__(self): + """Returns data as string.""" return json.dumps(hexlify(self.data).decode('ascii')) @@ -262,6 +291,7 @@ class Bool(Uint8): # Bool = Uint8 super(Bool, self).__init__(d) def __str__(self): + """Returns data as string.""" return json.dumps(True) if self.data else json.dumps(False) @@ -276,9 +306,11 @@ class Fixed_array(object): raise NotImplementedError def __bytes__(self): + """Returns bytes representation.""" raise NotImplementedError def __str__(self): + """Returns data as string.""" raise NotImplementedError @@ -288,12 +320,14 @@ class Optional(object): self.data = d def __bytes__(self): + """Returns data as bytes.""" if not self.data: return py23_bytes(Bool(0)) else: return py23_bytes(Bool(1)) + py23_bytes(self.data) if py23_bytes(self.data) else py23_bytes(Bool(0)) def __str__(self): + """Returns data as string.""" return str(self.data) def isempty(self): @@ -309,9 +343,11 @@ class Static_variant(object): self.type_id = type_id def __bytes__(self): + """Returns bytes representation.""" return varint(self.type_id) + py23_bytes(self.data) def __str__(self): + """Returns data as string.""" return json.dumps([self.type_id, self.data.json()]) @@ -321,6 +357,7 @@ class Map(object): self.data = data def __bytes__(self): + """Returns bytes representation.""" b = b"" b += varint(len(self.data)) for e in self.data: @@ -328,6 +365,7 @@ class Map(object): return b def __str__(self): + """Returns data as string.""" r = [] for e in self.data: r.append([str(e[0]), str(e[1])]) @@ -340,9 +378,11 @@ class Id(object): self.data = Varint32(d) def __bytes__(self): + """Returns bytes representation.""" return py23_bytes(self.data) def __str__(self): + """Returns data as string.""" return str(self.data) @@ -356,10 +396,12 @@ class VoteId(object): self.instance = int(parts[1]) def __bytes__(self): + """Returns bytes representation.""" binary = (self.type & 0xff) | (self.instance << 8) return struct.pack("<I", binary) def __str__(self): + """Returns data as string.""" return "%d:%d" % (self.type, self.instance) @@ -383,9 +425,11 @@ class ObjectId(object): raise Exception("Object id is invalid") def __bytes__(self): + """Returns bytes representation.""" return py23_bytes(self.instance) # only yield instance def __str__(self): + """Returns data as string.""" return self.Id @@ -405,11 +449,13 @@ class FullObjectId(object): raise Exception("Object id is invalid") def __bytes__(self): + """Returns bytes representation.""" return ( self.space << 56 | self.type << 48 | self.id ).to_bytes(8, byteorder="little", signed=False) def __str__(self): + """Returns data as string.""" return self.Id @@ -426,4 +472,5 @@ class Enum8(Uint8): super(Enum8, self).__init__(selection) def __str__(self): + """Returns data as string.""" return str(self.options[self.data]) diff --git a/beemgraphenebase/version.py b/beemgraphenebase/version.py index beb9d42278b3d419adc6fa5942a533dc7bcd9870..21ea10598e7caafd360a913823d3afa25cbd8973 100644 --- a/beemgraphenebase/version.py +++ b/beemgraphenebase/version.py @@ -1,4 +1,2 @@ - -""" THIS FILE IS GENERATED FROM beem SETUP.PY -""" +"""THIS FILE IS GENERATED FROM beem SETUP.PY.""" version = '0.19.11' diff --git a/setup.py b/setup.py index 244d78b4e79179fe9a6797392c0ae6882b4dcac4..9eac494f15b1cda8b85c797c1aa51381fe8812e9 100755 --- a/setup.py +++ b/setup.py @@ -36,11 +36,8 @@ requires = [ def write_version_py(filename): - """ Write version - """ - cnt = """ -\""" THIS FILE IS GENERATED FROM beem SETUP.PY -\""" + """Write version.""" + cnt = """\"""THIS FILE IS GENERATED FROM beem SETUP.PY.\""" version = '%(version)s' """ with open(filename, 'w') as a: diff --git a/tests/__init__.py b/tests/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2813bd379a19ac1ea9a85dcbf1e9d4e205e068e0 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Unit tests.""" \ No newline at end of file diff --git a/tests/beembase/__init__.py b/tests/beembase/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2813bd379a19ac1ea9a85dcbf1e9d4e205e068e0 100644 --- a/tests/beembase/__init__.py +++ b/tests/beembase/__init__.py @@ -0,0 +1 @@ +"""Unit tests.""" \ No newline at end of file diff --git a/tests/beemgraphene/__init__.py b/tests/beemgraphene/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2813bd379a19ac1ea9a85dcbf1e9d4e205e068e0 100644 --- a/tests/beemgraphene/__init__.py +++ b/tests/beemgraphene/__init__.py @@ -0,0 +1 @@ +"""Unit tests.""" \ No newline at end of file diff --git a/tests/test_discussions.py b/tests/test_discussions.py index 8fc065105bcce190e34b140a0d3d9c2cd3224c80..b79b7a6e1dfb4fc6fc5a6293e6c548e793f955b0 100644 --- a/tests/test_discussions.py +++ b/tests/test_discussions.py @@ -6,7 +6,13 @@ from builtins import super import unittest from pprint import pprint from beem import Steem -from beem.discussions import Query, Discussions_by_trending +from beem.discussions import ( + Query, Discussions_by_trending, Comment_discussions_by_payout, + Post_discussions_by_payout, Discussions_by_created, Discussions_by_active, + Discussions_by_cashout, Discussions_by_payout, Discussions_by_votes, + Discussions_by_children, Discussions_by_hot, Discussions_by_feed, Discussions_by_blog, + Discussions_by_comments, Discussions_by_promoted +) from datetime import datetime from beem.instance import set_shared_steem_instance @@ -35,5 +41,102 @@ class Testcases(unittest.TestCase): bts = self.bts query = Query() query["limit"] = 10 + query["tag"] = "steemit" d = Discussions_by_trending(query, steem_instance=bts) self.assertEqual(len(d), 10) + + def test_comment_payout(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Comment_discussions_by_payout(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_post_payout(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Post_discussions_by_payout(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_created(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Discussions_by_created(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_active(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Discussions_by_active(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_cashout(self): + bts = self.bts + query = Query() + query["limit"] = 10 + d = Discussions_by_cashout({"limit": 10}, steem_instance=bts) + # self.assertEqual(len(d), 10) + + def test_payout(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Discussions_by_payout(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_votes(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Discussions_by_votes(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_children(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Discussions_by_children(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_feed(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "gtg" + d = Discussions_by_feed(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_blog(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "gtg" + d = Discussions_by_blog(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_comments(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["filter_tags"] = ["gtg"] + query["start_author"] = "gtg" + d = Discussions_by_comments(query, steem_instance=bts) + self.assertEqual(len(d), 10) + + def test_promoted(self): + bts = self.bts + query = Query() + query["limit"] = 10 + query["tag"] = "steemit" + d = Discussions_by_promoted(query, steem_instance=bts) + self.assertEqual(len(d), 10) diff --git a/tests/test_websocket.py b/tests/test_websocket.py new file mode 100644 index 0000000000000000000000000000000000000000..c65aced209fe704584c51638161e63ea17e32534 --- /dev/null +++ b/tests/test_websocket.py @@ -0,0 +1,41 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals +from builtins import range +from builtins import super +import mock +import string +import unittest +import random +import itertools +from pprint import pprint +from beem import Steem +from beemapi.websocket import SteemWebsocket +from beem.instance import set_shared_steem_instance +# Py3 compatibility +import sys + +wif = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3" +core_unit = "STM" +nodes = ["wss://steemd.pevo.science", "wss://gtg.steem.house:8090", "wss://rpc.steemliberator.com", "wss://rpc.buildteam.io", + "wss://rpc.steemviz.com", "wss://seed.bitcoiner.me", "wss://node.steem.ws", "wss://steemd.steemgigs.org", "wss://steemd.steemit.com", + "wss://steemd.minnowsupportproject.org"] + + +class Testcases(unittest.TestCase): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.ws = SteemWebsocket( + nodes, + ) + + def test_connect(self): + self.assertIn(next(self.ws.urls), nodes) + self.assertIn(next(self.ws.urls), nodes) + self.assertIn(next(self.ws.urls), nodes) + self.assertIn(next(self.ws.urls), nodes) + + \ No newline at end of file