diff --git a/grapheneapi/aio/api.py b/grapheneapi/aio/api.py index 245670ff..c52eabda 100644 --- a/grapheneapi/aio/api.py +++ b/grapheneapi/aio/api.py @@ -32,8 +32,7 @@ def get_network(self): return self._chain_props async def cache_chain_properties(self): - """ Cache chain properties to prevent turning lots of methods into async - """ + """Cache chain properties to prevent turning lots of methods into async""" self._chain_props = await self.get_chain_properties() def get_cached_chain_properties(self): @@ -58,8 +57,7 @@ async def next(self): await self.connect() async def find_next(self): - """ Find the next url in the list - """ + """Find the next url in the list""" if int(self.num_retries) < 0: # pragma: no cover self._cnt_retries += 1 sleeptime = (self._cnt_retries - 1) * 2 if self._cnt_retries < 10 else 10 @@ -103,8 +101,7 @@ async def func(*args, **kwargs): except KeyboardInterrupt: # pragma: no cover raise except RPCError as e: # pragma: no cover - """ When the backend actual returns an error - """ + """When the backend actual returns an error""" self.post_process_exception(e) # the above line should raise. Let's be sure to at least # break @@ -118,8 +115,7 @@ async def func(*args, **kwargs): self.error_url() self.next() except Exception as e: # pragma: no cover - """ When something fails talking to the backend - """ + """When something fails talking to the backend""" import traceback log.debug(traceback.format_exc()) diff --git a/grapheneapi/aio/http.py b/grapheneapi/aio/http.py index 1b06d02b..67228a80 100644 --- a/grapheneapi/aio/http.py +++ b/grapheneapi/aio/http.py @@ -9,8 +9,7 @@ class Http(Rpc): - """ RPC Calls - """ + """RPC Calls""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -24,10 +23,10 @@ async def disconnect(self): await self.session.close() async def rpcexec(self, payload): - """ Execute a RPC call + """Execute a RPC call - :param dict payload: json-rpc request in format: - {"jsonrpc": "2.0", "method": "call", "params": "[x, y, z]", "id": 1} + :param dict payload: json-rpc request in format: + {"jsonrpc": "2.0", "method": "call", "params": "[x, y, z]", "id": 1} """ async with self.session.post(self.url, json=payload) as response: response_text = await response.text() diff --git a/grapheneapi/aio/rpc.py b/grapheneapi/aio/rpc.py index 931fbd22..16a02569 100644 --- a/grapheneapi/aio/rpc.py +++ b/grapheneapi/aio/rpc.py @@ -16,10 +16,10 @@ def __init__(self, url, *args, loop=None, **kwargs): self.loop = kwargs.get(loop, asyncio.get_event_loop()) 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 - This method is actually defined in RPC class, but we need to - overwrite this here so that we can use async/await. + This method is actually defined in RPC class, but we need to + overwrite this here so that we can use async/await. """ async def method(*args, **kwargs): diff --git a/grapheneapi/aio/websocket.py b/grapheneapi/aio/websocket.py index bfea7e98..881210cb 100644 --- a/grapheneapi/aio/websocket.py +++ b/grapheneapi/aio/websocket.py @@ -30,7 +30,7 @@ async def disconnect(self): await self.ws.close() async def _parsing_wrapper(self): - """ Wraps parse_messages() coroutine to retrieve and handle exceptions + """Wraps parse_messages() coroutine to retrieve and handle exceptions When parse_messages() stopped for any reason, websocket transport should be stopped, and get_response_by_id() should be notified about broken parser @@ -52,12 +52,12 @@ async def _parsing_wrapper(self): self._event.set() async def parse_messages(self): - """ Listen websocket for incoming messages in infinity manner + """Listen websocket for incoming messages in infinity manner - Messages which are responses (has id) are stored in dict, while - messages which are notifies are stored in asyncio queue and are - supposed to be processed later by whom who sets the subscribtion - callback + Messages which are responses (has id) are stored in dict, while + messages which are notifies are stored in asyncio queue and are + supposed to be processed later by whom who sets the subscribtion + callback """ async for message in self.ws: @@ -97,9 +97,9 @@ async def parse_messages(self): await self.notifications.put(m) async def get_response_by_id(self, request_id): - """ Pop response from dict containing all query results + """Pop response from dict containing all query results - :param int request_id: request id to get response to + :param int request_id: request id to get response to """ response = None while not response: @@ -114,10 +114,10 @@ async def get_response_by_id(self, request_id): return response async def rpcexec(self, payload): - """ Execute a RPC call + """Execute a RPC call - :param dict payload: json-rpc request in format: - {"jsonrpc": "2.0", "method": "call", "params": "[x, y, z]", "id": 1} + :param dict payload: json-rpc request in format: + {"jsonrpc": "2.0", "method": "call", "params": "[x, y, z]", "id": 1} """ if not self.ws: await self.connect() diff --git a/grapheneapi/api.py b/grapheneapi/api.py index 54d58edc..fa15ab14 100644 --- a/grapheneapi/api.py +++ b/grapheneapi/api.py @@ -84,8 +84,7 @@ def connect(self): self.register_apis() def find_next(self): - """ Find the next url in the list - """ + """Find the next url in the list""" if int(self.num_retries) < 0: # pragma: no cover self._cnt_retries += 1 sleeptime = (self._cnt_retries - 1) * 2 if self._cnt_retries < 10 else 10 @@ -119,8 +118,7 @@ def find_next(self): return url def reset_counter(self): - """ reset the failed connection counters - """ + """reset the failed connection counters""" self._cnt_retries = 0 for i in self._url_counter: self._url_counter[i] = 0 @@ -141,34 +139,34 @@ def post_process_exception(self, exception): @property def api_id(self): - """ This allows to list api_ids, if they have been registered through - api_register() -- LEGACY + """This allows to list api_ids, if they have been registered through + api_register() -- LEGACY - In previous API version, one would connect and register to APIs - like this + In previous API version, one would connect and register to APIs + like this - .. code-block:: python + .. code-block:: python - 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) + 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) """ return self.connection.api_id def register_apis(self): # pragma: no cover - """ This method is called right after connection and has previously - been used to register to different APIs within the backend that are - considered default. The requirement to register to APIs has been - removed in some systems. + """This method is called right after connection and has previously + been used to register to different APIs within the backend that are + considered default. The requirement to register to APIs has been + removed in some systems. """ pass def __getattr__(self, name): - """ Proxies RPC calls to actual Websocket or Http instance. + """Proxies RPC calls to actual Websocket or Http instance. - Connection-related errors catched here and handled. + Connection-related errors catched here and handled. """ def func(*args, **kwargs): @@ -182,8 +180,7 @@ def func(*args, **kwargs): except KeyboardInterrupt: # pragma: no cover raise except RPCError as e: # pragma: no cover - """ When the backend actual returns an error - """ + """When the backend actual returns an error""" self.post_process_exception(e) # the above line should raise. Let's be sure to at least # break @@ -197,8 +194,7 @@ def func(*args, **kwargs): self.error_url() self.next() except Exception as e: # pragma: no cover - """ When something fails talking to the backend - """ + """When something fails talking to the backend""" import traceback log.debug(traceback.format_exc()) diff --git a/grapheneapi/grapheneapi.py b/grapheneapi/grapheneapi.py index 75d0602e..571fb399 100644 --- a/grapheneapi/grapheneapi.py +++ b/grapheneapi/grapheneapi.py @@ -13,49 +13,49 @@ 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=""): @@ -66,20 +66,20 @@ def __init__(self, host, port, username="", password=""): 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( @@ -108,8 +108,7 @@ def rpcexec(self, payload): 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, "jsonrpc": "2.0", "id": 0} diff --git a/grapheneapi/http.py b/grapheneapi/http.py index 74d92591..f3214a48 100644 --- a/grapheneapi/http.py +++ b/grapheneapi/http.py @@ -10,8 +10,7 @@ class Http(Rpc): - """ RPC Calls - """ + """RPC Calls""" def proxies(self): # pragma: no cover proxy_url = self.get_proxy_url() @@ -20,13 +19,13 @@ def proxies(self): # pragma: no cover return {"http": proxy_url, "https": proxy_url} 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 HttpInvalidStatusCode: if the server returns a status code - that is not 200 + :param json payload: Payload data + :raises ValueError: if the server does not respond in proper JSON + format + :raises HttpInvalidStatusCode: if the server returns a status code + that is not 200 """ log.debug(json.dumps(payload)) query = requests.post(self.url, json=payload, proxies=self.proxies()) diff --git a/grapheneapi/rpc.py b/grapheneapi/rpc.py index 0e1026b2..aaec25e0 100644 --- a/grapheneapi/rpc.py +++ b/grapheneapi/rpc.py @@ -10,21 +10,21 @@ class Rpc: - """ This class allows to call API methods synchronously, without - callbacks. + """This class allows to call API methods synchronously, without + callbacks. - :param str url: A single REST endpoint URL - :param int num_retries: Try x times to num_retries to a node on - disconnect, -1 for indefinitely - :param str proxy: Proxy URL (e.g. socks5://localhost:9050), - None by default. + :param str url: A single REST endpoint URL + :param int num_retries: Try x times to num_retries to a node on + disconnect, -1 for indefinitely + :param str proxy: Proxy URL (e.g. socks5://localhost:9050), + None by default. - Usage: + Usage: - .. code-block:: python + .. code-block:: python - ws = GrapheneHTTPRPC("https://api.node.com") - print(ws.get_account_count()) + ws = GrapheneHTTPRPC("https://api.node.com") + print(ws.get_account_count()) """ @@ -119,8 +119,7 @@ def parse_response(self, query, log_on_debug=True): 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, **kwargs): diff --git a/grapheneapi/websocket.py b/grapheneapi/websocket.py index f6adafa6..7aa26d58 100644 --- a/grapheneapi/websocket.py +++ b/grapheneapi/websocket.py @@ -50,11 +50,11 @@ def disconnect(self): """ 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 + :param json payload: Payload data + :raises ValueError: if the server does not respond in proper JSON + format """ if not self.ws: # pragma: no cover self.connect() diff --git a/graphenebase/account.py b/graphenebase/account.py index 82e2b5ec..22e74133 100644 --- a/graphenebase/account.py +++ b/graphenebase/account.py @@ -15,10 +15,10 @@ class PasswordKey(Prefix): - """ This class derives a private key given the account name, the - role and a password. It leverages the technology of Brainkeys - and allows people to have a secure private key by providing a - passphrase only. + """This class derives a private key given the account name, the + role and a password. It leverages the technology of Brainkeys + and allows people to have a secure private key by providing a + passphrase only. """ def __init__(self, account, password, role="active", prefix=None): @@ -28,8 +28,8 @@ def __init__(self, account, password, role="active", prefix=None): self.password = password def get_private(self): - """ Derive private key from the brain key and the current sequence - number + """Derive private key from the brain key and the current sequence + number """ a = _bytes(self.account + self.role + self.password) s = hashlib.sha256(a).digest() @@ -48,20 +48,20 @@ def get_public_key(self): class BrainKey(Prefix): """Brainkey implementation similar to the graphene-ui web-wallet. - :param str brainkey: Brain Key - :param int sequence: Sequence number for consecutive keys + :param str brainkey: Brain Key + :param int sequence: Sequence number for consecutive keys - Keys in Graphene are derived from a seed brain key which is a string of - 16 words out of a predefined dictionary with 49744 words. It is a - simple single-chain key derivation scheme that is not compatible with - BIP44 but easy to use. + Keys in Graphene are derived from a seed brain key which is a string of + 16 words out of a predefined dictionary with 49744 words. It is a + simple single-chain key derivation scheme that is not compatible with + BIP44 but easy to use. - Given the brain key, a private key is derived as:: + Given the brain key, a private key is derived as:: - privkey = SHA256(SHA512(brainkey + " " + sequence)) + privkey = SHA256(SHA512(brainkey + " " + sequence)) - Incrementing the sequence number yields a new key that can be - regenerated given the brain key. + Incrementing the sequence number yields a new key that can be + regenerated given the brain key. """ @@ -74,29 +74,29 @@ def __init__(self, brainkey=None, sequence=0, prefix=None): self.sequence = sequence def __next__(self): - """ Get the next private key (sequence number increment) for - iterators + """Get the next private key (sequence number increment) for + iterators """ return self.next_sequence() def next_sequence(self): - """ Increment the sequence number by 1 """ + """Increment the sequence number by 1""" self.sequence += 1 return self def normalize(self, brainkey): - """ Correct formating with single whitespace syntax and no trailing - space + """Correct formating with single whitespace syntax and no trailing + space """ return " ".join(re.compile("[\t\n\v\f\r ]+").split(brainkey)) def get_brainkey(self): - """ Return brain key of this instance """ + """Return brain key of this instance""" return self.normalize(self.brainkey) def get_private(self): - """ Derive private key from the brain key and the current sequence - number + """Derive private key from the brain key and the current sequence + number """ encoded = "%s %d" % (self.brainkey, self.sequence) a = _bytes(encoded) @@ -104,8 +104,7 @@ def get_private(self): return PrivateKey(hexlify(s).decode("ascii"), prefix=self.prefix) def get_blind_private(self): - """ Derive private key from the brain key (and no sequence number) - """ + """Derive private key from the brain key (and no sequence number)""" a = _bytes(self.brainkey) return PrivateKey(hashlib.sha256(a).hexdigest(), prefix=self.prefix) @@ -120,8 +119,8 @@ def get_public_key(self): @staticmethod def suggest(): - """ Suggest a new random brain key. Randomness is provided by the - operating system using ``os.urandom()``. + """Suggest a new random brain key. Randomness is provided by the + operating system using ``os.urandom()``. """ word_count = 16 brainkey = [None] * word_count @@ -129,24 +128,24 @@ def suggest(): assert len(dict_lines) == 49744 for j in range(0, word_count): num = int.from_bytes(os.urandom(2), byteorder="little") - rndMult = num / 2 ** 16 # returns float between 0..1 (inclusive) + rndMult = num / 2**16 # returns float between 0..1 (inclusive) wIdx = round(len(dict_lines) * rndMult) brainkey[j] = dict_lines[wIdx] return " ".join(brainkey).upper() class Address(Prefix): - """ Address class + """Address class - This class serves as an address representation for Public Keys. + This class serves as an address representation for Public Keys. - :param str address: Base58 encoded address (defaults to ``None``) - :param str pubkey: Base58 encoded pubkey (defaults to ``None``) - :param str prefix: Network prefix (defaults to ``GPH``) + :param str address: Base58 encoded address (defaults to ``None``) + :param str pubkey: Base58 encoded pubkey (defaults to ``None``) + :param str prefix: Network prefix (defaults to ``GPH``) - Example:: + Example:: - Address("GPHFN9r6VYzBK8EKtMewfNbfiGCr56pHDBFi") + Address("GPHFN9r6VYzBK8EKtMewfNbfiGCr56pHDBFi") """ @@ -156,9 +155,9 @@ def __init__(self, address, prefix=None): @classmethod def from_pubkey(cls, pubkey, compressed=True, version=56, prefix=None): - """ Load an address provided the public key. + """Load an address provided the public key. - Version: 56 => PTS + Version: 56 => PTS """ # Ensure this is a public key pubkey = PublicKey(pubkey, prefix=prefix or Prefix.prefix) @@ -174,31 +173,30 @@ def from_pubkey(cls, pubkey, compressed=True, version=56, prefix=None): return cls(result, prefix=pubkey.prefix) def __repr__(self): - """ Gives the hex representation of the ``GrapheneBase58CheckEncoded`` - Graphene address. + """Gives the hex representation of the ``GrapheneBase58CheckEncoded`` + Graphene address. """ return repr(self._address) def __str__(self): - """ Returns the readable Graphene address. This call is equivalent to - ``format(Address, "GPH")`` + """Returns the readable Graphene address. This call is equivalent to + ``format(Address, "GPH")`` """ return format(self._address, self.prefix) def __format__(self, _format): - """ May be issued to get valid "MUSE", "PLAY" or any other Graphene compatible - address with corresponding prefix. + """May be issued to get valid "MUSE", "PLAY" or any other Graphene compatible + address with corresponding prefix. """ return format(self._address, _format) def __bytes__(self): - """ Returns the raw content of the ``Base58CheckEncoded`` address """ + """Returns the raw content of the ``Base58CheckEncoded`` address""" return bytes(self._address) class GrapheneAddress(Address): - """ Graphene Addresses are different. Hence we have a different class - """ + """Graphene Addresses are different. Hence we have a different class""" @classmethod def from_pubkey(cls, pubkey, compressed=True, version=56, prefix=None): @@ -216,20 +214,20 @@ def from_pubkey(cls, pubkey, compressed=True, version=56, prefix=None): class PublicKey(Prefix): - """ This class deals with Public Keys and inherits ``Address``. + """This class deals with Public Keys and inherits ``Address``. - :param str pk: Base58 encoded public key - :param str prefix: Network prefix (defaults to ``GPH``) + :param str pk: Base58 encoded public key + :param str prefix: Network prefix (defaults to ``GPH``) - Example::: + Example::: - PublicKey("GPH6UtYWWs3rkZGV8JA86qrgkG6tyFksgECefKE1MiH4HkLD8PFGL") + PublicKey("GPH6UtYWWs3rkZGV8JA86qrgkG6tyFksgECefKE1MiH4HkLD8PFGL") - .. note:: By default, graphene-based networks deal with **compressed** - public keys. If an **uncompressed** key is required, the - method ``unCompressed`` can be used:: + .. note:: By default, graphene-based networks deal with **compressed** + public keys. If an **uncompressed** key is required, the + method ``unCompressed`` can be used:: - PublicKey("xxxxx").unCompressed() + PublicKey("xxxxx").unCompressed() """ @@ -259,7 +257,7 @@ def compressed_key(self): return PublicKey(self.compressed()) def _derive_y_from_x(self, x, is_even): - """ Derive y point from x point """ + """Derive y point from x point""" curve = ecdsa.SECP256k1.curve # The curve equation over F_p is: # y^2 = x^3 + ax + b @@ -271,11 +269,11 @@ def _derive_y_from_x(self, x, is_even): return beta def compressed(self): - """ returns the compressed key """ + """returns the compressed key""" return repr(self._pk) def uncompressed(self): - """ Derive uncompressed key """ + """Derive uncompressed key""" public_key = repr(self._pk) prefix = public_key[0:2] assert prefix == "02" or prefix == "03" @@ -285,27 +283,27 @@ def uncompressed(self): return key def point(self): - """ Return the point for the public key """ + """Return the point for the public key""" string = unhexlify(self.unCompressed()) return ecdsa.VerifyingKey.from_string( string[1:], curve=ecdsa.SECP256k1 ).pubkey.point def child(self, offset256): - """ Derive new public key from this key and a sha256 "offset" """ + """Derive new public key from this key and a sha256 "offset" """ a = bytes(self) + offset256 s = hashlib.sha256(a).digest() return self.add(s) def add(self, digest256): - """ Derive new public key from this key and a sha256 "digest" """ + """Derive new public key from this key and a sha256 "digest" """ from .ecdsa import tweakaddPubkey return tweakaddPubkey(self, digest256) @classmethod def from_privkey(cls, privkey, prefix=None): - """ Derive uncompressed public key """ + """Derive uncompressed public key""" privkey = PrivateKey(privkey, prefix=prefix or Prefix.prefix) secret = unhexlify(repr(privkey)) order = ecdsa.SigningKey.from_string( @@ -324,64 +322,63 @@ def from_privkey(cls, privkey, prefix=None): return cls(compressed, prefix=prefix or Prefix.prefix) def __repr__(self): - """ Gives the hex representation of the Graphene public key. """ + """Gives the hex representation of the Graphene public key.""" return repr(self._pk) def __str__(self): - """ Returns the readable Graphene public key. This call is equivalent to - ``format(PublicKey, "GPH")`` + """Returns the readable Graphene public key. This call is equivalent to + ``format(PublicKey, "GPH")`` """ return format(self._pk, self.prefix) def __format__(self, _format): - """ Formats the instance of:doc:`Base58 ` according to - ``_format`` + """Formats the instance of:doc:`Base58 ` according to + ``_format`` """ return format(self._pk, _format) def __bytes__(self): - """ Returns the raw public key (has length 33)""" + """Returns the raw public key (has length 33)""" return bytes(self._pk) def __lt__(self, other): - """ For sorting of public keys (due to graphene), - we actually sort according to addresses + """For sorting of public keys (due to graphene), + we actually sort according to addresses """ assert isinstance(other, PublicKey) return repr(self.address) < repr(other.address) def unCompressed(self): - """ Alias for self.uncompressed() - LEGACY""" + """Alias for self.uncompressed() - LEGACY""" return self.uncompressed() @property def address(self): - """ Obtain a GrapheneAddress from a public key - """ + """Obtain a GrapheneAddress from a public key""" return GrapheneAddress.from_pubkey(repr(self), prefix=self.prefix) class PrivateKey(Prefix): - """ Derives the compressed and uncompressed public keys and - constructs two instances of ``PublicKey``: + """Derives the compressed and uncompressed public keys and + constructs two instances of ``PublicKey``: - :param str wif: Base58check-encoded wif key - :param str prefix: Network prefix (defaults to ``GPH``) + :param str wif: Base58check-encoded wif key + :param str prefix: Network prefix (defaults to ``GPH``) - Example::: + Example::: - PrivateKey("5HqUkGuo62BfcJU5vNhTXKJRXuUi9QSE6jp8C3uBJ2BVHtB8WSd") + PrivateKey("5HqUkGuo62BfcJU5vNhTXKJRXuUi9QSE6jp8C3uBJ2BVHtB8WSd") - Compressed vs. Uncompressed: + Compressed vs. Uncompressed: - * ``PrivateKey("w-i-f").pubkey``: - Instance of ``PublicKey`` using compressed key. - * ``PrivateKey("w-i-f").pubkey.address``: - Instance of ``Address`` using compressed key. - * ``PrivateKey("w-i-f").uncompressed``: - Instance of ``PublicKey`` using uncompressed key. - * ``PrivateKey("w-i-f").uncompressed.address``: - Instance of ``Address`` using uncompressed key. + * ``PrivateKey("w-i-f").pubkey``: + Instance of ``PublicKey`` using compressed key. + * ``PrivateKey("w-i-f").pubkey.address``: + Instance of ``Address`` using compressed key. + * ``PrivateKey("w-i-f").uncompressed``: + Instance of ``PublicKey`` using uncompressed key. + * ``PrivateKey("w-i-f").uncompressed.address``: + Instance of ``Address`` using uncompressed key. """ @@ -422,13 +419,12 @@ def uncompressed(self): return PublicKey(self.pubkey.uncompressed(), prefix=self.prefix) def get_secret(self): - """ Get sha256 digest of the wif key. - """ + """Get sha256 digest of the wif key.""" return hashlib.sha256(bytes(self)).digest() def derive_private_key(self, sequence): - """ Derive new private key from this private key and an arbitrary - sequence number + """Derive new private key from this private key and an arbitrary + sequence number """ encoded = "%s %d" % (str(self), sequence) a = bytes(encoded, "ascii") @@ -436,16 +432,15 @@ def derive_private_key(self, sequence): return PrivateKey(hexlify(s).decode("ascii"), prefix=self.pubkey.prefix) def child(self, offset256): - """ Derive new private key from this key and a sha256 "offset" - """ + """Derive new private key from this key and a sha256 "offset" """ a = bytes(self.pubkey) + offset256 s = hashlib.sha256(a).digest() return self.derive_from_seed(s) def derive_from_seed(self, offset): - """ Derive private key using "generate_from_seed" method. - Here, the key itself serves as a `seed`, and `offset` - is expected to be a sha256 digest. + """Derive private key using "generate_from_seed" method. + Here, the key itself serves as a `seed`, and `offset` + is expected to be a sha256 digest. """ seed = int(hexlify(bytes(self)).decode("ascii"), 16) z = int(hexlify(offset).decode("ascii"), 16) @@ -457,23 +452,23 @@ def derive_from_seed(self, offset): return PrivateKey(secret, prefix=self.pubkey.prefix) def __format__(self, _format): - """ Formats the instance of:doc:`Base58 ` according to - ``_format`` + """Formats the instance of:doc:`Base58 ` according to + ``_format`` """ return format(self._wif, _format) def __repr__(self): - """ Gives the hex representation of the Graphene private key.""" + """Gives the hex representation of the Graphene private key.""" return repr(self._wif) def __str__(self): - """ Returns the readable (uncompressed wif format) Graphene private key. This - call is equivalent to ``format(PrivateKey, "WIF")`` + """Returns the readable (uncompressed wif format) Graphene private key. This + call is equivalent to ``format(PrivateKey, "WIF")`` """ return format(self._wif, "WIF") def __bytes__(self): # pragma: no cover - """ Returns the raw private key """ + """Returns the raw private key""" return bytes(self._wif) @@ -492,8 +487,8 @@ def from_pubkey(cls, pubkey, compressed=False, version=56, prefix=None): return cls(hexlify(addressbin).decode("ascii")) def __str__(self): - """ Returns the readable Graphene address. This call is equivalent to - ``format(Address, "GPH")`` + """Returns the readable Graphene address. This call is equivalent to + ``format(Address, "GPH")`` """ return format(self._address, "BTC") diff --git a/graphenebase/base58.py b/graphenebase/base58.py index 188467cd..4de6ffef 100644 --- a/graphenebase/base58.py +++ b/graphenebase/base58.py @@ -54,11 +54,11 @@ def __init__(self, data, prefix=None): raise ValueError("Error loading Base58 object: {}".format(data)) def __format__(self, _format): - """ Format output according to argument _format (wif,...) + """Format output according to argument _format (wif,...) - :param str _format: Format to use - :return: formatted data according to _format - :rtype: str + :param str _format: Format to use + :return: formatted data according to _format + :rtype: str """ if _format.upper() == "WIF": @@ -71,26 +71,26 @@ def __format__(self, _format): return _format.upper() + str(self) def __repr__(self): - """ Returns hex value of object + """Returns hex value of object - :return: Hex string of instance's data - :rtype: hex string + :return: Hex string of instance's data + :rtype: hex string """ return self._hex def __str__(self): - """ Return graphene-base58CheckEncoded string of data + """Return graphene-base58CheckEncoded string of data - :return: Base58 encoded data - :rtype: str + :return: Base58 encoded data + :rtype: str """ return gphBase58CheckEncode(self._hex) def __bytes__(self): - """ Return raw bytes + """Return raw bytes - :return: Raw bytes of instance - :rtype: bytes + :return: Raw bytes of instance + :rtype: bytes """ return unhexlify(self._hex) diff --git a/graphenebase/bip38.py b/graphenebase/bip38.py index 6b112600..bdd62483 100644 --- a/graphenebase/bip38.py +++ b/graphenebase/bip38.py @@ -38,13 +38,13 @@ class SaltException(Exception): def _encrypt_xor(a, b, aes): - """ Returns encrypt(a ^ b). """ + """Returns encrypt(a ^ b).""" a = unhexlify("%0.32x" % (int((a), 16) ^ int(hexlify(b), 16))) return aes.encrypt(a) def encrypt(privkey, passphrase): - """ BIP0038 non-ec-multiply encryption. Returns BIP0038 encrypted privkey. + """BIP0038 non-ec-multiply encryption. Returns BIP0038 encrypted privkey. :param privkey: Private key :type privkey: Base58 diff --git a/graphenebase/ecdsa.py b/graphenebase/ecdsa.py index 9af83d98..54615004 100644 --- a/graphenebase/ecdsa.py +++ b/graphenebase/ecdsa.py @@ -78,8 +78,7 @@ def compressedPubkey(pk): def recover_public_key(digest, signature, i, message=None): - """ Recover the public key from the the signature - """ + """Recover the public key from the the signature""" # See http: //www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6 primarily curve = ecdsa.SECP256k1.curve @@ -124,8 +123,8 @@ def recover_public_key(digest, signature, i, message=None): def recoverPubkeyParameter(message, digest, signature, pubkey): - """ Use to derive a number that allows to easily recover the - public key from the signature + """Use to derive a number that allows to easily recover the + public key from the signature """ if not isinstance(message, bytes): message = bytes(message, "utf-8") # pragma: no cover @@ -154,9 +153,9 @@ def recoverPubkeyParameter(message, digest, signature, pubkey): def sign_message(message, wif, hashfn=hashlib.sha256): - """ Sign a digest with a wif key + """Sign a digest with a wif key - :param str wif: Private key in + :param str wif: Private key in """ if not isinstance(message, bytes): diff --git a/graphenebase/memo.py b/graphenebase/memo.py index 692b1abb..9c7ced0d 100644 --- a/graphenebase/memo.py +++ b/graphenebase/memo.py @@ -16,16 +16,16 @@ def get_shared_secret(priv, pub): - """ Derive the share secret between ``priv`` and ``pub`` + """Derive the share secret between ``priv`` and ``pub`` - :param `Base58` priv: Private Key - :param `Base58` pub: Public Key - :return: Shared secret - :rtype: hex + :param `Base58` priv: Private Key + :param `Base58` pub: Public Key + :return: Shared secret + :rtype: hex - The shared secret is generated such that:: + The shared secret is generated such that:: - Pub(Alice) * Priv(Bob) = Pub(Bob) * Priv(Alice) + Pub(Alice) * Priv(Bob) = Pub(Bob) * Priv(Alice) """ pub_point = pub.point() @@ -38,12 +38,12 @@ def get_shared_secret(priv, pub): def init_aes(shared_secret, nonce): - """ Initialize AES instance + """Initialize AES instance - :param hex shared_secret: Shared Secret to use as encryption key - :param int nonce: Random nonce - :return: AES instance - :rtype: AES + :param hex shared_secret: Shared Secret to use as encryption key + :param int nonce: Random nonce + :return: AES instance + :rtype: AES """ " Shared Secret " @@ -70,14 +70,14 @@ def _unpad(s, BS): def encode_memo(priv, pub, nonce, message): - """ Encode a message with a shared secret between Alice and Bob + """Encode a message with a shared secret between Alice and Bob - :param PrivateKey priv: Private Key (of Alice) - :param PublicKey pub: Public Key (of Bob) - :param int nonce: Random nonce - :param str message: Memo message - :return: Encrypted message - :rtype: hex + :param PrivateKey priv: Private Key (of Alice) + :param PublicKey pub: Public Key (of Bob) + :param int nonce: Random nonce + :param str message: Memo message + :return: Encrypted message + :rtype: hex """ shared_secret = get_shared_secret(priv, pub) @@ -93,16 +93,16 @@ def encode_memo(priv, pub, nonce, message): def decode_memo(priv, pub, nonce, message): - """ Decode a message with a shared secret between Alice and Bob - - :param PrivateKey priv: Private Key (of Bob) - :param PublicKey pub: Public Key (of Alice) - :param int nonce: Nonce used for Encryption - :param bytes message: Encrypted Memo message - :return: Decrypted message - :rtype: str - :raise ValueError: if message cannot be decoded as valid UTF-8 - string + """Decode a message with a shared secret between Alice and Bob + + :param PrivateKey priv: Private Key (of Bob) + :param PublicKey pub: Public Key (of Alice) + :param int nonce: Nonce used for Encryption + :param bytes message: Encrypted Memo message + :return: Decrypted message + :rtype: str + :raise ValueError: if message cannot be decoded as valid UTF-8 + string """ shared_secret = get_shared_secret(priv, pub) diff --git a/graphenebase/objects.py b/graphenebase/objects.py index fac67fc2..1d9899c6 100644 --- a/graphenebase/objects.py +++ b/graphenebase/objects.py @@ -35,9 +35,9 @@ class Operation(list): - """ The superclass for an operation. This class i used to instanciate an - operation, identify the operationid/name and serialize the operation - into bytes. + """The superclass for an operation. This class i used to instanciate an + operation, identify the operationid/name and serialize the operation + into bytes. """ module = "graphenebase.operations" @@ -145,8 +145,7 @@ def getOperationIdForName(self, name): return self.ops[name] def getOperationNameForId(self, i): - """ Convert an operation id into the corresponding string - """ + """Convert an operation id into the corresponding string""" for key in self.ops: if int(self.ops[key]) is int(i): return key @@ -157,13 +156,13 @@ def getOperationNameForId(self, i): class GrapheneObject(OrderedDict): - """ Core abstraction class + """Core abstraction class - This class is used for any JSON reflected object in Graphene. + This class is used for any JSON reflected object in Graphene. - * ``instance.__json__()``: encodes data into json format - * ``bytes(instance)``: encodes data into wire format - * ``str(instances)``: dumps json object as string + * ``instance.__json__()``: encodes data into json format + * ``bytes(instance)``: encodes data into wire format + * ``str(instances)``: dumps json object as string """ @@ -224,14 +223,12 @@ def __str__(self): # Legacy support @property def data(self): # pragma: no cover - """ Read data explicitly (backwards compatibility) - """ + """Read data explicitly (backwards compatibility)""" return self @data.setter def data(self, data): # pragma: no cover - """ Set data through a setter (backwards compatibility) - """ + """Set data through a setter (backwards compatibility)""" self.update(data) toJson = __json__ diff --git a/graphenebase/operationids.py b/graphenebase/operationids.py index 5772851c..eb563b58 100644 --- a/graphenebase/operationids.py +++ b/graphenebase/operationids.py @@ -12,8 +12,7 @@ def getOperationNameForId(i: int): - """ Convert an operation id into the corresponding string - """ + """Convert an operation id into the corresponding string""" assert isinstance(i, (int)), "This method expects an integer argument" for key in operations: if int(operations[key]) is int(i): @@ -22,8 +21,8 @@ def getOperationNameForId(i: int): def getOperationName(id: str): - """ This method returns the name representation of an operation given - its value as used in the API + """This method returns the name representation of an operation given + its value as used in the API """ if isinstance(id, str): # Some graphene chains (e.g. steem) do not encode the diff --git a/graphenebase/prefix.py b/graphenebase/prefix.py index 6e218d90..6739bb62 100644 --- a/graphenebase/prefix.py +++ b/graphenebase/prefix.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- class Prefix: - """ This class is meant to allow changing the prefix. - The prefix is used to link a public key to a specific blockchain. + """This class is meant to allow changing the prefix. + The prefix is used to link a public key to a specific blockchain. """ prefix = "GPH" diff --git a/graphenebase/signedtransactions.py b/graphenebase/signedtransactions.py index aeee9775..9013cbbc 100644 --- a/graphenebase/signedtransactions.py +++ b/graphenebase/signedtransactions.py @@ -31,14 +31,14 @@ class MissingSignatureForKey(Exception): class Signed_Transaction(GrapheneObject): - """ Create a signed transaction and offer method to create the - signature - - :param num refNum: parameter ref_block_num (see ``getBlockParams``) - :param num refPrefix: parameter ref_block_prefix (see - ``getBlockParams``) - :param str expiration: expiration date - :param Array operations: array of operations + """Create a signed transaction and offer method to create the + signature + + :param num refNum: parameter ref_block_num (see ``getBlockParams``) + :param num refPrefix: parameter ref_block_prefix (see + ``getBlockParams``) + :param str expiration: expiration date + :param Array operations: array of operations """ known_chains = known_chains @@ -82,8 +82,7 @@ def getOperationKlass(self): @property def id(self): - """ The transaction id of this transaction - """ + """The transaction id of this transaction""" # Store signatures temporarily since they are not part of # transaction id sigs = self.data["signatures"] @@ -177,10 +176,10 @@ def verify(self, pubkeys=[], chain=None): return pubKeysFound def sign(self, wifkeys, chain=None): - """ Sign the transaction with the provided private keys. + """Sign the transaction with the provided private keys. - :param array wifkeys: Array of wif keys - :param str chain: identifier for the chain + :param array wifkeys: Array of wif keys + :param str chain: identifier for the chain """ if not chain: diff --git a/graphenebase/transactions.py b/graphenebase/transactions.py index 6adeaba8..7e993c7c 100644 --- a/graphenebase/transactions.py +++ b/graphenebase/transactions.py @@ -17,9 +17,9 @@ def getBlockParams(ws, use_head_block=False): - """ Auxiliary method to obtain ``ref_block_num`` and - ``ref_block_prefix``. Requires a websocket connection to a - witness node! + """Auxiliary method to obtain ``ref_block_num`` and + ``ref_block_prefix``. Requires a websocket connection to a + witness node! """ raise DeprecationWarning( "This method shouldn't be called anymore. It is part of " @@ -28,11 +28,11 @@ def getBlockParams(ws, use_head_block=False): def formatTimeFromNow(secs=0): - """ Properly Format Time that is `x` seconds in the future + """Properly Format Time that is `x` seconds in the future - :param int secs: Seconds to go in the future (`x>0`) or the past (`x<0`) - :return: Properly formated time for Graphene (`%Y-%m-%dT%H:%M:%S`) - :rtype: str + :param int secs: Seconds to go in the future (`x>0`) or the past (`x<0`) + :return: Properly formated time for Graphene (`%Y-%m-%dT%H:%M:%S`) + :rtype: str """ return datetime.utcfromtimestamp(time.time() + int(secs)).strftime(timeformat) diff --git a/graphenebase/types.py b/graphenebase/types.py index d19d7264..55bcc355 100644 --- a/graphenebase/types.py +++ b/graphenebase/types.py @@ -11,8 +11,7 @@ def varint(n): - """ Varint encoding - """ + """Varint encoding""" data = b"" while n >= 0x80: data += bytes([(n & 0x7F) | 0x80]) @@ -22,8 +21,7 @@ def varint(n): def varintdecode(data): # pragma: no cover - """ Varint decoding - """ + """Varint decoding""" shift = 0 result = 0 for b in bytes(data): @@ -35,13 +33,12 @@ def varintdecode(data): # pragma: no cover def variable_buffer(s): - """ Encode variable length buffer - """ + """Encode variable length buffer""" return varint(len(s)) + s def JsonObj(data): - """ Return json object from data + """Return json object from data If data has a __json__() method, use that, else assume it follows the convention that its string representation is interprettable as valid json. @@ -359,8 +356,7 @@ def __str__(self): class ObjectId: - """ Encodes protocol ids - serializes to the *instance* only! - """ + """Encodes protocol ids - serializes to the *instance* only!""" object_types = object_type @@ -391,8 +387,7 @@ def __str__(self): class FullObjectId: - """ Encodes object ids - serializes to a full object id - """ + """Encodes object ids - serializes to a full object id""" def __init__(self, object_str): if len(object_str.split(".")) == 3: diff --git a/graphenebase/utils.py b/graphenebase/utils.py index c2a3d80f..a587ce89 100644 --- a/graphenebase/utils.py +++ b/graphenebase/utils.py @@ -7,8 +7,7 @@ def _bytes(x): # pragma: no branch - """ Python3 and Python2 compatibility - """ + """Python3 and Python2 compatibility""" if sys.version > "3": return bytes(x, "utf8") else: # pragma: no cover @@ -37,8 +36,7 @@ def unicodify(data): def formatTime(t): - """ Properly Format Time for permlinks - """ + """Properly Format Time for permlinks""" if isinstance(t, (float, int)): return datetime.utcfromtimestamp(t).strftime(timeFormat) elif isinstance(t, datetime): @@ -48,12 +46,12 @@ def formatTime(t): def formatTimeFromNow(secs=0): - """ Properly Format Time that is `x` seconds in the future + """Properly Format Time that is `x` seconds in the future - :param int secs: Seconds to go in the future (`x>0`) or the - past (`x<0`) - :return: Properly formated time for Graphene (`%Y-%m-%dT%H:%M:%S`) - :rtype: str + :param int secs: Seconds to go in the future (`x>0`) or the + past (`x<0`) + :return: Properly formated time for Graphene (`%Y-%m-%dT%H:%M:%S`) + :rtype: str """ return datetime.utcfromtimestamp(time.time() + int(secs)).strftime(timeFormat) @@ -61,7 +59,7 @@ def formatTimeFromNow(secs=0): def parse_time(block_time): """Take a string representation of time from the blockchain, and parse it - into datetime object. + into datetime object. """ return datetime.strptime(block_time, timeFormat).replace(tzinfo=timezone.utc) diff --git a/graphenecommon/account.py b/graphenecommon/account.py index 8baf8a51..14ff243d 100644 --- a/graphenecommon/account.py +++ b/graphenecommon/account.py @@ -10,32 +10,32 @@ class Account(BlockchainObject, AbstractBlockchainInstanceProvider): - """ This class allows to easily access Account data + """This class allows to easily access Account data - :param str account_name: Name of the account - :param instance blockchain_instance: instance to use when accesing a RPC - :param bool full: Obtain all account data including orders, positions, etc. - :param bool lazy: Use lazy loading - :param bool full: Obtain all account data including orders, positions, - etc. - :returns: Account data - :rtype: dictionary - :raises .exceptions.AccountDoesNotExistsException: if account - does not exist + :param str account_name: Name of the account + :param instance blockchain_instance: instance to use when accesing a RPC + :param bool full: Obtain all account data including orders, positions, etc. + :param bool lazy: Use lazy loading + :param bool full: Obtain all account data including orders, positions, + etc. + :returns: Account data + :rtype: dictionary + :raises .exceptions.AccountDoesNotExistsException: if account + does not exist - Instances of this class are dictionaries that come with additional - methods (see below) that allow dealing with an account and it's - corresponding functions. + Instances of this class are dictionaries that come with additional + methods (see below) that allow dealing with an account and it's + corresponding functions. - .. code-block:: python + .. code-block:: python - from .account import Account - account = Account("init0") - print(account) + from .account import Account + account = Account("init0") + print(account) - .. note:: This class comes with its own caching function to reduce the - load on the API server. Instances of this class can be - refreshed with ``Account.refresh()``. + .. note:: This class comes with its own caching function to reduce the + load on the API server. Instances of this class can be + refreshed with ``Account.refresh()``. """ @@ -49,8 +49,7 @@ def __init__(self, *args, **kwargs): BlockchainObject.__init__(self, *args, **kwargs) def refresh(self): - """ Refresh/Obtain an account's data from the API server - """ + """Refresh/Obtain an account's data from the API server""" import re if re.match(r"^1\.2\.[0-9]*$", self.identifier): @@ -83,8 +82,7 @@ def name(self): @property def is_fully_loaded(self): # pragma: no cover - """ Is this instance fully loaded / e.g. all data available? - """ + """Is this instance fully loaded / e.g. all data available?""" return self.full and "votes" in self def ensure_full(self): # pragma: no cover @@ -94,14 +92,13 @@ def ensure_full(self): # pragma: no cover @property def is_ltm(self): - """ Is the account a lifetime member (LTM)? - """ + """Is the account a lifetime member (LTM)?""" return self.get("id") == self.get("lifetime_referrer") @property def balances(self): - """ List balances of an account. This call returns instances of - :class:`amount.Amount`. + """List balances of an account. This call returns instances of + :class:`amount.Amount`. """ balances = self.blockchain.rpc.get_account_balances(self["id"], []) return [ @@ -111,8 +108,8 @@ def balances(self): ] def balance(self, symbol): - """ Obtain the balance of a specific Asset. This call returns instances of - :class:`amount.Amount`. + """Obtain the balance of a specific Asset. This call returns instances of + :class:`amount.Amount`. """ if isinstance(symbol, dict) and "symbol" in symbol: symbol = symbol["symbol"] @@ -123,26 +120,26 @@ def balance(self, symbol): return self.amount_class(0, symbol, blockchain_instance=self.blockchain) def history(self, first=0, last=0, limit=-1, only_ops=[], exclude_ops=[]): - """ Returns a generator for individual account transactions. The - latest operation will be first. This call can be used in a - ``for`` loop. - - :param int first: sequence number of the first - transaction to return (*optional*) - :param int last: sequence number of the last - transaction to return (*optional*) - :param int limit: limit number of transactions to - return (*optional*) - :param array only_ops: Limit generator by these - operations (*optional*) - :param array exclude_ops: Exclude these operations from - generator (*optional*). - - ... note:: - only_ops and exclude_ops takes an array of strings: - The full list of operation ID's can be found in - operationids.py. - Example: ['transfer', 'fill_order'] + """Returns a generator for individual account transactions. The + latest operation will be first. This call can be used in a + ``for`` loop. + + :param int first: sequence number of the first + transaction to return (*optional*) + :param int last: sequence number of the last + transaction to return (*optional*) + :param int limit: limit number of transactions to + return (*optional*) + :param array only_ops: Limit generator by these + operations (*optional*) + :param array exclude_ops: Exclude these operations from + generator (*optional*). + + ... note:: + only_ops and exclude_ops takes an array of strings: + The full list of operation ID's can be found in + operationids.py. + Example: ['transfer', 'fill_order'] """ _limit = 100 cnt = 0 @@ -183,47 +180,43 @@ def history(self, first=0, last=0, limit=-1, only_ops=[], exclude_ops=[]): first = int(txs[-1]["id"].split(".")[2]) def upgrade(self): # pragma: no cover - """ Upgrade account to life time member - """ + """Upgrade account to life time member""" assert callable(self.blockchain.upgrade_account) return self.blockchain.upgrade_account(account=self) def whitelist(self, account): # pragma: no cover - """ Add an other account to the whitelist of this account - """ + """Add an other account to the whitelist of this account""" assert callable(self.blockchain.account_whitelist) return self.blockchain.account_whitelist(account, lists=["white"], account=self) def blacklist(self, account): # pragma: no cover - """ Add an other account to the blacklist of this account - """ + """Add an other account to the blacklist of this account""" assert callable(self.blockchain.account_whitelist) return self.blockchain.account_whitelist(account, lists=["black"], account=self) def nolist(self, account): # pragma: no cover - """ Remove an other account from any list of this account - """ + """Remove an other account from any list of this account""" assert callable(self.blockchain.account_whitelist) return self.blockchain.account_whitelist(account, lists=[], account=self) class AccountUpdate(dict, AbstractBlockchainInstanceProvider): - """ This purpose of this class is to keep track of account updates - as they are pushed through by :class:`notify.Notify`. + """This purpose of this class is to keep track of account updates + as they are pushed through by :class:`notify.Notify`. - Instances of this class are dictionaries and take the following - form: + Instances of this class are dictionaries and take the following + form: - ... code-block: js + ... code-block: js - {'id': '2.6.29', - 'lifetime_fees_paid': '44261516129', - 'most_recent_op': '2.9.0', - 'owner': '1.2.29', - 'pending_fees': 0, - 'pending_vested_fees': 16310, - 'total_core_in_orders': '6788845277634', - 'total_ops': 0} + {'id': '2.6.29', + 'lifetime_fees_paid': '44261516129', + 'most_recent_op': '2.9.0', + 'owner': '1.2.29', + 'pending_fees': 0, + 'pending_vested_fees': 16310, + 'total_core_in_orders': '6788845277634', + 'total_ops': 0} """ @@ -241,9 +234,9 @@ def __init__(self, data, *args, **kwargs): @property def account(self): - """ In oder to obtain the actual - :class:`account.Account` from this class, you can - use the ``account`` attribute. + """In oder to obtain the actual + :class:`account.Account` from this class, you can + use the ``account`` attribute. """ account = self.account_class(self["owner"], blockchain_instance=self.blockchain) # account.refresh() diff --git a/graphenecommon/aio/account.py b/graphenecommon/aio/account.py index 10dd9a05..d80cb2d6 100644 --- a/graphenecommon/aio/account.py +++ b/graphenecommon/aio/account.py @@ -12,32 +12,32 @@ class Account(BlockchainObject, SyncAccount): - """ This class allows to easily access Account data + """This class allows to easily access Account data - :param str account_name: Name of the account - :param instance blockchain_instance: instance to use when accesing a RPC - :param bool full: Obtain all account data including orders, positions, etc. - :param bool lazy: Use lazy loading - :param bool full: Obtain all account data including orders, positions, - etc. - :returns: Account data - :rtype: dictionary - :raises .exceptions.AccountDoesNotExistsException: if account - does not exist + :param str account_name: Name of the account + :param instance blockchain_instance: instance to use when accesing a RPC + :param bool full: Obtain all account data including orders, positions, etc. + :param bool lazy: Use lazy loading + :param bool full: Obtain all account data including orders, positions, + etc. + :returns: Account data + :rtype: dictionary + :raises .exceptions.AccountDoesNotExistsException: if account + does not exist - Instances of this class are dictionaries that come with additional - methods (see below) that allow dealing with an account and it's - corresponding functions. + Instances of this class are dictionaries that come with additional + methods (see below) that allow dealing with an account and it's + corresponding functions. - .. code-block:: python + .. code-block:: python - from aio.account import Account - account = await Account("init0") - print(account) + from aio.account import Account + account = await Account("init0") + print(account) - .. note:: This class comes with its own caching function to reduce the - load on the API server. Instances of this class can be - refreshed with ``await Account.refresh()``. + .. note:: This class comes with its own caching function to reduce the + load on the API server. Instances of this class can be + refreshed with ``await Account.refresh()``. """ @@ -51,8 +51,7 @@ async def __init__(self, *args, **kwargs): await BlockchainObject.__init__(self, *args, **kwargs) async def refresh(self): - """ Refresh/Obtain an account's data from the API server - """ + """Refresh/Obtain an account's data from the API server""" import re if re.match(r"^1\.2\.[0-9]*$", self.identifier): @@ -92,8 +91,8 @@ async def ensure_full(self): # pragma: no cover @property async def balances(self): - """ List balances of an account. This call returns instances of - :class:`amount.Amount`. + """List balances of an account. This call returns instances of + :class:`amount.Amount`. """ balances = await self.blockchain.rpc.get_account_balances(self["id"], []) return [ @@ -103,8 +102,8 @@ async def balances(self): ] async def balance(self, symbol): - """ Obtain the balance of a specific Asset. This call returns instances of - :class:`amount.Amount`. + """Obtain the balance of a specific Asset. This call returns instances of + :class:`amount.Amount`. """ if isinstance(symbol, dict) and "symbol" in symbol: symbol = symbol["symbol"] @@ -115,26 +114,26 @@ async def balance(self, symbol): return await self.amount_class(0, symbol, blockchain_instance=self.blockchain) async def history(self, first=0, last=0, limit=-1, only_ops=[], exclude_ops=[]): - """ Returns a generator for individual account transactions. The - latest operation will be first. This call can be used in a - ``for`` loop. - - :param int first: sequence number of the first - transaction to return (*optional*) - :param int last: sequence number of the last - transaction to return (*optional*) - :param int limit: limit number of transactions to - return (*optional*) - :param array only_ops: Limit generator by these - operations (*optional*) - :param array exclude_ops: Exclude these operations from - generator (*optional*). - - ... note:: - only_ops and exclude_ops takes an array of strings: - The full list of operation ID's can be found in - operationids.py. - Example: ['transfer', 'fill_order'] + """Returns a generator for individual account transactions. The + latest operation will be first. This call can be used in a + ``for`` loop. + + :param int first: sequence number of the first + transaction to return (*optional*) + :param int last: sequence number of the last + transaction to return (*optional*) + :param int limit: limit number of transactions to + return (*optional*) + :param array only_ops: Limit generator by these + operations (*optional*) + :param array exclude_ops: Exclude these operations from + generator (*optional*). + + ... note:: + only_ops and exclude_ops takes an array of strings: + The full list of operation ID's can be found in + operationids.py. + Example: ['transfer', 'fill_order'] """ _limit = 100 cnt = 0 @@ -175,52 +174,48 @@ async def history(self, first=0, last=0, limit=-1, only_ops=[], exclude_ops=[]): first = int(txs[-1]["id"].split(".")[2]) async def upgrade(self): # pragma: no cover - """ Upgrade account to life time member - """ + """Upgrade account to life time member""" assert callable(self.blockchain.upgrade_account) return await self.blockchain.upgrade_account(account=self) async def whitelist(self, account): # pragma: no cover - """ Add an other account to the whitelist of this account - """ + """Add an other account to the whitelist of this account""" assert callable(self.blockchain.account_whitelist) return await self.blockchain.account_whitelist( account, lists=["white"], account=self ) async def blacklist(self, account): # pragma: no cover - """ Add an other account to the blacklist of this account - """ + """Add an other account to the blacklist of this account""" assert callable(self.blockchain.account_whitelist) return await self.blockchain.account_whitelist( account, lists=["black"], account=self ) async def nolist(self, account): # pragma: no cover - """ Remove an other account from any list of this account - """ + """Remove an other account from any list of this account""" assert callable(self.blockchain.account_whitelist) return await self.blockchain.account_whitelist(account, lists=[], account=self) @asyncinit class AccountUpdate(SyncAccountUpdate): - """ This purpose of this class is to keep track of account updates - as they are pushed through by :class:`notify.Notify`. + """This purpose of this class is to keep track of account updates + as they are pushed through by :class:`notify.Notify`. - Instances of this class are dictionaries and take the following - form: + Instances of this class are dictionaries and take the following + form: - ... code-block: js + ... code-block: js - {'id': '2.6.29', - 'lifetime_fees_paid': '44261516129', - 'most_recent_op': '2.9.0', - 'owner': '1.2.29', - 'pending_fees': 0, - 'pending_vested_fees': 16310, - 'total_core_in_orders': '6788845277634', - 'total_ops': 0} + {'id': '2.6.29', + 'lifetime_fees_paid': '44261516129', + 'most_recent_op': '2.9.0', + 'owner': '1.2.29', + 'pending_fees': 0, + 'pending_vested_fees': 16310, + 'total_core_in_orders': '6788845277634', + 'total_ops': 0} """ @@ -241,9 +236,9 @@ async def __init__(self, data, *args, **kwargs): @property async def account(self): - """ In oder to obtain the actual - :class:`account.Account` from this class, you can - use the ``account`` attribute. + """In oder to obtain the actual + :class:`account.Account` from this class, you can + use the ``account`` attribute. """ account = await self.account_class( self["owner"], blockchain_instance=self.blockchain diff --git a/graphenecommon/aio/amount.py b/graphenecommon/aio/amount.py index fd01a2f4..32f79dcc 100644 --- a/graphenecommon/aio/amount.py +++ b/graphenecommon/aio/amount.py @@ -8,9 +8,9 @@ @asyncinit class Amount(SyncAmount): async def __init__(self, *args, **kwargs): - """ Async version of :class:`..amount.Amount` + """Async version of :class:`..amount.Amount` - Limitations: most of arithmetic operations are not supported on async version + Limitations: most of arithmetic operations are not supported on async version """ self.define_classes() assert self.asset_class @@ -92,8 +92,7 @@ async def __init__(self, *args, **kwargs): self["amount"] = float(self.get("amount", 0.0)) async def copy(self): - """ Copy the instance and make sure not to use a reference - """ + """Copy the instance and make sure not to use a reference""" return await self.__class__( amount=self["amount"], asset=self["asset"].copy(), @@ -102,8 +101,7 @@ async def copy(self): @property async def asset(self): - """ Returns the asset as instance of :class:`.asset.Asset` - """ + """Returns the asset as instance of :class:`.asset.Asset`""" if not self["asset"]: self["asset"] = await self.asset_class( self["symbol"], blockchain_instance=self.blockchain diff --git a/graphenecommon/aio/asset.py b/graphenecommon/aio/asset.py index 53aee0a4..f9b3ae86 100644 --- a/graphenecommon/aio/asset.py +++ b/graphenecommon/aio/asset.py @@ -5,17 +5,17 @@ class Asset(BlockchainObject, SyncAsset): - """ Deals with Assets of the network. + """Deals with Assets of the network. - :param str Asset: Symbol name or object id of an asset - :param bool full: Also obtain bitasset-data and dynamic asset data - :param instance blockchain_instance: instance to use when accesing a RPC - :returns: All data of an asset - :rtype: dict + :param str Asset: Symbol name or object id of an asset + :param bool full: Also obtain bitasset-data and dynamic asset data + :param instance blockchain_instance: instance to use when accesing a RPC + :returns: All data of an asset + :rtype: dict - .. note:: This class comes with its own caching function to reduce the - load on the API server. Instances of this class can be - refreshed with ``await Asset.refresh()``. + .. note:: This class comes with its own caching function to reduce the + load on the API server. Instances of this class can be + refreshed with ``await Asset.refresh()``. """ async def __init__(self, *args, **kwargs): @@ -26,8 +26,7 @@ async def __init__(self, *args, **kwargs): await BlockchainObject.__init__(self, *args, **kwargs) async def refresh(self): - """ Refresh the data from the API server - """ + """Refresh the data from the API server""" asset = await self.blockchain.rpc.get_asset(self.identifier) if not asset: raise AssetDoesNotExistsException(self.identifier) @@ -47,8 +46,7 @@ async def ensure_full(self): await self.refresh() async def update_cer(self, cer, account=None, **kwargs): - """ Update the Core Exchange Rate (CER) of an asset - """ + """Update the Core Exchange Rate (CER) of an asset""" assert callable(self.blockchain.update_cer) return await self.blockchain.update_cer( self["symbol"], cer, account=account, **kwargs diff --git a/graphenecommon/aio/block.py b/graphenecommon/aio/block.py index 709cc4a9..7f1bb047 100644 --- a/graphenecommon/aio/block.py +++ b/graphenecommon/aio/block.py @@ -5,22 +5,22 @@ class Block(BlockchainObject, SyncBlock): - """ Read a single block from the chain + """Read a single block from the chain - :param int block: block number - :param instance blockchain_instance: instance to use when accesing a RPC - :param bool lazy: Use lazy loading - :param loop: asyncio event loop + :param int block: block number + :param instance blockchain_instance: instance to use when accesing a RPC + :param bool lazy: Use lazy loading + :param loop: asyncio event loop - Instances of this class are dictionaries that come with additional - methods (see below) that allow dealing with a block and it's - corresponding functions. + Instances of this class are dictionaries that come with additional + methods (see below) that allow dealing with a block and it's + corresponding functions. - .. code-block:: python + .. code-block:: python - from aio.block import Block - block = await Block(1) - print(block) + from aio.block import Block + block = await Block(1) + print(block) """ async def __init__(self, *args, use_cache=False, **kwargs): @@ -31,8 +31,8 @@ async def __init__(self, *args, use_cache=False, **kwargs): await BlockchainObject.__init__(self, *args, **kwargs) async def refresh(self): - """ Even though blocks never change, you freshly obtain its contents - from an API with this method + """Even though blocks never change, you freshly obtain its contents + from an API with this method """ block = await self.blockchain.rpc.get_block(self.identifier) if not block: @@ -51,8 +51,8 @@ async def __init__(self, *args, use_cache=False, **kwargs): await BlockchainObject.__init__(self, *args, **kwargs) async def refresh(self): - """ Even though blocks never change, you freshly obtain its contents - from an API with this method + """Even though blocks never change, you freshly obtain its contents + from an API with this method """ block = await self.blockchain.rpc.get_block_header(self.identifier) if not block: diff --git a/graphenecommon/aio/blockchain.py b/graphenecommon/aio/blockchain.py index be844e9f..7ffcb158 100644 --- a/graphenecommon/aio/blockchain.py +++ b/graphenecommon/aio/blockchain.py @@ -6,16 +6,16 @@ @asyncinit class Blockchain(SyncBlockchain): - """ This class allows to access the blockchain and read data - from it + """This class allows to access the blockchain and read data + from it - :param instance blockchain_instance: instance to use when accesing a RPC - :param str mode: (default) Irreversible block (``irreversible``) or - actual head block (``head``) - :param int max_block_wait_repetition: (default) 3 maximum wait time for - next block ismax_block_wait_repetition * block_interval + :param instance blockchain_instance: instance to use when accesing a RPC + :param str mode: (default) Irreversible block (``irreversible``) or + actual head block (``head``) + :param int max_block_wait_repetition: (default) 3 maximum wait time for + next block ismax_block_wait_repetition * block_interval - This class let's you deal with blockchain related data and methods. + This class let's you deal with blockchain related data and methods. """ async def __init__(self, *args, **kwargs): @@ -23,13 +23,12 @@ async def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) async def info(self): - """ This call returns the *dynamic global properties* - """ + """This call returns the *dynamic global properties*""" return await self.blockchain.rpc.get_dynamic_global_properties() async def chainParameters(self): - """ The blockchain parameters, such as fees, and committee-controlled - parameters are returned here + """The blockchain parameters, such as fees, and committee-controlled + parameters are returned here """ if not self._parameters: await self.update_chain_parameters() @@ -40,74 +39,71 @@ async def update_chain_parameters(self): self._parameters = config["parameters"] def get_network(self): - """ Identify the network + """Identify the network - :returns: Network parameters - :rtype: dict + :returns: Network parameters + :rtype: dict """ return self.blockchain.rpc.get_network() async def get_chain_properties(self): - """ Return chain properties - """ + """Return chain properties""" return await self.blockchain.rpc.get_chain_properties() async def config(self): - """ Returns object 2.0.0 - """ + """Returns object 2.0.0""" return await self.blockchain.rpc.get_object("2.0.0") async def get_current_block_num(self): - """ This call returns the current block + """This call returns the current block - .. note:: The block number returned depends on the ``mode`` used - when instanciating from this class. + .. note:: The block number returned depends on the ``mode`` used + when instanciating from this class. """ result = await self.info() return result.get(self.mode) async def get_current_block(self): - """ This call returns the current block + """This call returns the current block - .. note:: The block number returned depends on the ``mode`` used - when instanciating from this class. + .. note:: The block number returned depends on the ``mode`` used + when instanciating from this class. """ return await self.block_class( await self.get_current_block_num(), blockchain_instance=self.blockchain ) async def get_block_interval(self): - """ This call returns the block interval - """ + """This call returns the block interval""" params = await self.chainParameters() return params.get("block_interval") async def block_time(self, block_num): - """ Returns a datetime of the block with the given block - number. + """Returns a datetime of the block with the given block + number. - :param int block_num: Block number + :param int block_num: Block number """ result = await self.block_class(block_num, blockchain_instance=self.blockchain) return result.time() async def block_timestamp(self, block_num): - """ Returns the timestamp of the block with the given block - number. + """Returns the timestamp of the block with the given block + number. - :param int block_num: Block number + :param int block_num: Block number """ result = await self.block_class(block_num, blockchain_instance=self.blockchain) return int(result.time().timestamp()) async def blocks(self, start=None, stop=None): - """ Yields blocks starting from ``start``. + """Yields blocks starting from ``start``. - :param int start: Starting block - :param int stop: Stop at this block - :param str mode: We here have the choice between - "head" (the last block) and "irreversible" (the block that is - confirmed by 2/3 of all block producers and is thus irreversible) + :param int start: Starting block + :param int stop: Stop at this block + :param str mode: We here have the choice between + "head" (the last block) and "irreversible" (the block that is + confirmed by 2/3 of all block producers and is thus irreversible) """ # Let's find out how often blocks are generated! self.block_interval = await self.get_block_interval() @@ -140,15 +136,15 @@ async def blocks(self, start=None, stop=None): await asyncio.sleep(self.block_interval) async def wait_for_and_get_block(self, block_number, blocks_waiting_for=None): - """ Get the desired block from the chain, if the current head block is - smaller (for both head and irreversible) then we wait, but a - maxmimum of blocks_waiting_for * max_block_wait_repetition time - before failure. - - :param int block_number: desired block number - :param int blocks_waiting_for: (default) difference between - block_number and current head how many blocks we are willing to - wait, positive int + """Get the desired block from the chain, if the current head block is + smaller (for both head and irreversible) then we wait, but a + maxmimum of blocks_waiting_for * max_block_wait_repetition time + before failure. + + :param int block_number: desired block number + :param int blocks_waiting_for: (default) difference between + block_number and current head how many blocks we are willing to + wait, positive int """ if not blocks_waiting_for: blocks_waiting_for = max( @@ -175,18 +171,18 @@ async def wait_for_and_get_block(self, block_number, blocks_waiting_for=None): return block async def ops(self, start=None, stop=None, **kwargs): - """ Yields all operations (excluding virtual operations) starting from - ``start``. - - :param int start: Starting block - :param int stop: Stop at this block - :param str mode: We here have the choice between - "head" (the last block) and "irreversible" (the block that is - confirmed by 2/3 of all block producers and is thus irreversible) - :param bool only_virtual_ops: Only yield virtual operations - - This call returns a list that only carries one operation and - its type! + """Yields all operations (excluding virtual operations) starting from + ``start``. + + :param int start: Starting block + :param int stop: Stop at this block + :param str mode: We here have the choice between + "head" (the last block) and "irreversible" (the block that is + confirmed by 2/3 of all block producers and is thus irreversible) + :param bool only_virtual_ops: Only yield virtual operations + + This call returns a list that only carries one operation and + its type! """ async for block in self.blocks(start=start, stop=stop, **kwargs): @@ -201,20 +197,20 @@ async def ops(self, start=None, stop=None, **kwargs): } async def stream(self, opNames=[], *args, **kwargs): - """ Yield specific operations (e.g. comments) only - - :param array opNames: List of operations to filter for - :param int start: Start at this block - :param int stop: Stop at this block - :param str mode: We here have the choice between - * "head": the last block - * "irreversible": the block that is confirmed by 2/3 of all - block producers and is thus irreversible! - - The dict output is formated such that ``type`` caries the - operation type, timestamp and block_num are taken from the - block the operation was stored in and the other key depend - on the actualy operation. + """Yield specific operations (e.g. comments) only + + :param array opNames: List of operations to filter for + :param int start: Start at this block + :param int stop: Stop at this block + :param str mode: We here have the choice between + * "head": the last block + * "irreversible": the block that is confirmed by 2/3 of all + block producers and is thus irreversible! + + The dict output is formated such that ``type`` caries the + operation type, timestamp and block_num are taken from the + block the operation was stored in and the other key depend + on the actualy operation. """ async for op in self.ops(**kwargs): if not opNames or op["op"][0] in opNames: @@ -227,20 +223,20 @@ async def stream(self, opNames=[], *args, **kwargs): yield r async def awaitTxConfirmation(self, transaction, limit=10): - """ Returns the transaction as seen by the blockchain after being - included into a block - - .. note:: If you want instant confirmation, you need to instantiate - class:`.blockchain.Blockchain` with - ``mode="head"``, otherwise, the call will wait until - confirmed in an irreversible block. - - .. note:: This method returns once the blockchain has included a - transaction with the **same signature**. Even though the - signature is not usually used to identify a transaction, - it still cannot be forfeited and is derived from the - transaction contented and thus identifies a transaction - uniquely. + """Returns the transaction as seen by the blockchain after being + included into a block + + .. note:: If you want instant confirmation, you need to instantiate + class:`.blockchain.Blockchain` with + ``mode="head"``, otherwise, the call will wait until + confirmed in an irreversible block. + + .. note:: This method returns once the blockchain has included a + transaction with the **same signature**. Even though the + signature is not usually used to identify a transaction, + it still cannot be forfeited and is derived from the + transaction contented and thus identifies a transaction + uniquely. """ counter = 0 async for block in self.blocks(): @@ -252,11 +248,11 @@ async def awaitTxConfirmation(self, transaction, limit=10): raise Exception("The operation has not been added after 10 blocks!") async def get_all_accounts(self, start="", stop="", steps=1e3, **kwargs): - """ Yields account names between start and stop. + """Yields account names between start and stop. - :param str start: Start at this account name - :param str stop: Stop at this account name - :param int steps: Obtain ``steps`` ret with a single call from RPC + :param str start: Start at this account name + :param str stop: Stop at this account name + :param int steps: Obtain ``steps`` ret with a single call from RPC """ lastname = start while True: diff --git a/graphenecommon/aio/blockchainobject.py b/graphenecommon/aio/blockchainobject.py index 44ea2010..62028d1f 100644 --- a/graphenecommon/aio/blockchainobject.py +++ b/graphenecommon/aio/blockchainobject.py @@ -11,22 +11,22 @@ class Caching(SyncCaching): def __getitem__(self, key): - """ This method overrides synchronous version to avoid calling - self.refresh() + """This method overrides synchronous version to avoid calling + self.refresh() """ return dict.__getitem__(self, key) async def items(self): - """ This overrides items() so that refresh() is called if the - object is not already fetched + """This overrides items() so that refresh() is called if the + object is not already fetched """ if not self._fetched: await self.refresh() return dict.items(self) def __contains__(self, key): - """ This method overrides synchronous version to avoid calling - self.refresh() + """This method overrides synchronous version to avoid calling + self.refresh() """ return dict.__contains__(self, key) @@ -48,11 +48,11 @@ async def __init__(self, *args, **kwargs): await self.refresh(*args, **kwargs) def __getitem__(self, key): - """ Since we've overwriten __getitem__ in cache and inherit from there, - we need to make sure we use `list` here instead of `dict`. + """Since we've overwriten __getitem__ in cache and inherit from there, + we need to make sure we use `list` here instead of `dict`. - This method overrides synchronous version to avoid calling - self.refresh() + This method overrides synchronous version to avoid calling + self.refresh() """ return list.__getitem__(self, key) @@ -112,13 +112,13 @@ async def __init__( class Object(BlockchainObject, AbstractBlockchainInstanceProvider): - """ This class is a basic class that allows to obtain any object - from the blockchyin by fetching it through the API + """This class is a basic class that allows to obtain any object + from the blockchyin by fetching it through the API """ async def refresh(self): - """ This is the refresh method that overloads the prototype in - BlockchainObject. + """This is the refresh method that overloads the prototype in + BlockchainObject. """ dict.__init__( self, diff --git a/graphenecommon/aio/chain.py b/graphenecommon/aio/chain.py index f81bf109..8e7302dc 100644 --- a/graphenecommon/aio/chain.py +++ b/graphenecommon/aio/chain.py @@ -17,11 +17,11 @@ def __init__(self, *args, **kwargs): self.notifications = None async def connect(self): - """ Connect to blockchain network + """Connect to blockchain network - Async version does wallet initialization after connect because - wallet depends on prefix which is available after connection only, - and we want to keep __init__() synchronous. + Async version does wallet initialization after connect because + wallet depends on prefix which is available after connection only, + and we want to keep __init__() synchronous. """ node = self._kwargs.get("node", None) rpcuser = self._kwargs.get("rpcuser", None) @@ -50,40 +50,39 @@ async def connect(self): self.notifications = self.rpc.connection.notifications async def info(self): - """ Returns the global properties - """ + """Returns the global properties""" return await self.rpc.get_dynamic_global_properties() async def finalizeOp(self, ops, account, permission, **kwargs): - """ This method obtains the required private keys if present in - the wallet, finalizes the transaction, signs it and - broadacasts it - - :param operation ops: The operation (or list of operaions) to - broadcast - :param operation account: The account that authorizes the - operation - :param string permission: The required permission for - signing (active, owner, posting) - :param object append_to: This allows to provide an instance of - ProposalsBuilder (see :func:`new_proposal`) or - TransactionBuilder (see :func:`new_tx()`) to specify - where to put a specific operation. - - ... note:: ``append_to`` is exposed to every method used in the - this class - - ... note:: - - If ``ops`` is a list of operation, they all need to be - signable by the same key! Thus, you cannot combine ops - that require active permission with ops that require - posting permission. Neither can you use different - accounts for different operations! - - ... note:: This uses ``txbuffer`` as instance of - :class:`transactionbuilder.TransactionBuilder`. - You may want to use your own txbuffer + """This method obtains the required private keys if present in + the wallet, finalizes the transaction, signs it and + broadacasts it + + :param operation ops: The operation (or list of operaions) to + broadcast + :param operation account: The account that authorizes the + operation + :param string permission: The required permission for + signing (active, owner, posting) + :param object append_to: This allows to provide an instance of + ProposalsBuilder (see :func:`new_proposal`) or + TransactionBuilder (see :func:`new_tx()`) to specify + where to put a specific operation. + + ... note:: ``append_to`` is exposed to every method used in the + this class + + ... note:: + + If ``ops`` is a list of operation, they all need to be + signable by the same key! Thus, you cannot combine ops + that require active permission with ops that require + posting permission. Neither can you use different + accounts for different operations! + + ... note:: This uses ``txbuffer`` as instance of + :class:`transactionbuilder.TransactionBuilder`. + You may want to use your own txbuffer """ if "append_to" in kwargs and kwargs["append_to"]: if self.proposer: @@ -140,13 +139,13 @@ async def finalizeOp(self, ops, account, permission, **kwargs): return await self.txbuffer.broadcast() async def sign(self, tx=None, wifs=[]): - """ Sign a provided transaction witht he provided key(s) + """Sign a provided transaction witht he provided key(s) - :param dict tx: The transaction to be signed and returned - :param string wifs: One or many wif keys to use for signing - a transaction. If not present, the keys will be loaded - from the wallet as defined in "missing_signatures" key - of the transactions. + :param dict tx: The transaction to be signed and returned + :param string wifs: One or many wif keys to use for signing + a transaction. If not present, the keys will be loaded + from the wallet as defined in "missing_signatures" key + of the transactions. """ if tx: txbuffer = self.transactionbuilder_class(tx, blockchain_instance=self) @@ -158,9 +157,9 @@ async def sign(self, tx=None, wifs=[]): return await txbuffer.json() async def broadcast(self, tx=None): - """ Broadcast a transaction to the Blockchain + """Broadcast a transaction to the Blockchain - :param tx tx: Signed transaction to broadcast + :param tx tx: Signed transaction to broadcast """ if tx: # If tx is provided, we broadcast the tx diff --git a/graphenecommon/aio/committee.py b/graphenecommon/aio/committee.py index de33ec5a..4b729034 100644 --- a/graphenecommon/aio/committee.py +++ b/graphenecommon/aio/committee.py @@ -5,11 +5,11 @@ class Committee(BlockchainObject, SyncCommittee): - """ Read data about a Committee Member in the chain + """Read data about a Committee Member in the chain - :param str member: Name of the Committee Member - :param instance blockchain_instance: instance to use when accesing a RPC - :param bool lazy: Use lazy loading + :param str member: Name of the Committee Member + :param instance blockchain_instance: instance to use when accesing a RPC + :param bool lazy: Use lazy loading """ diff --git a/graphenecommon/aio/genesisbalance.py b/graphenecommon/aio/genesisbalance.py index 54a91725..2e4f92a8 100644 --- a/graphenecommon/aio/genesisbalance.py +++ b/graphenecommon/aio/genesisbalance.py @@ -8,18 +8,18 @@ class GenesisBalance(BlockchainObject, SyncGenesisBalance): - """ Deals with Assets of the network. - - :param str Asset: Symbol name or object id of an asset - :param bool lazy: Lazy loading - :param bool full: Also obtain bitasset-data and dynamic asset data - :param instance blockchain_instance: instance to use when accesing a RPC - :returns: All data of an asset - :rtype: dict - - .. note:: This class comes with its own caching function to reduce the - load on the API server. Instances of this class can be - refreshed with ``Asset.refresh()``. + """Deals with Assets of the network. + + :param str Asset: Symbol name or object id of an asset + :param bool lazy: Lazy loading + :param bool full: Also obtain bitasset-data and dynamic asset data + :param instance blockchain_instance: instance to use when accesing a RPC + :returns: All data of an asset + :rtype: dict + + .. note:: This class comes with its own caching function to reduce the + load on the API server. Instances of this class can be + refreshed with ``Asset.refresh()``. """ async def __init__(self, *args, **kwargs): @@ -42,12 +42,12 @@ async def refresh(self): ) async def claim(self, account=None, **kwargs): - """ Claim a balance from the genesis block + """Claim a balance from the genesis block - :param str balance_id: The identifier that identifies the balance - to claim (1.15.x) - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) + :param str balance_id: The identifier that identifies the balance + to claim (1.15.x) + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) """ if not account: if "default_account" in self.blockchain.config: @@ -123,8 +123,8 @@ async def claim(self, account=None, **kwargs): class GenesisBalances(SyncGenesisBalances): - """ List genesis balances that can be claimed from the - keys in the wallet + """List genesis balances that can be claimed from the + keys in the wallet """ async def __init__(self, **kwargs): diff --git a/graphenecommon/aio/memo.py b/graphenecommon/aio/memo.py index e90d7b57..1f7f5d12 100644 --- a/graphenecommon/aio/memo.py +++ b/graphenecommon/aio/memo.py @@ -5,41 +5,41 @@ @asyncinit class Memo(SyncMemo): - """ Deals with Memos that are attached to a transfer + """Deals with Memos that are attached to a transfer - :param .account.Account from_account: Account that has sent - the memo - :param .account.Account to_account: Account that has received - the memo - :param instance blockchain_instance: instance to use when accesing a RPC + :param .account.Account from_account: Account that has sent + the memo + :param .account.Account to_account: Account that has received + the memo + :param instance blockchain_instance: instance to use when accesing a RPC - A memo is encrypted with a shared secret derived from a private key of - the sender and a public key of the receiver. Due to the underlying - mathematics, the same shared secret can be derived by the private key - of the receiver and the public key of the sender. The encrypted message - is perturbed by a nonce that is part of the transmitted message. + A memo is encrypted with a shared secret derived from a private key of + the sender and a public key of the receiver. Due to the underlying + mathematics, the same shared secret can be derived by the private key + of the receiver and the public key of the sender. The encrypted message + is perturbed by a nonce that is part of the transmitted message. - .. code-block:: python + .. code-block:: python - from .memo import Memo - m = await Memo("from-account", "to-account") - m.blockchain.wallet.unlock("secret") - enc = (m.encrypt("foobar")) - print(enc) - >> {'nonce': '17329630356955254641', 'message': '8563e2bb2976e0217806d642901a2855'} - print(m.decrypt(enc)) - >> foobar + from .memo import Memo + m = await Memo("from-account", "to-account") + m.blockchain.wallet.unlock("secret") + enc = (m.encrypt("foobar")) + print(enc) + >> {'nonce': '17329630356955254641', 'message': '8563e2bb2976e0217806d642901a2855'} + print(m.decrypt(enc)) + >> foobar - To decrypt a memo, simply use + To decrypt a memo, simply use - .. code-block:: python + .. code-block:: python - from memo import Memo - m = await Memo() - m.blockchain.wallet.unlock("secret") - print(memo.decrypt(op_data["memo"])) + from memo import Memo + m = await Memo() + m.blockchain.wallet.unlock("secret") + print(memo.decrypt(op_data["memo"])) - if ``op_data`` being the payload of a transfer operation. + if ``op_data`` being the payload of a transfer operation. """ diff --git a/graphenecommon/aio/message.py b/graphenecommon/aio/message.py index a38faf59..a37fbeed 100644 --- a/graphenecommon/aio/message.py +++ b/graphenecommon/aio/message.py @@ -28,21 +28,20 @@ @asyncinit class MessageV1(SyncMessageV1): - """ Allow to sign and verify Messages that are sigend with a private key - """ + """Allow to sign and verify Messages that are sigend with a private key""" async def __init__(self, *args, **kwargs): # __init__ should be async because AbstractBlockchainInstanceProvider expects async __init__ super().__init__(*args, **kwargs) async def sign(self, account=None, **kwargs): - """ Sign a message with an account's memo key + """Sign a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) - :raises ValueError: If not account for signing is provided + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) + :raises ValueError: If not account for signing is provided - :returns: the signed message encapsulated in a known format + :returns: the signed message encapsulated in a known format """ if not account: if "default_account" in self.blockchain.config: @@ -84,13 +83,13 @@ async def sign(self, account=None, **kwargs): ) async def verify(self, **kwargs): - """ Verify a message with an account's memo key + """Verify a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) - :returns: True if the message is verified successfully - :raises InvalidMessageSignature if the signature is not ok + :returns: True if the message is verified successfully + :raises InvalidMessageSignature if the signature is not ok """ # Split message into its parts parts = re.split("|".join(self.MESSAGE_SPLIT), self.message) @@ -166,21 +165,20 @@ async def verify(self, **kwargs): @asyncinit class MessageV2(SyncMessageV2): - """ Allow to sign and verify Messages that are sigend with a private key - """ + """Allow to sign and verify Messages that are sigend with a private key""" async def __init__(self, *args, **kwargs): # __init__ should be async because AbstractBlockchainInstanceProvider expects async __init__ super().__init__(*args, **kwargs) async def sign(self, account=None, **kwargs): - """ Sign a message with an account's memo key + """Sign a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) - :raises ValueError: If not account for signing is provided + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) + :raises ValueError: If not account for signing is provided - :returns: the signed message encapsulated in a known format + :returns: the signed message encapsulated in a known format """ if not account: if "default_account" in self.blockchain.config: @@ -214,13 +212,13 @@ async def sign(self, account=None, **kwargs): return dict(signed=enc_message, payload=payload, signature=signature) async def verify(self, **kwargs): - """ Verify a message with an account's memo key + """Verify a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) - :returns: True if the message is verified successfully - :raises InvalidMessageSignature if the signature is not ok + :returns: True if the message is verified successfully + :raises InvalidMessageSignature if the signature is not ok """ if not isinstance(self.message, dict): try: diff --git a/graphenecommon/aio/price.py b/graphenecommon/aio/price.py index 10b7ccf3..2e2c72c2 100644 --- a/graphenecommon/aio/price.py +++ b/graphenecommon/aio/price.py @@ -8,57 +8,57 @@ @asyncinit class Price(SyncPrice): - """ This class deals with all sorts of prices of any pair of assets to - simplify dealing with the tuple:: + """This class deals with all sorts of prices of any pair of assets to + simplify dealing with the tuple:: - (quote, base) + (quote, base) - each being an instance of :class:`.amount.Amount`. The - amount themselves define the price. + each being an instance of :class:`.amount.Amount`. The + amount themselves define the price. - .. note:: + .. note:: - The price (floating) is derived as ``base/quote`` + The price (floating) is derived as ``base/quote`` - :param list args: Allows to deal with different representations of a price - :param asset.Asset base: Base asset - :param asset.Asset quote: Quote asset - :param instance blockchain_instance: instance to use when accesing a RPC - :returns: All data required to represent a price - :rtype: dict + :param list args: Allows to deal with different representations of a price + :param asset.Asset base: Base asset + :param asset.Asset quote: Quote asset + :param instance blockchain_instance: instance to use when accesing a RPC + :returns: All data required to represent a price + :rtype: dict - Way to obtain a proper instance: + Way to obtain a proper instance: - * ``args`` is a str with a price and two assets - * ``args`` can be a floating number and ``base`` and ``quote`` being instances of :class:`.asset.Asset` - * ``args`` can be a floating number and ``base`` and ``quote`` being instances of ``str`` - * ``args`` can be dict with keys ``price``, ``base``, and ``quote`` (*graphene balances*) - * ``args`` can be dict with keys ``base`` and ``quote`` - * ``args`` can be dict with key ``receives`` (filled orders) - * ``args`` being a list of ``[quote, base]`` both being instances of :class:`.amount.Amount` - * ``args`` being a list of ``[quote, base]`` both being instances of ``str`` (``amount symbol``) - * ``base`` and ``quote`` being instances of :class:`.asset.Amount` + * ``args`` is a str with a price and two assets + * ``args`` can be a floating number and ``base`` and ``quote`` being instances of :class:`.asset.Asset` + * ``args`` can be a floating number and ``base`` and ``quote`` being instances of ``str`` + * ``args`` can be dict with keys ``price``, ``base``, and ``quote`` (*graphene balances*) + * ``args`` can be dict with keys ``base`` and ``quote`` + * ``args`` can be dict with key ``receives`` (filled orders) + * ``args`` being a list of ``[quote, base]`` both being instances of :class:`.amount.Amount` + * ``args`` being a list of ``[quote, base]`` both being instances of ``str`` (``amount symbol``) + * ``base`` and ``quote`` being instances of :class:`.asset.Amount` - This allows instanciations like: + This allows instanciations like: - * ``Price("0.315 USD/BTS")`` - * ``Price(0.315, base="USD", quote="BTS")`` - * ``Price(0.315, base=self.asset_class("USD"), quote=self.asset_class("BTS"))`` - * ``Price({"base": {"amount": 1, "asset_id": "1.3.0"}, "quote": {"amount": 10, "asset_id": "1.3.106"}})`` - * ``Price({"receives": {"amount": 1, "asset_id": "1.3.0"}, "pays": {"amount": 10, "asset_id": "1.3.106"}}, base_asset=self.asset_class("1.3.0"))`` - * ``Price(quote="10 GOLD", base="1 USD")`` - * ``Price("10 GOLD", "1 USD")`` - * ``Price(self.amount_class("10 GOLD"), self.amount_class("1 USD"))`` - * ``Price(1.0, "USD/GOLD")`` + * ``Price("0.315 USD/BTS")`` + * ``Price(0.315, base="USD", quote="BTS")`` + * ``Price(0.315, base=self.asset_class("USD"), quote=self.asset_class("BTS"))`` + * ``Price({"base": {"amount": 1, "asset_id": "1.3.0"}, "quote": {"amount": 10, "asset_id": "1.3.106"}})`` + * ``Price({"receives": {"amount": 1, "asset_id": "1.3.0"}, "pays": {"amount": 10, "asset_id": "1.3.106"}}, base_asset=self.asset_class("1.3.0"))`` + * ``Price(quote="10 GOLD", base="1 USD")`` + * ``Price("10 GOLD", "1 USD")`` + * ``Price(self.amount_class("10 GOLD"), self.amount_class("1 USD"))`` + * ``Price(1.0, "USD/GOLD")`` - Instances of this class can be used in regular mathematical expressions - (``+-*/%``) such as: + Instances of this class can be used in regular mathematical expressions + (``+-*/%``) such as: - .. code-block:: python + .. code-block:: python - >>> from price import Price - >>> Price("0.3314 USD/BTS") * 2 - 0.662600000 USD/BTS + >>> from price import Price + >>> Price("0.3314 USD/BTS") * 2 + 0.662600000 USD/BTS """ @@ -256,9 +256,9 @@ async def copy(self): ) async def as_base(self, base): - """ Returns the price instance so that the base asset is ``base``. + """Returns the price instance so that the base asset is ``base``. - Note: This makes a copy of the object! + Note: This makes a copy of the object! """ if base == self["base"]["symbol"]: return await self.copy() @@ -269,9 +269,9 @@ async def as_base(self, base): raise InvalidAssetException async def as_quote(self, quote): - """ Returns the price instance so that the quote asset is ``quote``. + """Returns the price instance so that the quote asset is ``quote``. - Note: This makes a copy of the object! + Note: This makes a copy of the object! """ if quote == self["quote"]["symbol"]: return await self.copy() @@ -282,8 +282,7 @@ async def as_quote(self, quote): raise InvalidAssetException async def invert(self): - """ Invert the price (e.g. go from ``USD/BTS`` into ``BTS/USD``) - """ + """Invert the price (e.g. go from ``USD/BTS`` into ``BTS/USD``)""" tmp = self["quote"] self["quote"] = self["base"] self["base"] = tmp diff --git a/graphenecommon/aio/proposal.py b/graphenecommon/aio/proposal.py index e342e42a..2d349b9c 100644 --- a/graphenecommon/aio/proposal.py +++ b/graphenecommon/aio/proposal.py @@ -10,10 +10,10 @@ class Proposal(BlockchainObject, SyncProposal): - """ Read data about a Proposal Balance in the chain + """Read data about a Proposal Balance in the chain - :param str id: Id of the proposal - :param instance blockchain_instance: instance to use when accesing a RPC + :param str id: Id of the proposal + :param instance blockchain_instance: instance to use when accesing a RPC """ @@ -32,8 +32,8 @@ async def refresh(self): @property async def proposer(self): - """ Return the proposer of the proposal if available in the backend, - else returns None + """Return the proposer of the proposal if available in the backend, + else returns None """ if "proposer" in self: return await self.account_class( @@ -42,10 +42,10 @@ async def proposer(self): class Proposals(BlockchainObjects, SyncProposals): - """ Obtain a list of pending proposals for an account + """Obtain a list of pending proposals for an account - :param str account: Account name - :param instance blockchain_instance: instance to use when accesing a RPC + :param str account: Account name + :param instance blockchain_instance: instance to use when accesing a RPC """ async def __init__(self, account, *args, **kwargs): diff --git a/graphenecommon/aio/transactionbuilder.py b/graphenecommon/aio/transactionbuilder.py index 27344847..d121fdb0 100644 --- a/graphenecommon/aio/transactionbuilder.py +++ b/graphenecommon/aio/transactionbuilder.py @@ -19,17 +19,17 @@ class ProposalBuilder(SyncProposalBuilder): - """ Proposal Builder allows us to construct an independent Proposal - that may later be added to an instance ot TransactionBuilder - - :param str proposer: Account name of the proposing user - :param int proposal_expiration: Number seconds until the proposal is - supposed to expire - :param int proposal_review: Number of seconds for review of the - proposal - :param .transactionbuilder.TransactionBuilder: Specify - your own instance of transaction builder (optional) - :param instance blockchain_instance: Blockchain instance + """Proposal Builder allows us to construct an independent Proposal + that may later be added to an instance ot TransactionBuilder + + :param str proposer: Account name of the proposing user + :param int proposal_expiration: Number seconds until the proposal is + supposed to expire + :param int proposal_review: Number of seconds for review of the + proposal + :param .transactionbuilder.TransactionBuilder: Specify + your own instance of transaction builder (optional) + :param instance blockchain_instance: Blockchain instance """ async def broadcast(self): @@ -39,8 +39,7 @@ async def broadcast(self): return await self.parent.broadcast() async def json(self): - """ Return the json formated version of this proposal - """ + """Return the json formated version of this proposal""" raw = await self.get_raw() if not raw: return dict() @@ -50,8 +49,7 @@ def __dict__(self): raise NotImplementedError("Use .json() instead") async def get_raw(self): - """ Returns an instance of base "Operations" for further processing - """ + """Returns an instance of base "Operations" for further processing""" if not self.ops: return ops = [self.operations.Op_wrapper(op=o) for o in list(self.ops)] @@ -72,8 +70,8 @@ async def get_raw(self): class TransactionBuilder(SyncTransactionBuilder): - """ This class simplifies the creation of transactions by adding - operations and signers. + """This class simplifies the creation of transactions by adding + operations and signers. """ async def list_operations(self): @@ -91,8 +89,7 @@ def __str__(self): raise NotImplementedError("Use .json() instead") async def json(self): - """ Show the transaction as plain json - """ + """Show the transaction as plain json""" if not self._is_constructed() or self._is_require_reconstruction(): await self.constructTx() return dict(self) @@ -149,8 +146,8 @@ async def _fetchkeys(self, account, perm, level=0, required_treshold=1): return r async def appendSigner(self, accounts, permission): - """ Try to obtain the wif key from the wallet by telling which account - and permission is supposed to sign the transaction + """Try to obtain the wif key from the wallet by telling which account + and permission is supposed to sign the transaction """ assert permission in self.permission_types, "Invalid permission" @@ -190,8 +187,8 @@ async def appendSigner(self, accounts, permission): self.signing_accounts.append(account) async def add_required_fees(self, ops, asset_id="1.3.0"): - """ Auxiliary method to obtain the required fees for a set of - operations. Requires a websocket connection to a witness node! + """Auxiliary method to obtain the required fees for a set of + operations. Requires a websocket connection to a witness node! """ ws = self.blockchain.rpc fees = await ws.get_required_fees([i.json() for i in ops], asset_id) @@ -216,8 +213,8 @@ async def add_required_fees(self, ops, asset_id="1.3.0"): return ops async def constructTx(self): - """ Construct the actual transaction and store it in the class's dict - store + """Construct the actual transaction and store it in the class's dict + store """ ops = list() for op in self.ops: @@ -255,9 +252,9 @@ async def constructTx(self): self._unset_require_reconstruction() async def get_block_params(self, use_head_block=False): - """ Auxiliary method to obtain ``ref_block_num`` and - ``ref_block_prefix``. Requires a websocket connection to a - witness node! + """Auxiliary method to obtain ``ref_block_num`` and + ``ref_block_prefix``. Requires a websocket connection to a + witness node! """ ws = self.blockchain.rpc dynBCParams = await ws.get_dynamic_global_properties() @@ -278,13 +275,13 @@ async def get_block_params(self, use_head_block=False): return ref_block_num, ref_block_prefix async def sign(self): - """ Sign a provided transaction with the provided key(s) + """Sign a provided transaction with the provided key(s) - :param dict tx: The transaction to be signed and returned - :param string wifs: One or many wif keys to use for signing - a transaction. If not present, the keys will be loaded - from the wallet as defined in "missing_signatures" key - of the transactions. + :param dict tx: The transaction to be signed and returned + :param string wifs: One or many wif keys to use for signing + a transaction. If not present, the keys will be loaded + from the wallet as defined in "missing_signatures" key + of the transactions. """ await self.constructTx() @@ -316,8 +313,7 @@ async def sign(self): return self.tx async def verify_authority(self): - """ Verify the authority of the signed transaction - """ + """Verify the authority of the signed transaction""" try: if not await self.blockchain.rpc.verify_authority(await self.json()): raise InsufficientAuthorityError @@ -325,9 +321,9 @@ async def verify_authority(self): raise e async def broadcast(self): - """ Broadcast a transaction to the blockchain network + """Broadcast a transaction to the blockchain network - :param tx tx: Signed transaction to broadcast + :param tx tx: Signed transaction to broadcast """ # Sign if not signed if not self._is_signed(): @@ -366,11 +362,11 @@ async def broadcast(self): return ret async def addSigningInformation(self, account, permission): - """ This is a private method that adds side information to a - unsigned/partial transaction in order to simplify later - signing (e.g. for multisig or coldstorage) + """This is a private method that adds side information to a + unsigned/partial transaction in order to simplify later + signing (e.g. for multisig or coldstorage) - FIXME: Does not work with owner keys! + FIXME: Does not work with owner keys! """ self.constructTx() self["blockchain"] = self.blockchain.rpc.chain_params diff --git a/graphenecommon/aio/vesting.py b/graphenecommon/aio/vesting.py index e3b24514..9b8486af 100644 --- a/graphenecommon/aio/vesting.py +++ b/graphenecommon/aio/vesting.py @@ -5,10 +5,10 @@ class Vesting(BlockchainObject, SyncVesting): - """ Read data about a Vesting Balance in the chain + """Read data about a Vesting Balance in the chain - :param str id: Id of the vesting balance - :param instance blockchain_instance: instance to use when accesing a RPC + :param str id: Id of the vesting balance + :param instance blockchain_instance: instance to use when accesing a RPC """ diff --git a/graphenecommon/aio/wallet.py b/graphenecommon/aio/wallet.py index c95c0087..f960db40 100644 --- a/graphenecommon/aio/wallet.py +++ b/graphenecommon/aio/wallet.py @@ -9,38 +9,37 @@ class Wallet(SyncWallet): - """ The wallet is meant to maintain access to private keys for - your accounts. It either uses manually provided private keys - or uses a SQLite database managed by storage.py. + """The wallet is meant to maintain access to private keys for + your accounts. It either uses manually provided private keys + or uses a SQLite database managed by storage.py. - :param array,dict,string keys: Predefine the wif keys to shortcut the - wallet database + :param array,dict,string keys: Predefine the wif keys to shortcut the + wallet database - .. note:: Wallet should be instantiated synchroously e.g. + .. note:: Wallet should be instantiated synchroously e.g. - .. code-block:: python + .. code-block:: python - w = Wallet() + w = Wallet() - Three wallet operation modes are possible: + Three wallet operation modes are possible: - * **Wallet Database**: Here, the library loads the keys from the - locally stored wallet SQLite database (see ``storage.py``). - * **Providing Keys**: Here, you can provide the keys for - your accounts manually. All you need to do is add the wif - keys for the accounts you want to use as a simple array - using the ``keys`` parameter to your blockchain instance. - * **Force keys**: This more is for advanced users and - requires that you know what you are doing. Here, the - ``keys`` parameter is a dictionary that overwrite the - ``active``, ``owner``, ``posting`` or ``memo`` keys for - any account. This mode is only used for *foreign* - signatures! + * **Wallet Database**: Here, the library loads the keys from the + locally stored wallet SQLite database (see ``storage.py``). + * **Providing Keys**: Here, you can provide the keys for + your accounts manually. All you need to do is add the wif + keys for the accounts you want to use as a simple array + using the ``keys`` parameter to your blockchain instance. + * **Force keys**: This more is for advanced users and + requires that you know what you are doing. Here, the + ``keys`` parameter is a dictionary that overwrite the + ``active``, ``owner``, ``posting`` or ``memo`` keys for + any account. This mode is only used for *foreign* + signatures! """ async def getOwnerKeyForAccount(self, name): - """ Obtain owner Private Key for an account from the wallet database - """ + """Obtain owner Private Key for an account from the wallet database""" account = await self.rpc.get_account(name) for authority in account["owner"]["key_auths"]: key = self.getPrivateKeyForPublicKey(authority[0]) @@ -49,8 +48,7 @@ async def getOwnerKeyForAccount(self, name): raise KeyNotFound async def getMemoKeyForAccount(self, name): - """ Obtain owner Memo Key for an account from the wallet database - """ + """Obtain owner Memo Key for an account from the wallet database""" account = await self.rpc.get_account(name) key = self.getPrivateKeyForPublicKey(account["options"]["memo_key"]) if key: @@ -58,8 +56,7 @@ async def getMemoKeyForAccount(self, name): return False async def getActiveKeyForAccount(self, name): - """ Obtain owner Active Key for an account from the wallet database - """ + """Obtain owner Active Key for an account from the wallet database""" account = await self.rpc.get_account(name) for authority in account["active"]["key_auths"]: try: @@ -69,15 +66,13 @@ async def getActiveKeyForAccount(self, name): return False async def getAccountsFromPublicKey(self, pub): - """ Obtain all accounts associated with a public key - """ + """Obtain all accounts associated with a public key""" result = await self.rpc.get_key_references([str(pub)]) names = result[0] return names async def getAccountFromPublicKey(self, pub): - """ Obtain the first account name from public key - """ + """Obtain the first account name from public key""" # FIXME, this only returns the first associated key. # If the key is used by multiple accounts, this # will surely lead to undesired behavior @@ -86,8 +81,7 @@ async def getAccountFromPublicKey(self, pub): return names[0] async def getAccounts(self): - """ Return all accounts installed in the wallet database - """ + """Return all accounts installed in the wallet database""" pubkeys = self.getPublicKeys() accounts = [] for pubkey in pubkeys: diff --git a/graphenecommon/aio/witness.py b/graphenecommon/aio/witness.py index 44f94110..c7255c3f 100644 --- a/graphenecommon/aio/witness.py +++ b/graphenecommon/aio/witness.py @@ -5,10 +5,10 @@ class Witness(BlockchainObject, SyncWitness): - """ Read data about a witness in the chain + """Read data about a witness in the chain - :param str account_name: Name of the witness - :param instance blockchain_instance: instance to use when accesing a RPC + :param str account_name: Name of the witness + :param instance blockchain_instance: instance to use when accesing a RPC """ @@ -70,11 +70,11 @@ async def is_active(self): class Witnesses(BlockchainObjects, SyncWitnesses): - """ Obtain a list of **active** witnesses and the current schedule + """Obtain a list of **active** witnesses and the current schedule - :param bool only_active: (False) Only return witnesses that are - actively producing blocks - :param instance blockchain_instance: instance to use when accesing a RPC + :param bool only_active: (False) Only return witnesses that are + actively producing blocks + :param instance blockchain_instance: instance to use when accesing a RPC """ async def __init__(self, *args, only_active=False, lazy=False, **kwargs): diff --git a/graphenecommon/aio/worker.py b/graphenecommon/aio/worker.py index 50b51abd..c1008033 100644 --- a/graphenecommon/aio/worker.py +++ b/graphenecommon/aio/worker.py @@ -6,10 +6,10 @@ class Worker(BlockchainObject, SyncWorker): - """ Read data about a worker in the chain + """Read data about a worker in the chain - :param str id: id of the worker - :param instance blockchain_instance: instance to use when accesing a RPC + :param str id: id of the worker + :param instance blockchain_instance: instance to use when accesing a RPC """ @@ -35,10 +35,10 @@ async def account(self): class Workers(BlockchainObjects, SyncWorkers): - """ Obtain a list of workers for an account + """Obtain a list of workers for an account - :param str account_name/id: Name/id of the account (optional) - :param instance blockchain_instance: instance to use when accesing a RPC + :param str account_name/id: Name/id of the account (optional) + :param instance blockchain_instance: instance to use when accesing a RPC """ async def __init__(self, *args, account_name=None, lazy=False, **kwargs): diff --git a/graphenecommon/amount.py b/graphenecommon/amount.py index d0d598e1..13701369 100644 --- a/graphenecommon/amount.py +++ b/graphenecommon/amount.py @@ -4,52 +4,52 @@ class Amount(dict, AbstractBlockchainInstanceProvider): - """ This class deals with Amounts of any asset to simplify dealing with the tuple:: + """This class deals with Amounts of any asset to simplify dealing with the tuple:: - (amount, asset) + (amount, asset) - :param list args: Allows to deal with different representations of an amount - :param float amount: Let's create an instance with a specific amount - :param str asset: Let's you create an instance with a specific asset (symbol) - :param instance blockchain_instance: instance to use when accesing a RPC - :returns: All data required to represent an Amount/Asset - :rtype: dict - :raises ValueError: if the data provided is not recognized + :param list args: Allows to deal with different representations of an amount + :param float amount: Let's create an instance with a specific amount + :param str asset: Let's you create an instance with a specific asset (symbol) + :param instance blockchain_instance: instance to use when accesing a RPC + :returns: All data required to represent an Amount/Asset + :rtype: dict + :raises ValueError: if the data provided is not recognized - .. code-block:: python + .. code-block:: python - from peerplays.amount import Amount - from peerplays.asset import Asset - a = Amount("1 USD") - b = Amount(1, "USD") - c = Amount("20", self.asset_class("USD")) - a + b - a * 2 - a += b - a /= 2.0 + from peerplays.amount import Amount + from peerplays.asset import Asset + a = Amount("1 USD") + b = Amount(1, "USD") + c = Amount("20", self.asset_class("USD")) + a + b + a * 2 + a += b + a /= 2.0 - Way to obtain a proper instance: + Way to obtain a proper instance: - * ``args`` can be a string, e.g.: "1 USD" - * ``args`` can be a dictionary containing ``amount`` and ``asset_id`` - * ``args`` can be a dictionary containing ``amount`` and ``asset`` - * ``args`` can be a list of a ``float`` and ``str`` (symbol) - * ``args`` can be a list of a ``float`` and a :class:`.asset.Asset` - * ``amount`` and ``asset`` are defined manually + * ``args`` can be a string, e.g.: "1 USD" + * ``args`` can be a dictionary containing ``amount`` and ``asset_id`` + * ``args`` can be a dictionary containing ``amount`` and ``asset`` + * ``args`` can be a list of a ``float`` and ``str`` (symbol) + * ``args`` can be a list of a ``float`` and a :class:`.asset.Asset` + * ``amount`` and ``asset`` are defined manually - An instance is a dictionary and comes with the following keys: + An instance is a dictionary and comes with the following keys: - * ``amount`` (float) - * ``symbol`` (str) - * ``asset`` (instance of :class:`.asset.Asset`) + * ``amount`` (float) + * ``symbol`` (str) + * ``asset`` (instance of :class:`.asset.Asset`) - Instances of this class can be used in regular mathematical expressions - (``+-*/%``) such as: + Instances of this class can be used in regular mathematical expressions + (``+-*/%``) such as: - .. code-block:: python + .. code-block:: python - Amount("1 USD") * 2 - Amount("15 GOLD") + Amount("0.5 GOLD") + Amount("1 USD") * 2 + Amount("15 GOLD") + Amount("0.5 GOLD") """ def __init__(self, *args, **kwargs): @@ -132,8 +132,7 @@ def __init__(self, *args, **kwargs): self["amount"] = float(self.get("amount", 0.0)) def copy(self): - """ Copy the instance and make sure not to use a reference - """ + """Copy the instance and make sure not to use a reference""" return self.__class__( amount=self["amount"], asset=self["asset"].copy(), @@ -142,14 +141,12 @@ def copy(self): @property def amount(self): - """ Returns the amount as float - """ + """Returns the amount as float""" return self["amount"] @property def symbol(self): - """ Returns the symbol of the asset - """ + """Returns the symbol of the asset""" return self["symbol"] def tuple(self): @@ -157,8 +154,7 @@ def tuple(self): @property def asset(self): - """ Returns the asset as instance of :class:`.asset.Asset` - """ + """Returns the asset as instance of :class:`.asset.Asset`""" if not self["asset"]: self["asset"] = self.asset_class( self["symbol"], blockchain_instance=self.blockchain diff --git a/graphenecommon/asset.py b/graphenecommon/asset.py index 68d4f46c..3ea593e5 100644 --- a/graphenecommon/asset.py +++ b/graphenecommon/asset.py @@ -5,18 +5,18 @@ class Asset(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Deals with Assets of the network. + """Deals with Assets of the network. - :param str Asset: Symbol name or object id of an asset - :param bool lazy: Lazy loading - :param bool full: Also obtain bitasset-data and dynamic asset data - :param instance blockchain_instance: instance to use when accesing a RPC - :returns: All data of an asset - :rtype: dict + :param str Asset: Symbol name or object id of an asset + :param bool lazy: Lazy loading + :param bool full: Also obtain bitasset-data and dynamic asset data + :param instance blockchain_instance: instance to use when accesing a RPC + :returns: All data of an asset + :rtype: dict - .. note:: This class comes with its own caching function to reduce the - load on the API server. Instances of this class can be - refreshed with ``Asset.refresh()``. + .. note:: This class comes with its own caching function to reduce the + load on the API server. Instances of this class can be + refreshed with ``Asset.refresh()``. """ def __init__(self, *args, **kwargs): @@ -27,8 +27,7 @@ def __init__(self, *args, **kwargs): BlockchainObject.__init__(self, *args, **kwargs) def refresh(self): - """ Refresh the data from the API server - """ + """Refresh the data from the API server""" asset = self.blockchain.rpc.get_asset(self.identifier) if not asset: raise AssetDoesNotExistsException(self.identifier) @@ -46,8 +45,7 @@ def refresh(self): @property def is_fully_loaded(self): - """ Is this instance fully loaded / e.g. all data available? - """ + """Is this instance fully loaded / e.g. all data available?""" return self.full and "bitasset_data_id" in self and "bitasset_data" in self @property @@ -60,20 +58,17 @@ def precision(self): @property def is_bitasset(self): - """ Is the asset a market pegged asset? - """ + """Is the asset a market pegged asset?""" return "bitasset_data_id" in self @property def permissions(self): - """ List the permissions for this asset that the issuer can obtain - """ + """List the permissions for this asset that the issuer can obtain""" return self["permissions"] @property def flags(self): - """ List the permissions that are currently used (flags) - """ + """List the permissions that are currently used (flags)""" return self["flags"] def ensure_full(self): @@ -82,8 +77,7 @@ def ensure_full(self): self.refresh() def update_cer(self, cer, account=None, **kwargs): - """ Update the Core Exchange Rate (CER) of an asset - """ + """Update the Core Exchange Rate (CER) of an asset""" assert callable(self.blockchain.update_cer) return self.blockchain.update_cer( self["symbol"], cer, account=account, **kwargs diff --git a/graphenecommon/block.py b/graphenecommon/block.py index 4f8fe88b..b354bf83 100644 --- a/graphenecommon/block.py +++ b/graphenecommon/block.py @@ -6,25 +6,25 @@ class Block(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Read a single block from the chain + """Read a single block from the chain - :param int block: block number - :param instance blockchain_instance: instance to use when accesing a RPC - :param bool lazy: Use lazy loading + :param int block: block number + :param instance blockchain_instance: instance to use when accesing a RPC + :param bool lazy: Use lazy loading - Instances of this class are dictionaries that come with additional - methods (see below) that allow dealing with a block and it's - corresponding functions. + Instances of this class are dictionaries that come with additional + methods (see below) that allow dealing with a block and it's + corresponding functions. - .. code-block:: python + .. code-block:: python - from block import Block - block = Block(1) - print(block) + from block import Block + block = Block(1) + print(block) - .. note:: This class comes with its own caching function to reduce the - load on the API server. Instances of this class can be - refreshed with ``Account.refresh()``. + .. note:: This class comes with its own caching function to reduce the + load on the API server. Instances of this class can be + refreshed with ``Account.refresh()``. """ @@ -38,8 +38,8 @@ def __init__(self, *args, use_cache=False, **kwargs): BlockchainObject.__init__(self, *args, **kwargs) def refresh(self): - """ Even though blocks never change, you freshly obtain its contents - from an API with this method + """Even though blocks never change, you freshly obtain its contents + from an API with this method """ identifier = self.identifier block = self.blockchain.rpc.get_block(self.identifier) @@ -52,8 +52,7 @@ def refresh(self): self.identifier = identifier def time(self): - """ Return a datatime instance for the timestamp of this block - """ + """Return a datatime instance for the timestamp of this block""" return parse_time(self["timestamp"]) @@ -68,8 +67,8 @@ def __init__(self, *args, use_cache=False, **kwargs): BlockchainObject.__init__(self, *args, **kwargs) def refresh(self): - """ Even though blocks never change, you freshly obtain its contents - from an API with this method + """Even though blocks never change, you freshly obtain its contents + from an API with this method """ block = self.blockchain.rpc.get_block_header(self.identifier) if not block: @@ -79,6 +78,5 @@ def refresh(self): ) def time(self): - """ Return a datatime instance for the timestamp of this block - """ + """Return a datatime instance for the timestamp of this block""" return parse_time(self["timestamp"]) diff --git a/graphenecommon/blockchain.py b/graphenecommon/blockchain.py index 4f012c03..6b92d5ed 100644 --- a/graphenecommon/blockchain.py +++ b/graphenecommon/blockchain.py @@ -4,16 +4,16 @@ class Blockchain(AbstractBlockchainInstanceProvider): - """ This class allows to access the blockchain and read data - from it + """This class allows to access the blockchain and read data + from it - :param instance blockchain_instance: instance to use when accesing a RPC - :param str mode: (default) Irreversible block (``irreversible``) or - actual head block (``head``) - :param int max_block_wait_repetition: (default) 3 maximum wait time for - next block ismax_block_wait_repetition * block_interval + :param instance blockchain_instance: instance to use when accesing a RPC + :param str mode: (default) Irreversible block (``irreversible``) or + actual head block (``head``) + :param int max_block_wait_repetition: (default) 3 maximum wait time for + next block ismax_block_wait_repetition * block_interval - This class let's you deal with blockchain related data and methods. + This class let's you deal with blockchain related data and methods. """ def __init__( @@ -46,13 +46,12 @@ def is_irreversible_mode(self): return self.mode == "last_irreversible_block_num" def info(self): - """ This call returns the *dynamic global properties* - """ + """This call returns the *dynamic global properties*""" return self.blockchain.rpc.get_dynamic_global_properties() def chainParameters(self): - """ The blockchain parameters, such as fees, and committee-controlled - parameters are returned here + """The blockchain parameters, such as fees, and committee-controlled + parameters are returned here """ if not self._parameters: self.update_chain_parameters() @@ -62,59 +61,56 @@ def update_chain_parameters(self): self._parameters = self.config()["parameters"] def get_network(self): - """ Identify the network + """Identify the network - :returns: Network parameters - :rtype: dict + :returns: Network parameters + :rtype: dict """ return self.blockchain.rpc.get_network() def get_chain_properties(self): - """ Return chain properties - """ + """Return chain properties""" return self.blockchain.rpc.get_chain_properties() def config(self): - """ Returns object 2.0.0 - """ + """Returns object 2.0.0""" return self.blockchain.rpc.get_object("2.0.0") def get_current_block_num(self): - """ This call returns the current block + """This call returns the current block - .. note:: The block number returned depends on the ``mode`` used - when instanciating from this class. + .. note:: The block number returned depends on the ``mode`` used + when instanciating from this class. """ return self.info().get(self.mode) def get_current_block(self): - """ This call returns the current block + """This call returns the current block - .. note:: The block number returned depends on the ``mode`` used - when instanciating from this class. + .. note:: The block number returned depends on the ``mode`` used + when instanciating from this class. """ return self.block_class( self.get_current_block_num(), blockchain_instance=self.blockchain ) def get_block_interval(self): - """ This call returns the block interval - """ + """This call returns the block interval""" return self.chainParameters().get("block_interval") def block_time(self, block_num): - """ Returns a datetime of the block with the given block - number. + """Returns a datetime of the block with the given block + number. - :param int block_num: Block number + :param int block_num: Block number """ return self.block_class(block_num, blockchain_instance=self.blockchain).time() def block_timestamp(self, block_num): - """ Returns the timestamp of the block with the given block - number. + """Returns the timestamp of the block with the given block + number. - :param int block_num: Block number + :param int block_num: Block number """ return int( self.block_class(block_num, blockchain_instance=self.blockchain) @@ -123,13 +119,13 @@ def block_timestamp(self, block_num): ) def blocks(self, start=None, stop=None): - """ Yields blocks starting from ``start``. + """Yields blocks starting from ``start``. - :param int start: Starting block - :param int stop: Stop at this block - :param str mode: We here have the choice between - "head" (the last block) and "irreversible" (the block that is - confirmed by 2/3 of all block producers and is thus irreversible) + :param int start: Starting block + :param int stop: Stop at this block + :param str mode: We here have the choice between + "head" (the last block) and "irreversible" (the block that is + confirmed by 2/3 of all block producers and is thus irreversible) """ # Let's find out how often blocks are generated! self.block_interval = self.get_block_interval() @@ -162,15 +158,15 @@ def blocks(self, start=None, stop=None): time.sleep(self.block_interval) def wait_for_and_get_block(self, block_number, blocks_waiting_for=None): - """ Get the desired block from the chain, if the current head block is - smaller (for both head and irreversible) then we wait, but a - maxmimum of blocks_waiting_for * max_block_wait_repetition time - before failure. - - :param int block_number: desired block number - :param int blocks_waiting_for: (default) difference between - block_number and current head how many blocks we are willing to - wait, positive int + """Get the desired block from the chain, if the current head block is + smaller (for both head and irreversible) then we wait, but a + maxmimum of blocks_waiting_for * max_block_wait_repetition time + before failure. + + :param int block_number: desired block number + :param int blocks_waiting_for: (default) difference between + block_number and current head how many blocks we are willing to + wait, positive int """ if not blocks_waiting_for: blocks_waiting_for = max(1, block_number - self.get_current_block_num()) @@ -195,18 +191,18 @@ def wait_for_and_get_block(self, block_number, blocks_waiting_for=None): return block def ops(self, start=None, stop=None, **kwargs): - """ Yields all operations (excluding virtual operations) starting from - ``start``. - - :param int start: Starting block - :param int stop: Stop at this block - :param str mode: We here have the choice between - "head" (the last block) and "irreversible" (the block that is - confirmed by 2/3 of all block producers and is thus irreversible) - :param bool only_virtual_ops: Only yield virtual operations - - This call returns a list that only carries one operation and - its type! + """Yields all operations (excluding virtual operations) starting from + ``start``. + + :param int start: Starting block + :param int stop: Stop at this block + :param str mode: We here have the choice between + "head" (the last block) and "irreversible" (the block that is + confirmed by 2/3 of all block producers and is thus irreversible) + :param bool only_virtual_ops: Only yield virtual operations + + This call returns a list that only carries one operation and + its type! """ for block in self.blocks(start=start, stop=stop, **kwargs): @@ -221,20 +217,20 @@ def ops(self, start=None, stop=None, **kwargs): } def stream(self, opNames=[], *args, **kwargs): - """ Yield specific operations (e.g. comments) only - - :param array opNames: List of operations to filter for - :param int start: Start at this block - :param int stop: Stop at this block - :param str mode: We here have the choice between - * "head": the last block - * "irreversible": the block that is confirmed by 2/3 of all - block producers and is thus irreversible! - - The dict output is formated such that ``type`` caries the - operation type, timestamp and block_num are taken from the - block the operation was stored in and the other key depend - on the actualy operation. + """Yield specific operations (e.g. comments) only + + :param array opNames: List of operations to filter for + :param int start: Start at this block + :param int stop: Stop at this block + :param str mode: We here have the choice between + * "head": the last block + * "irreversible": the block that is confirmed by 2/3 of all + block producers and is thus irreversible! + + The dict output is formated such that ``type`` caries the + operation type, timestamp and block_num are taken from the + block the operation was stored in and the other key depend + on the actualy operation. """ for op in self.ops(**kwargs): if not opNames or op["op"][0] in opNames: @@ -247,20 +243,20 @@ def stream(self, opNames=[], *args, **kwargs): yield r def awaitTxConfirmation(self, transaction, limit=10): - """ Returns the transaction as seen by the blockchain after being - included into a block - - .. note:: If you want instant confirmation, you need to instantiate - class:`.blockchain.Blockchain` with - ``mode="head"``, otherwise, the call will wait until - confirmed in an irreversible block. - - .. note:: This method returns once the blockchain has included a - transaction with the **same signature**. Even though the - signature is not usually used to identify a transaction, - it still cannot be forfeited and is derived from the - transaction contented and thus identifies a transaction - uniquely. + """Returns the transaction as seen by the blockchain after being + included into a block + + .. note:: If you want instant confirmation, you need to instantiate + class:`.blockchain.Blockchain` with + ``mode="head"``, otherwise, the call will wait until + confirmed in an irreversible block. + + .. note:: This method returns once the blockchain has included a + transaction with the **same signature**. Even though the + signature is not usually used to identify a transaction, + it still cannot be forfeited and is derived from the + transaction contented and thus identifies a transaction + uniquely. """ counter = 0 for block in self.blocks(): @@ -272,11 +268,11 @@ def awaitTxConfirmation(self, transaction, limit=10): raise Exception("The operation has not been added after 10 blocks!") def get_all_accounts(self, start="", stop="", steps=1e3, **kwargs): - """ Yields account names between start and stop. + """Yields account names between start and stop. - :param str start: Start at this account name - :param str stop: Stop at this account name - :param int steps: Obtain ``steps`` ret with a single call from RPC + :param str start: Start at this account name + :param str stop: Stop at this account name + :param int steps: Obtain ``steps`` ret with a single call from RPC """ lastname = start while True: diff --git a/graphenecommon/blockchainobject.py b/graphenecommon/blockchainobject.py index bf4b679a..209594a3 100644 --- a/graphenecommon/blockchainobject.py +++ b/graphenecommon/blockchainobject.py @@ -8,8 +8,8 @@ class Caching: - """ This class implements a few common methods that are used to - either cache lists or dicts + """This class implements a few common methods that are used to + either cache lists or dicts """ __caching_args = set() @@ -43,13 +43,11 @@ def _store_items(self, key=None): self._fetched = True def incached(self, id): - """ Is an element cached? - """ + """Is an element cached?""" return id in self._cache def getfromcache(self, id): - """ Get an element from the cache explicitly - """ + """Get an element from the cache explicitly""" return self._cache.get(id, None) def __getitem__(self, key): @@ -58,8 +56,8 @@ def __getitem__(self, key): return dict.__getitem__(self, key) def items(self): - """ This overwrites items() so that refresh() is called if the - object is not already fetched + """This overwrites items() so that refresh() is called if the + object is not already fetched """ if not self._fetched: self.refresh() @@ -75,24 +73,23 @@ def __repr__(self): @classmethod def clear_cache(cls): - """ Clear/Reset the entire Cache - """ + """Clear/Reset the entire Cache""" cls._cache = ObjectCacheInMemory() __str__ = __repr__ class BlockchainObjects(Caching, list): - """ This class is used internally to store **lists** of objects and - deal with the cache and indexing thereof. + """This class is used internally to store **lists** of objects and + deal with the cache and indexing thereof. """ identifier = None def refresh(self, *args, **kwargs): - """ Interface that needs to be implemented. This method is - called when an object is requested that has not yet been - fetched/stored + """Interface that needs to be implemented. This method is + called when an object is requested that has not yet been + fetched/stored """ raise NotImplementedError @@ -120,17 +117,17 @@ def _cache_key(self, key=""): return self.__class__.__name__ def store(self, data, key=None, *args, **kwargs): - """ Cache the list + """Cache the list - :param list data: List of objects to cache + :param list data: List of objects to cache """ list.__init__(self, data) self._store_items(self._cache_key(key)) @classmethod def cache_objects(cls, data, key=None): - """ This classmethod allows to feed multiple objects into the - cache is is mostly used for testing + """This classmethod allows to feed multiple objects into the + cache is is mostly used for testing """ return cls._import(data, key) @@ -142,13 +139,12 @@ def _import(cls, data, key=None): # legacy def cache(self, key): - """ (legacy) store the current object with key ``key``. - """ + """(legacy) store the current object with key ``key``.""" self.store(self, key) def __getitem__(self, key): - """ Since we've overwriten __getitem__ in cache and inherit from there, - we need to make sure we use `list` here instead of `dict`. + """Since we've overwriten __getitem__ in cache and inherit from there, + we need to make sure we use `list` here instead of `dict`. """ if not self._fetched: self.refresh() @@ -156,9 +152,9 @@ def __getitem__(self, key): class BlockchainObject(Caching, dict): - """ This class deals with objects from graphene-based blockchains. - It is used to validate object ids, store entire objects in - the cache and deal with indexing thereof. + """This class deals with objects from graphene-based blockchains. + It is used to validate object ids, store entire objects in + the cache and deal with indexing thereof. """ space_id = 1 @@ -217,17 +213,17 @@ def __init__(self, data, klass=None, lazy=False, use_cache=True, *args, **kwargs self._store_item() def store(self, data, key="id"): - """ Cache the list + """Cache the list - :param list data: List of objects to cache + :param list data: List of objects to cache """ dict.__init__(self, data) self._store_item(key) @classmethod def cache_object(cls, data, key=None): - """ This classmethod allows to feed an object into the - cache is is mostly used for testing + """This classmethod allows to feed an object into the + cache is is mostly used for testing """ return cls._import(data, key) @@ -239,12 +235,12 @@ def _import(cls, data, key=None): @staticmethod def objectid_valid(i): - """ Test if a string looks like a regular object id of the - form::: + """Test if a string looks like a regular object id of the + form::: - xxxx.yyyyy.zzzz + xxxx.yyyyy.zzzz - with those being numbers. + with those being numbers. """ if "." not in i: return False @@ -258,13 +254,12 @@ def objectid_valid(i): return False def test_valid_objectid(self, i): - """ Alias for objectid_valid - """ + """Alias for objectid_valid""" return self.objectid_valid(i) def testid(self, id): - """ In contrast to validity, this method tests if the objectid - matches the type_id provided in self.type_id or self.type_ids + """In contrast to validity, this method tests if the objectid + matches the type_id provided in self.type_id or self.type_ids """ parts = id.split(".") if not self.type_id: @@ -282,13 +277,13 @@ def testid(self, id): class Object(BlockchainObject, AbstractBlockchainInstanceProvider): - """ This class is a basic class that allows to obtain any object - from the blockchyin by fetching it through the API + """This class is a basic class that allows to obtain any object + from the blockchyin by fetching it through the API """ def refresh(self): - """ This is the refresh method that overloads the prototype in - BlockchainObject. + """This is the refresh method that overloads the prototype in + BlockchainObject. """ dict.__init__( self, diff --git a/graphenecommon/chain.py b/graphenecommon/chain.py index a4018791..382a68ba 100644 --- a/graphenecommon/chain.py +++ b/graphenecommon/chain.py @@ -67,8 +67,7 @@ def __init__( # RPC # ------------------------------------------------------------------------- def connect(self, node="", rpcuser="", rpcpassword="", **kwargs): - """ Connect to blockchain network (internal use only) - """ + """Connect to blockchain network (internal use only)""" if not node: if "node" in self.config: node = self.config["node"] @@ -91,27 +90,24 @@ def is_connected(self): # ------------------------------------------------------------------------- @property def prefix(self): - """ Contains the prefix of the blockchain - """ + """Contains the prefix of the blockchain""" return self.rpc.chain_params["prefix"] def set_blocking(self, block=True): - """ This sets a flag that forces the broadcast to block until the - transactions made it into a block + """This sets a flag that forces the broadcast to block until the + transactions made it into a block """ self.blocking = block def info(self): - """ Returns the global properties - """ + """Returns the global properties""" return self.rpc.get_dynamic_global_properties() # ------------------------------------------------------------------------- # Wallet # ------------------------------------------------------------------------- def set_default_account(self, account): - """ Set the default account to be used - """ + """Set the default account to be used""" self.account_class(account) self.config["default_account"] = account @@ -119,26 +115,24 @@ def newWallet(self, pwd): return self.new_wallet(pwd) def new_wallet(self, pwd): - """ Create a new wallet. This method is basically only calls - :func:`wallet.Wallet.create`. + """Create a new wallet. This method is basically only calls + :func:`wallet.Wallet.create`. - :param str pwd: Password to use for the new wallet - :raises exceptions.WalletExists: if there is already a - wallet created + :param str pwd: Password to use for the new wallet + :raises exceptions.WalletExists: if there is already a + wallet created """ return self.wallet.create(pwd) def unlock(self, *args, **kwargs): - """ Unlock the internal wallet - """ + """Unlock the internal wallet""" return self.wallet.unlock(*args, **kwargs) # ------------------------------------------------------------------------- # Shared instance interface # ------------------------------------------------------------------------- def set_shared_instance(self): - """ This method allows to set the current instance as default - """ + """This method allows to set the current instance as default""" # self._sharedInstance.instance = self log.warning( DeprecationWarning( @@ -151,35 +145,35 @@ def set_shared_instance(self): # General transaction/operation stuff # ------------------------------------------------------------------------- def finalizeOp(self, ops, account, permission, **kwargs): - """ This method obtains the required private keys if present in - the wallet, finalizes the transaction, signs it and - broadacasts it - - :param operation ops: The operation (or list of operaions) to - broadcast - :param operation account: The account that authorizes the - operation - :param string permission: The required permission for - signing (active, owner, posting) - :param object append_to: This allows to provide an instance of - ProposalsBuilder (see :func:`new_proposal`) or - TransactionBuilder (see :func:`new_tx()`) to specify - where to put a specific operation. - - ... note:: ``append_to`` is exposed to every method used in the - this class - - ... note:: - - If ``ops`` is a list of operation, they all need to be - signable by the same key! Thus, you cannot combine ops - that require active permission with ops that require - posting permission. Neither can you use different - accounts for different operations! - - ... note:: This uses ``txbuffer`` as instance of - :class:`transactionbuilder.TransactionBuilder`. - You may want to use your own txbuffer + """This method obtains the required private keys if present in + the wallet, finalizes the transaction, signs it and + broadacasts it + + :param operation ops: The operation (or list of operaions) to + broadcast + :param operation account: The account that authorizes the + operation + :param string permission: The required permission for + signing (active, owner, posting) + :param object append_to: This allows to provide an instance of + ProposalsBuilder (see :func:`new_proposal`) or + TransactionBuilder (see :func:`new_tx()`) to specify + where to put a specific operation. + + ... note:: ``append_to`` is exposed to every method used in the + this class + + ... note:: + + If ``ops`` is a list of operation, they all need to be + signable by the same key! Thus, you cannot combine ops + that require active permission with ops that require + posting permission. Neither can you use different + accounts for different operations! + + ... note:: This uses ``txbuffer`` as instance of + :class:`transactionbuilder.TransactionBuilder`. + You may want to use your own txbuffer """ if "append_to" in kwargs and kwargs["append_to"]: if self.proposer: @@ -236,13 +230,13 @@ def finalizeOp(self, ops, account, permission, **kwargs): return self.txbuffer.broadcast() def sign(self, tx=None, wifs=[]): - """ Sign a provided transaction witht he provided key(s) + """Sign a provided transaction witht he provided key(s) - :param dict tx: The transaction to be signed and returned - :param string wifs: One or many wif keys to use for signing - a transaction. If not present, the keys will be loaded - from the wallet as defined in "missing_signatures" key - of the transactions. + :param dict tx: The transaction to be signed and returned + :param string wifs: One or many wif keys to use for signing + a transaction. If not present, the keys will be loaded + from the wallet as defined in "missing_signatures" key + of the transactions. """ if tx: txbuffer = self.transactionbuilder_class(tx, blockchain_instance=self) @@ -254,9 +248,9 @@ def sign(self, tx=None, wifs=[]): return txbuffer.json() def broadcast(self, tx=None): - """ Broadcast a transaction to the Blockchain + """Broadcast a transaction to the Blockchain - :param tx tx: Signed transaction to broadcast + :param tx tx: Signed transaction to broadcast """ if tx: # If tx is provided, we broadcast the tx @@ -271,26 +265,23 @@ def broadcast(self, tx=None): # ------------------------------------------------------------------------- @property def txbuffer(self): - """ Returns the currently active tx buffer - """ + """Returns the currently active tx buffer""" return self.tx() @property def propbuffer(self): - """ Return the default proposal buffer - """ + """Return the default proposal buffer""" return self.proposal() def tx(self): - """ Returns the default transaction buffer - """ + """Returns the default transaction buffer""" return self._txbuffers[0] def proposal(self, proposer=None, proposal_expiration=None, proposal_review=None): - """ Return the default proposal buffer + """Return the default proposal buffer - ... note:: If any parameter is set, the default proposal - parameters will be changed! + ... note:: If any parameter is set, the default proposal + parameters will be changed! """ if not self._propbuffer: return self.new_proposal( @@ -339,9 +330,9 @@ def new_proposal( return proposal def new_tx(self, *args, **kwargs): - """ Let's obtain a new txbuffer + """Let's obtain a new txbuffer - :returns int txid: id of the new txbuffer + :returns int txid: id of the new txbuffer """ builder = self.transactionbuilder_class( *args, blockchain_instance=self, **kwargs @@ -360,6 +351,5 @@ def clear(self): # self.new_proposal() def clear_cache(self): - """ Clear Caches - """ + """Clear Caches""" self.blockchainobject_class.clear_cache() diff --git a/graphenecommon/committee.py b/graphenecommon/committee.py index bfbd16c7..a3a9941c 100644 --- a/graphenecommon/committee.py +++ b/graphenecommon/committee.py @@ -5,11 +5,11 @@ class Committee(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Read data about a Committee Member in the chain + """Read data about a Committee Member in the chain - :param str member: Name of the Committee Member - :param instance blockchain_instance: instance to use when accesing a RPC - :param bool lazy: Use lazy loading + :param str member: Name of the Committee Member + :param instance blockchain_instance: instance to use when accesing a RPC + :param bool lazy: Use lazy loading """ diff --git a/graphenecommon/exceptions.py b/graphenecommon/exceptions.py index 2dc2f13d..87293afe 100644 --- a/graphenecommon/exceptions.py +++ b/graphenecommon/exceptions.py @@ -1,65 +1,58 @@ # -*- coding: utf-8 -*- class WalletExists(Exception): - """ A wallet has already been created and requires a password to be - unlocked by means of :func:`wallet.unlock`. + """A wallet has already been created and requires a password to be + unlocked by means of :func:`wallet.unlock`. """ pass class WalletLocked(Exception): - """ Wallet is locked - """ + """Wallet is locked""" pass class OfflineHasNoRPCException(Exception): - """ When in offline mode, we don't have RPC - """ + """When in offline mode, we don't have RPC""" pass class NoWalletException(Exception): - """ No Wallet could be found, please use :func:`wallet.create` to - create a new wallet + """No Wallet could be found, please use :func:`wallet.create` to + create a new wallet """ pass class KeyNotFound(Exception): - """ Key not found - """ + """Key not found""" pass class KeyAlreadyInStoreException(Exception): - """ The key is already stored in the store - """ + """The key is already stored in the store""" pass class InvalidWifError(Exception): - """ The provided private Key has an invalid format - """ + """The provided private Key has an invalid format""" pass class WorkerDoesNotExistsException(Exception): - """ Worker does not exist - """ + """Worker does not exist""" pass class WitnessDoesNotExistsException(Exception): - """ The witness does not exist - """ + """The witness does not exist""" pass @@ -105,8 +98,7 @@ class InvalidMessageSignature(Exception): class WrongMemoKey(Exception): - """ The memo provided is not equal the one on the blockchain - """ + """The memo provided is not equal the one on the blockchain""" pass diff --git a/graphenecommon/genesisbalance.py b/graphenecommon/genesisbalance.py index f5f2f665..0d1b58e2 100644 --- a/graphenecommon/genesisbalance.py +++ b/graphenecommon/genesisbalance.py @@ -5,18 +5,18 @@ class GenesisBalance(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Deals with Assets of the network. - - :param str Asset: Symbol name or object id of an asset - :param bool lazy: Lazy loading - :param bool full: Also obtain bitasset-data and dynamic asset data - :param instance blockchain_instance: instance to use when accesing a RPC - :returns: All data of an asset - :rtype: dict - - .. note:: This class comes with its own caching function to reduce the - load on the API server. Instances of this class can be - refreshed with ``Asset.refresh()``. + """Deals with Assets of the network. + + :param str Asset: Symbol name or object id of an asset + :param bool lazy: Lazy loading + :param bool full: Also obtain bitasset-data and dynamic asset data + :param instance blockchain_instance: instance to use when accesing a RPC + :returns: All data of an asset + :rtype: dict + + .. note:: This class comes with its own caching function to reduce the + load on the API server. Instances of this class can be + refreshed with ``Asset.refresh()``. """ def __init__(self, *args, **kwargs): @@ -39,12 +39,12 @@ def refresh(self): ) def claim(self, account=None, **kwargs): - """ Claim a balance from the genesis block + """Claim a balance from the genesis block - :param str balance_id: The identifier that identifies the balance - to claim (1.15.x) - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) + :param str balance_id: The identifier that identifies the balance + to claim (1.15.x) + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) """ if not account: if "default_account" in self.blockchain.config: @@ -109,8 +109,8 @@ def claim(self, account=None, **kwargs): class GenesisBalances(list, AbstractBlockchainInstanceProvider): - """ List genesis balances that can be claimed from the - keys in the wallet + """List genesis balances that can be claimed from the + keys in the wallet """ def __init__(self, **kwargs): diff --git a/graphenecommon/instance.py b/graphenecommon/instance.py index 29dcfb0f..23443c21 100644 --- a/graphenecommon/instance.py +++ b/graphenecommon/instance.py @@ -3,18 +3,17 @@ class SharedInstance: - """ This class merely offers a singelton for the Blockchain Instance - """ + """This class merely offers a singelton for the Blockchain Instance""" instance = None config = {} class AbstractBlockchainInstanceProvider: - """ This is a class that allows compatibility with previous - naming conventions. It will extract 'blockchain_instance' - from the key word arguments and ensure that self.blockchain - contains an instance of the main chain instance + """This is a class that allows compatibility with previous + naming conventions. It will extract 'blockchain_instance' + from the key word arguments and ensure that self.blockchain + contains an instance of the main chain instance """ _sharedInstance = SharedInstance @@ -42,13 +41,11 @@ def __init__(self, *args, **kwargs): return NewClass def get_instance_class(self): - """ Should return the Chain instance class, e.g. `bitshares.BitShares` - """ + """Should return the Chain instance class, e.g. `bitshares.BitShares`""" raise NotImplementedError def define_classes(self): - """ Needs to define instance variables that provide classes - """ + """Needs to define instance variables that provide classes""" raise NotImplementedError @property @@ -61,14 +58,13 @@ def blockchain(self): @property def chain(self): - """ Short form for blockchain (for the lazy) - """ + """Short form for blockchain (for the lazy)""" return self.blockchain def shared_blockchain_instance(self): - """ This method will initialize ``SharedInstance.instance`` and return it. - The purpose of this method is to have offer single default - instance that can be reused by multiple classes. + """This method will initialize ``SharedInstance.instance`` and return it. + The purpose of this method is to have offer single default + instance that can be reused by multiple classes. """ if not self._sharedInstance.instance: klass = self.get_instance_class() @@ -77,10 +73,10 @@ def shared_blockchain_instance(self): @classmethod def set_shared_blockchain_instance(cls, instance): - """ This method allows us to override default instance for all - users of ``SharedInstance.instance``. + """This method allows us to override default instance for all + users of ``SharedInstance.instance``. - :param chaininstance instance: Chain instance + :param chaininstance instance: Chain instance """ cls._sharedInstance.instance = instance @@ -88,15 +84,14 @@ def set_shared_blockchain_instance(cls, instance): # Shared instance interface # ------------------------------------------------------------------------- def set_shared_instance(self): - """ This method allows to set the current instance as default - """ + """This method allows to set the current instance as default""" self._sharedInstance.instance = self @classmethod def set_shared_config(cls, config): - """ This allows to set a config that will be used when calling - ``shared_blockchain_instance`` and allows to define the configuration - without requiring to actually create an instance + """This allows to set a config that will be used when calling + ``shared_blockchain_instance`` and allows to define the configuration + without requiring to actually create an instance """ assert isinstance(config, dict) cls._sharedInstance.config.update(config) diff --git a/graphenecommon/memo.py b/graphenecommon/memo.py index 64e8136c..35e10cb4 100644 --- a/graphenecommon/memo.py +++ b/graphenecommon/memo.py @@ -6,41 +6,41 @@ class Memo(AbstractBlockchainInstanceProvider): - """ Deals with Memos that are attached to a transfer + """Deals with Memos that are attached to a transfer - :param .account.Account from_account: Account that has sent - the memo - :param .account.Account to_account: Account that has received - the memo - :param instance blockchain_instance: instance to use when accesing a RPC + :param .account.Account from_account: Account that has sent + the memo + :param .account.Account to_account: Account that has received + the memo + :param instance blockchain_instance: instance to use when accesing a RPC - A memo is encrypted with a shared secret derived from a private key of - the sender and a public key of the receiver. Due to the underlying - mathematics, the same shared secret can be derived by the private key - of the receiver and the public key of the sender. The encrypted message - is perturbed by a nonce that is part of the transmitted message. + A memo is encrypted with a shared secret derived from a private key of + the sender and a public key of the receiver. Due to the underlying + mathematics, the same shared secret can be derived by the private key + of the receiver and the public key of the sender. The encrypted message + is perturbed by a nonce that is part of the transmitted message. - .. code-block:: python + .. code-block:: python - from .memo import Memo - m = Memo("from-account", "to-account") - m.blockchain.wallet.unlock("secret") - enc = (m.encrypt("foobar")) - print(enc) - >> {'nonce': '17329630356955254641', 'message': '8563e2bb2976e0217806d642901a2855'} - print(m.decrypt(enc)) - >> foobar + from .memo import Memo + m = Memo("from-account", "to-account") + m.blockchain.wallet.unlock("secret") + enc = (m.encrypt("foobar")) + print(enc) + >> {'nonce': '17329630356955254641', 'message': '8563e2bb2976e0217806d642901a2855'} + print(m.decrypt(enc)) + >> foobar - To decrypt a memo, simply use + To decrypt a memo, simply use - .. code-block:: python + .. code-block:: python - from memo import Memo - m = Memo() - m.blockchain.wallet.unlock("secret") - print(memo.decrypt(op_data["memo"])) + from memo import Memo + m = Memo() + m.blockchain.wallet.unlock("secret") + print(memo.decrypt(op_data["memo"])) - if ``op_data`` being the payload of a transfer operation. + if ``op_data`` being the payload of a transfer operation. """ @@ -60,17 +60,16 @@ def __init__(self, from_account=None, to_account=None, **kwargs): ) def unlock_wallet(self, *args, **kwargs): - """ Unlock the library internal wallet - """ + """Unlock the library internal wallet""" self.blockchain.wallet.unlock(*args, **kwargs) return self def encrypt(self, message): - """ Encrypt a memo + """Encrypt a memo - :param str message: clear text memo message - :returns: encrypted message - :rtype: str + :param str message: clear text memo message + :returns: encrypted message + :rtype: str """ if not message: return None @@ -112,11 +111,11 @@ def encrypt(self, message): } def decrypt(self, message): - """ Decrypt a message + """Decrypt a message - :param dict message: encrypted memo message - :returns: decrypted message - :rtype: str + :param dict message: encrypted memo message + :returns: decrypted message + :rtype: str """ if not message: return None diff --git a/graphenecommon/message.py b/graphenecommon/message.py index ea3c75bb..873aee95 100644 --- a/graphenecommon/message.py +++ b/graphenecommon/message.py @@ -21,8 +21,7 @@ class MessageV1(AbstractBlockchainInstanceProvider): - """ Allow to sign and verify Messages that are sigend with a private key - """ + """Allow to sign and verify Messages that are sigend with a private key""" MESSAGE_SPLIT = ( "-----BEGIN GRAPHENE SIGNED MESSAGE-----", @@ -62,13 +61,13 @@ def __init__(self, message, *args, **kwargs): self.plain_message = None def sign(self, account=None, **kwargs): - """ Sign a message with an account's memo key + """Sign a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) - :raises ValueError: If not account for signing is provided + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) + :raises ValueError: If not account for signing is provided - :returns: the signed message encapsulated in a known format + :returns: the signed message encapsulated in a known format """ if not account: if "default_account" in self.blockchain.config: @@ -110,13 +109,13 @@ def sign(self, account=None, **kwargs): ) def verify(self, **kwargs): - """ Verify a message with an account's memo key + """Verify a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) - :returns: True if the message is verified successfully - :raises InvalidMessageSignature if the signature is not ok + :returns: True if the message is verified successfully + :raises InvalidMessageSignature if the signature is not ok """ # Split message into its parts parts = re.split("|".join(self.MESSAGE_SPLIT), self.message) @@ -191,8 +190,7 @@ def verify(self, **kwargs): class MessageV2(AbstractBlockchainInstanceProvider): - """ Allow to sign and verify Messages that are sigend with a private key - """ + """Allow to sign and verify Messages that are sigend with a private key""" def __init__(self, message, *args, **kwargs): self.define_classes() @@ -206,13 +204,13 @@ def __init__(self, message, *args, **kwargs): self.plain_message = None def sign(self, account=None, **kwargs): - """ Sign a message with an account's memo key + """Sign a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) - :raises ValueError: If not account for signing is provided + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) + :raises ValueError: If not account for signing is provided - :returns: the signed message encapsulated in a known format + :returns: the signed message encapsulated in a known format """ if not account: if "default_account" in self.blockchain.config: @@ -246,13 +244,13 @@ def sign(self, account=None, **kwargs): return dict(signed=enc_message, payload=payload, signature=signature) def verify(self, **kwargs): - """ Verify a message with an account's memo key + """Verify a message with an account's memo key - :param str account: (optional) the account that owns the bet - (defaults to ``default_account``) + :param str account: (optional) the account that owns the bet + (defaults to ``default_account``) - :returns: True if the message is verified successfully - :raises InvalidMessageSignature if the signature is not ok + :returns: True if the message is verified successfully + :raises InvalidMessageSignature if the signature is not ok """ if not isinstance(self.message, dict): try: diff --git a/graphenecommon/objectcache.py b/graphenecommon/objectcache.py index e51624f2..f5c64d95 100644 --- a/graphenecommon/objectcache.py +++ b/graphenecommon/objectcache.py @@ -36,9 +36,9 @@ def __str__(self): class ObjectCacheInMemory(ExpiringDict, ObjectCacheInterface): - """ This class implements an object/dict cache that comes with an - expiration. Expired items are removed from the cache. The cache has a - max_length. + """This class implements an object/dict cache that comes with an + expiration. Expired items are removed from the cache. The cache has a + max_length. """ def __init__( @@ -64,11 +64,9 @@ def __init__( ) def set_expiration(self, expiration): - """ Set new default expiration time in seconds (default: 10s) - """ + """Set new default expiration time in seconds (default: 10s)""" self.default_expiration = expiration def get_expiration(self): - """ Return the default expiration - """ + """Return the default expiration""" return self.default_expiration diff --git a/graphenecommon/price.py b/graphenecommon/price.py index 56d17d8d..0ee150e2 100644 --- a/graphenecommon/price.py +++ b/graphenecommon/price.py @@ -6,57 +6,57 @@ class Price(dict, AbstractBlockchainInstanceProvider): - """ This class deals with all sorts of prices of any pair of assets to - simplify dealing with the tuple:: + """This class deals with all sorts of prices of any pair of assets to + simplify dealing with the tuple:: - (quote, base) + (quote, base) - each being an instance of :class:`.amount.Amount`. The - amount themselves define the price. + each being an instance of :class:`.amount.Amount`. The + amount themselves define the price. - .. note:: + .. note:: - The price (floating) is derived as ``base/quote`` + The price (floating) is derived as ``base/quote`` - :param list args: Allows to deal with different representations of a price - :param asset.Asset base: Base asset - :param asset.Asset quote: Quote asset - :param instance blockchain_instance: instance to use when accesing a RPC - :returns: All data required to represent a price - :rtype: dict + :param list args: Allows to deal with different representations of a price + :param asset.Asset base: Base asset + :param asset.Asset quote: Quote asset + :param instance blockchain_instance: instance to use when accesing a RPC + :returns: All data required to represent a price + :rtype: dict - Way to obtain a proper instance: + Way to obtain a proper instance: - * ``args`` is a str with a price and two assets - * ``args`` can be a floating number and ``base`` and ``quote`` being instances of :class:`.asset.Asset` - * ``args`` can be a floating number and ``base`` and ``quote`` being instances of ``str`` - * ``args`` can be dict with keys ``price``, ``base``, and ``quote`` (*graphene balances*) - * ``args`` can be dict with keys ``base`` and ``quote`` - * ``args`` can be dict with key ``receives`` (filled orders) - * ``args`` being a list of ``[quote, base]`` both being instances of :class:`.amount.Amount` - * ``args`` being a list of ``[quote, base]`` both being instances of ``str`` (``amount symbol``) - * ``base`` and ``quote`` being instances of :class:`.asset.Amount` + * ``args`` is a str with a price and two assets + * ``args`` can be a floating number and ``base`` and ``quote`` being instances of :class:`.asset.Asset` + * ``args`` can be a floating number and ``base`` and ``quote`` being instances of ``str`` + * ``args`` can be dict with keys ``price``, ``base``, and ``quote`` (*graphene balances*) + * ``args`` can be dict with keys ``base`` and ``quote`` + * ``args`` can be dict with key ``receives`` (filled orders) + * ``args`` being a list of ``[quote, base]`` both being instances of :class:`.amount.Amount` + * ``args`` being a list of ``[quote, base]`` both being instances of ``str`` (``amount symbol``) + * ``base`` and ``quote`` being instances of :class:`.asset.Amount` - This allows instanciations like: + This allows instanciations like: - * ``Price("0.315 USD/BTS")`` - * ``Price(0.315, base="USD", quote="BTS")`` - * ``Price(0.315, base=self.asset_class("USD"), quote=self.asset_class("BTS"))`` - * ``Price({"base": {"amount": 1, "asset_id": "1.3.0"}, "quote": {"amount": 10, "asset_id": "1.3.106"}})`` - * ``Price({"receives": {"amount": 1, "asset_id": "1.3.0"}, "pays": {"amount": 10, "asset_id": "1.3.106"}}, base_asset=self.asset_class("1.3.0"))`` - * ``Price(quote="10 GOLD", base="1 USD")`` - * ``Price("10 GOLD", "1 USD")`` - * ``Price(self.amount_class("10 GOLD"), self.amount_class("1 USD"))`` - * ``Price(1.0, "USD/GOLD")`` + * ``Price("0.315 USD/BTS")`` + * ``Price(0.315, base="USD", quote="BTS")`` + * ``Price(0.315, base=self.asset_class("USD"), quote=self.asset_class("BTS"))`` + * ``Price({"base": {"amount": 1, "asset_id": "1.3.0"}, "quote": {"amount": 10, "asset_id": "1.3.106"}})`` + * ``Price({"receives": {"amount": 1, "asset_id": "1.3.0"}, "pays": {"amount": 10, "asset_id": "1.3.106"}}, base_asset=self.asset_class("1.3.0"))`` + * ``Price(quote="10 GOLD", base="1 USD")`` + * ``Price("10 GOLD", "1 USD")`` + * ``Price(self.amount_class("10 GOLD"), self.amount_class("1 USD"))`` + * ``Price(1.0, "USD/GOLD")`` - Instances of this class can be used in regular mathematical expressions - (``+-*/%``) such as: + Instances of this class can be used in regular mathematical expressions + (``+-*/%``) such as: - .. code-block:: python + .. code-block:: python - >>> from price import Price - >>> Price("0.3314 USD/BTS") * 2 - 0.662600000 USD/BTS + >>> from price import Price + >>> Price("0.3314 USD/BTS") * 2 + 0.662600000 USD/BTS """ @@ -228,8 +228,7 @@ def __init__( raise ValueError("Couldn't parse 'Price'.") def __setitem__(self, key, value): - """ Here we set "price" if we change quote or base - """ + """Here we set "price" if we change quote or base""" dict.__setitem__(self, key, value) if ( "quote" in self and "base" in self and self["base"] and self["quote"] @@ -253,9 +252,9 @@ def symbols(self): return self["base"]["symbol"], self["quote"]["symbol"] def as_base(self, base): - """ Returns the price instance so that the base asset is ``base``. + """Returns the price instance so that the base asset is ``base``. - Note: This makes a copy of the object! + Note: This makes a copy of the object! """ if base == self["base"]["symbol"]: return self.copy() @@ -265,9 +264,9 @@ def as_base(self, base): raise InvalidAssetException def as_quote(self, quote): - """ Returns the price instance so that the quote asset is ``quote``. + """Returns the price instance so that the quote asset is ``quote``. - Note: This makes a copy of the object! + Note: This makes a copy of the object! """ if quote == self["quote"]["symbol"]: return self.copy() @@ -277,8 +276,7 @@ def as_quote(self, quote): raise InvalidAssetException def invert(self): - """ Invert the price (e.g. go from ``USD/BTS`` into ``BTS/USD``) - """ + """Invert the price (e.g. go from ``USD/BTS`` into ``BTS/USD``)""" tmp = self["quote"] self["quote"] = self["base"] self["base"] = tmp diff --git a/graphenecommon/proposal.py b/graphenecommon/proposal.py index 6e440af9..af0dc020 100644 --- a/graphenecommon/proposal.py +++ b/graphenecommon/proposal.py @@ -11,10 +11,10 @@ class Proposal(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Read data about a Proposal Balance in the chain + """Read data about a Proposal Balance in the chain - :param str id: Id of the proposal - :param instance blockchain_instance: instance to use when accesing a RPC + :param str id: Id of the proposal + :param instance blockchain_instance: instance to use when accesing a RPC """ @@ -35,8 +35,8 @@ def proposed_operations(self): @property def proposer(self): - """ Return the proposer of the proposal if available in the backend, - else returns None + """Return the proposer of the proposal if available in the backend, + else returns None """ if "proposer" in self: return self.account_class( @@ -60,10 +60,10 @@ def is_in_review(self): class Proposals(BlockchainObjects, AbstractBlockchainInstanceProvider): - """ Obtain a list of pending proposals for an account + """Obtain a list of pending proposals for an account - :param str account: Account name - :param instance blockchain_instance: instance to use when accesing a RPC + :param str account: Account name + :param instance blockchain_instance: instance to use when accesing a RPC """ def __init__(self, account, *args, **kwargs): diff --git a/graphenecommon/transactionbuilder.py b/graphenecommon/transactionbuilder.py index 84ff7aa5..63f38f8b 100644 --- a/graphenecommon/transactionbuilder.py +++ b/graphenecommon/transactionbuilder.py @@ -17,17 +17,17 @@ class ProposalBuilder(AbstractBlockchainInstanceProvider): - """ Proposal Builder allows us to construct an independent Proposal - that may later be added to an instance of TransactionBuilder - - :param str proposer: Account name of the proposing user - :param int proposal_expiration: Number seconds until the proposal is - supposed to expire - :param int proposal_review: Number of seconds for review of the - proposal - :param .transactionbuilder.TransactionBuilder: Specify - your own instance of transaction builder (optional) - :param instance blockchain_instance: Blockchain instance + """Proposal Builder allows us to construct an independent Proposal + that may later be added to an instance of TransactionBuilder + + :param str proposer: Account name of the proposing user + :param int proposal_expiration: Number seconds until the proposal is + supposed to expire + :param int proposal_review: Number of seconds for review of the + proposal + :param .transactionbuilder.TransactionBuilder: Specify + your own instance of transaction builder (optional) + :param instance blockchain_instance: Blockchain instance """ def __init__( @@ -67,9 +67,9 @@ def set_parent(self, p): self.parent = p def appendOps(self, ops, append_to=None): - """ Append op(s) to the transaction builder + """Append op(s) to the transaction builder - :param list ops: One or a list of operations + :param list ops: One or a list of operations """ if isinstance(ops, list): self.ops.extend(ops) @@ -89,8 +89,7 @@ def broadcast(self): return self.parent.broadcast() def get_parent(self): - """ This allows to referr to the actual parent of the Proposal - """ + """This allows to referr to the actual parent of the Proposal""" return self.parent def __repr__(self): @@ -99,8 +98,7 @@ def __repr__(self): ) def json(self): - """ Return the json formated version of this proposal - """ + """Return the json formated version of this proposal""" raw = self.get_raw() if not raw: return dict() @@ -110,8 +108,7 @@ def __dict__(self): return self.json() def get_raw(self): - """ Returns an instance of base "Operations" for further processing - """ + """Returns an instance of base "Operations" for further processing""" if not self.ops: return ops = [self.operations.Op_wrapper(op=o) for o in list(self.ops)] @@ -132,8 +129,8 @@ def get_raw(self): class TransactionBuilder(dict, AbstractBlockchainInstanceProvider): - """ This class simplifies the creation of transactions by adding - operations and signers. + """This class simplifies the creation of transactions by adding + operations and signers. """ #: Some graphene chains support more than just owner, active (e.g. steem also has 'posting') @@ -212,21 +209,19 @@ def __getitem__(self, key): return dict(self).__getitem__(key) def get_parent(self): - """ TransactionBuilders don't have parents, they are their own parent - """ + """TransactionBuilders don't have parents, they are their own parent""" return self def json(self): - """ Show the transaction as plain json - """ + """Show the transaction as plain json""" if not self._is_constructed() or self._is_require_reconstruction(): self.constructTx() return dict(self) def appendOps(self, ops, append_to=None): - """ Append op(s) to the transaction builder + """Append op(s) to the transaction builder - :param list ops: One or a list of operations + :param list ops: One or a list of operations """ if isinstance(ops, list): self.ops.extend(ops) @@ -284,11 +279,11 @@ def _fetchkeys(self, account, perm, level=0, required_treshold=1): return r def appendSigner(self, accounts, permission): - """ Try to obtain the wif key from the wallet by telling which account - and permission is supposed to sign the transaction + """Try to obtain the wif key from the wallet by telling which account + and permission is supposed to sign the transaction - :param str,list,tuple,set accounts: accounts to sign transaction with - :param str permission: type of permission, e.g. "active", "owner" etc + :param str,list,tuple,set accounts: accounts to sign transaction with + :param str permission: type of permission, e.g. "active", "owner" etc """ assert permission in self.permission_types, "Invalid permission" @@ -330,8 +325,7 @@ def appendSigner(self, accounts, permission): self.signing_accounts.append(account) def appendWif(self, wif): - """ Add a wif that should be used for signing of the transaction. - """ + """Add a wif that should be used for signing of the transaction.""" if wif: try: self.privatekey_class(wif) @@ -340,8 +334,7 @@ def appendWif(self, wif): raise InvalidWifError def set_fee_asset(self, fee_asset): - """ Set asset to fee - """ + """Set asset to fee""" if isinstance(fee_asset, self.amount_class): self.fee_asset_id = fee_asset["id"] elif isinstance(fee_asset, self.asset_class): @@ -352,8 +345,8 @@ def set_fee_asset(self, fee_asset): self.fee_asset_id = "1.3.0" def add_required_fees(self, ops, asset_id="1.3.0"): - """ Auxiliary method to obtain the required fees for a set of - operations. Requires a websocket connection to a witness node! + """Auxiliary method to obtain the required fees for a set of + operations. Requires a websocket connection to a witness node! """ ws = self.blockchain.rpc fees = ws.get_required_fees([i.json() for i in ops], asset_id) @@ -378,8 +371,8 @@ def add_required_fees(self, ops, asset_id="1.3.0"): return ops def constructTx(self): - """ Construct the actual transaction and store it in the class's dict - store + """Construct the actual transaction and store it in the class's dict + store """ ops = list() for op in self.ops: @@ -423,9 +416,9 @@ def constructTx(self): self._unset_require_reconstruction() def get_block_params(self, use_head_block=False): - """ Auxiliary method to obtain ``ref_block_num`` and - ``ref_block_prefix``. Requires a websocket connection to a - witness node! + """Auxiliary method to obtain ``ref_block_num`` and + ``ref_block_prefix``. Requires a websocket connection to a + witness node! """ ws = self.blockchain.rpc dynBCParams = ws.get_dynamic_global_properties() @@ -446,13 +439,13 @@ def get_block_params(self, use_head_block=False): return ref_block_num, ref_block_prefix def sign(self): - """ Sign a provided transaction with the provided key(s) + """Sign a provided transaction with the provided key(s) - :param dict tx: The transaction to be signed and returned - :param string wifs: One or many wif keys to use for signing - a transaction. If not present, the keys will be loaded - from the wallet as defined in "missing_signatures" key - of the transactions. + :param dict tx: The transaction to be signed and returned + :param string wifs: One or many wif keys to use for signing + a transaction. If not present, the keys will be loaded + from the wallet as defined in "missing_signatures" key + of the transactions. """ self.constructTx() @@ -484,8 +477,7 @@ def sign(self): return self.tx def verify_authority(self): - """ Verify the authority of the signed transaction - """ + """Verify the authority of the signed transaction""" try: if not self.blockchain.rpc.verify_authority(self.json()): raise InsufficientAuthorityError @@ -493,9 +485,9 @@ def verify_authority(self): raise e def broadcast(self): - """ Broadcast a transaction to the blockchain network + """Broadcast a transaction to the blockchain network - :param tx tx: Signed transaction to broadcast + :param tx tx: Signed transaction to broadcast """ # Sign if not signed if not self._is_signed(): @@ -532,8 +524,7 @@ def broadcast(self): return ret def clear(self): - """ Clear the transaction builder and start from scratch - """ + """Clear the transaction builder and start from scratch""" self.ops = [] self.wifs = set() self.signing_accounts = [] @@ -544,11 +535,11 @@ def clear(self): dict.__init__(self, {}) def addSigningInformation(self, account, permission): - """ This is a private method that adds side information to a - unsigned/partial transaction in order to simplify later - signing (e.g. for multisig or coldstorage) + """This is a private method that adds side information to a + unsigned/partial transaction in order to simplify later + signing (e.g. for multisig or coldstorage) - FIXME: Does not work with owner keys! + FIXME: Does not work with owner keys! """ self.constructTx() self["blockchain"] = self.blockchain.rpc.chain_params @@ -579,9 +570,9 @@ def addSigningInformation(self, account, permission): ) def appendMissingSignatures(self): - """ Store which accounts/keys are supposed to sign the transaction + """Store which accounts/keys are supposed to sign the transaction - This method is used for an offline-signer! + This method is used for an offline-signer! """ missing_signatures = self.get("missing_signatures", []) for pub in missing_signatures: diff --git a/graphenecommon/utils.py b/graphenecommon/utils.py index 59accba7..91c4cac0 100644 --- a/graphenecommon/utils.py +++ b/graphenecommon/utils.py @@ -8,8 +8,7 @@ def formatTime(t): - """ Properly Format Time for permlinks - """ + """Properly Format Time for permlinks""" if isinstance(t, float): return datetime.utcfromtimestamp(t).strftime(timeFormat) if isinstance(t, datetime): @@ -17,8 +16,7 @@ def formatTime(t): def formatTimeString(t): - """ Properly Format Time for permlinks - """ + """Properly Format Time for permlinks""" try: return datetime.strptime(t, timeFormat) except Exception: @@ -27,12 +25,12 @@ def formatTimeString(t): def formatTimeFromNow(secs=None): - """ Properly Format Time that is `x` seconds in the future + """Properly Format Time that is `x` seconds in the future - :param int secs: Seconds to go in the future (`x>0`) or the - past (`x<0`) - :return: Properly formated time for Graphene (`%Y-%m-%dT%H:%M:%S`) - :rtype: str + :param int secs: Seconds to go in the future (`x>0`) or the + past (`x<0`) + :return: Properly formated time for Graphene (`%Y-%m-%dT%H:%M:%S`) + :rtype: str """ return datetime.utcfromtimestamp(time.time() + int(secs or 0)).strftime(timeFormat) @@ -40,7 +38,7 @@ def formatTimeFromNow(secs=None): def parse_time(block_time): """Take a string representation of time from the blockchain, and parse it - into datetime object. + into datetime object. """ return formatTimeString(block_time).replace(tzinfo=timezone.utc) diff --git a/graphenecommon/vesting.py b/graphenecommon/vesting.py index 6ee4a165..abef117a 100644 --- a/graphenecommon/vesting.py +++ b/graphenecommon/vesting.py @@ -5,10 +5,10 @@ class Vesting(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Read data about a Vesting Balance in the chain + """Read data about a Vesting Balance in the chain - :param str id: Id of the vesting balance - :param instance blockchain_instance: instance to use when accesing a RPC + :param str id: Id of the vesting balance + :param instance blockchain_instance: instance to use when accesing a RPC """ diff --git a/graphenecommon/wallet.py b/graphenecommon/wallet.py index 3e0f56a0..3d015d91 100644 --- a/graphenecommon/wallet.py +++ b/graphenecommon/wallet.py @@ -16,27 +16,27 @@ class Wallet(AbstractBlockchainInstanceProvider): - """ The wallet is meant to maintain access to private keys for - your accounts. It either uses manually provided private keys - or uses a SQLite database managed by storage.py. - - :param array,dict,string keys: Predefine the wif keys to shortcut the - wallet database - - Three wallet operation modes are possible: - - * **Wallet Database**: Here, the library loads the keys from the - locally stored wallet SQLite database (see ``storage.py``). - * **Providing Keys**: Here, you can provide the keys for - your accounts manually. All you need to do is add the wif - keys for the accounts you want to use as a simple array - using the ``keys`` parameter to your blockchain instance. - * **Force keys**: This more is for advanced users and - requires that you know what you are doing. Here, the - ``keys`` parameter is a dictionary that overwrite the - ``active``, ``owner``, ``posting`` or ``memo`` keys for - any account. This mode is only used for *foreign* - signatures! + """The wallet is meant to maintain access to private keys for + your accounts. It either uses manually provided private keys + or uses a SQLite database managed by storage.py. + + :param array,dict,string keys: Predefine the wif keys to shortcut the + wallet database + + Three wallet operation modes are possible: + + * **Wallet Database**: Here, the library loads the keys from the + locally stored wallet SQLite database (see ``storage.py``). + * **Providing Keys**: Here, you can provide the keys for + your accounts manually. All you need to do is add the wif + keys for the accounts you want to use as a simple array + using the ``keys`` parameter to your blockchain instance. + * **Force keys**: This more is for advanced users and + requires that you know what you are doing. Here, the + ``keys`` parameter is a dictionary that overwrite the + ``active``, ``owner``, ``posting`` or ``memo`` keys for + any account. This mode is only used for *foreign* + signatures! """ def __init__(self, *args, **kwargs): @@ -80,8 +80,8 @@ def rpc(self): return self.blockchain.rpc def setKeys(self, loadkeys): - """ This method is strictly only for in memory keys that are - passed to Wallet with the ``keys`` argument + """This method is strictly only for in memory keys that are + passed to Wallet with the ``keys`` argument """ log.debug("Force setting of private keys. Not using the wallet database!") if isinstance(loadkeys, dict): @@ -93,46 +93,39 @@ def setKeys(self, loadkeys): self.store.add(str(wif), pub) def is_encrypted(self): - """ Is the key store encrypted? - """ + """Is the key store encrypted?""" return self.store.is_encrypted() def unlock(self, pwd): - """ Unlock the wallet database - """ + """Unlock the wallet database""" if self.store.is_encrypted(): return self.store.unlock(pwd) def lock(self): - """ Lock the wallet database - """ + """Lock the wallet database""" if self.store.is_encrypted(): return self.store.lock() else: return False def unlocked(self): - """ Is the wallet database unlocked? - """ + """Is the wallet database unlocked?""" if self.store.is_encrypted(): return not self.store.locked() else: return True def locked(self): - """ Is the wallet database locked? - """ + """Is the wallet database locked?""" if self.store.is_encrypted(): return self.store.locked() def changePassphrase(self, new_pwd): - """ Change the passphrase for the wallet database - """ + """Change the passphrase for the wallet database""" self.masterpwd.changePassword(new_pwd) def created(self): - """ Do we have a wallet database already? - """ + """Do we have a wallet database already?""" if len(self.store.getPublicKeys()): # Already keys installed return True @@ -140,20 +133,17 @@ def created(self): return False def create(self, pwd): - """ Alias for newWallet() - """ + """Alias for newWallet()""" self.newWallet(pwd) def newWallet(self, pwd): - """ Create a new wallet database - """ + """Create a new wallet database""" if self.created(): raise WalletExists("You already have created a wallet!") self.store.unlock(pwd) def addPrivateKey(self, wif): - """ Add a private key to the wallet database - """ + """Add a private key to the wallet database""" try: pub = self.publickey_from_wif(wif) except Exception: @@ -163,30 +153,27 @@ def addPrivateKey(self, wif): self.store.add(str(wif), str(pub)) def getPrivateKeyForPublicKey(self, pub): - """ Obtain the private key for a given public key + """Obtain the private key for a given public key - :param str pub: Public Key + :param str pub: Public Key """ if str(pub) not in self.store: raise KeyNotFound return self.store.getPrivateKeyForPublicKey(str(pub)) def removePrivateKeyFromPublicKey(self, pub): - """ Remove a key from the wallet database - """ + """Remove a key from the wallet database""" self.store.delete(str(pub)) def removeAccount(self, account): - """ Remove all keys associated with a given account - """ + """Remove all keys associated with a given account""" accounts = self.getAccounts() for a in accounts: if a["name"] == account: self.store.delete(a["pubkey"]) def getOwnerKeyForAccount(self, name): - """ Obtain owner Private Key for an account from the wallet database - """ + """Obtain owner Private Key for an account from the wallet database""" account = self.rpc.get_account(name) for authority in account["owner"]["key_auths"]: key = self.getPrivateKeyForPublicKey(authority[0]) @@ -195,8 +182,7 @@ def getOwnerKeyForAccount(self, name): raise KeyNotFound def getMemoKeyForAccount(self, name): - """ Obtain owner Memo Key for an account from the wallet database - """ + """Obtain owner Memo Key for an account from the wallet database""" account = self.rpc.get_account(name) key = self.getPrivateKeyForPublicKey(account["options"]["memo_key"]) if key: @@ -204,8 +190,7 @@ def getMemoKeyForAccount(self, name): return False def getActiveKeyForAccount(self, name): - """ Obtain owner Active Key for an account from the wallet database - """ + """Obtain owner Active Key for an account from the wallet database""" account = self.rpc.get_account(name) for authority in account["active"]["key_auths"]: try: @@ -215,21 +200,18 @@ def getActiveKeyForAccount(self, name): return False def getAccountFromPrivateKey(self, wif): - """ Obtain account name from private key - """ + """Obtain account name from private key""" pub = self.publickey_from_wif(wif) return self.getAccountFromPublicKey(pub) def getAccountsFromPublicKey(self, pub): - """ Obtain all accounts associated with a public key - """ + """Obtain all accounts associated with a public key""" names = self.rpc.get_key_references([str(pub)])[0] for name in names: yield name def getAccountFromPublicKey(self, pub): - """ Obtain the first account name from public key - """ + """Obtain the first account name from public key""" # FIXME, this only returns the first associated key. # If the key is used by multiple accounts, this # will surely lead to undesired behavior @@ -238,8 +220,8 @@ def getAccountFromPublicKey(self, pub): return names[0] def getAllAccounts(self, pub): - """ Get the account data for a public key (all accounts found for this - public key) + """Get the account data for a public key (all accounts found for this + public key) """ return DeprecationWarning( "Use 'getAccountsFromPublicKey' instead and resolve with your own " @@ -247,8 +229,7 @@ def getAllAccounts(self, pub): ) def getKeyType(self, account, pub): - """ Get key type - """ + """Get key type""" for authority in ["owner", "active"]: for key in account[authority]["key_auths"]: if str(pub) == key[0]: @@ -258,8 +239,7 @@ def getKeyType(self, account, pub): return None def getAccounts(self): - """ Return all accounts installed in the wallet database - """ + """Return all accounts installed in the wallet database""" pubkeys = self.getPublicKeys() accounts = [] for pubkey in pubkeys: @@ -269,10 +249,10 @@ def getAccounts(self): return accounts def getPublicKeys(self, current=False): - """ Return all installed public keys + """Return all installed public keys - :param bool current: If true, returns only keys for currently - connected blockchain + :param bool current: If true, returns only keys for currently + connected blockchain """ pubkeys = self.store.getPublicKeys() if not current: diff --git a/graphenecommon/witness.py b/graphenecommon/witness.py index 8bc550d4..514c7a5d 100644 --- a/graphenecommon/witness.py +++ b/graphenecommon/witness.py @@ -5,10 +5,10 @@ class Witness(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Read data about a witness in the chain + """Read data about a witness in the chain - :param str account_name: Name of the witness - :param instance blockchain_instance: instance to use when accesing a RPC + :param str account_name: Name of the witness + :param instance blockchain_instance: instance to use when accesing a RPC """ @@ -66,11 +66,11 @@ def is_active(self): class Witnesses(BlockchainObjects, AbstractBlockchainInstanceProvider): - """ Obtain a list of **active** witnesses and the current schedule + """Obtain a list of **active** witnesses and the current schedule - :param bool only_active: (False) Only return witnesses that are - actively producing blocks - :param instance blockchain_instance: instance to use when accesing a RPC + :param bool only_active: (False) Only return witnesses that are + actively producing blocks + :param instance blockchain_instance: instance to use when accesing a RPC """ def __init__(self, *args, only_active=False, lazy=False, **kwargs): diff --git a/graphenecommon/worker.py b/graphenecommon/worker.py index 1d6cf669..5d755611 100644 --- a/graphenecommon/worker.py +++ b/graphenecommon/worker.py @@ -6,10 +6,10 @@ class Worker(BlockchainObject, AbstractBlockchainInstanceProvider): - """ Read data about a worker in the chain + """Read data about a worker in the chain - :param str id: id of the worker - :param instance blockchain_instance: instance to use when accesing a RPC + :param str id: id of the worker + :param instance blockchain_instance: instance to use when accesing a RPC """ @@ -41,10 +41,10 @@ def account(self): class Workers(BlockchainObjects, AbstractBlockchainInstanceProvider): - """ Obtain a list of workers for an account + """Obtain a list of workers for an account - :param str account_name/id: Name/id of the account (optional) - :param instance blockchain_instance: instance to use when accesing a RPC + :param str account_name/id: Name/id of the account (optional) + :param instance blockchain_instance: instance to use when accesing a RPC """ def __init__(self, *args, account_name=None, lazy=False, **kwargs): diff --git a/graphenestorage/__init__.py b/graphenestorage/__init__.py index 68484bc3..9589d2a0 100644 --- a/graphenestorage/__init__.py +++ b/graphenestorage/__init__.py @@ -14,22 +14,22 @@ def get_default_config_store(*args, **kwargs): - """ This method returns the default **configuration** store - that uses an SQLite database internally. + """This method returns the default **configuration** store + that uses an SQLite database internally. - :params str appname: The appname that is used internally to distinguish - different SQLite files + :params str appname: The appname that is used internally to distinguish + different SQLite files """ kwargs["appname"] = kwargs.get("appname", "graphene") return SqliteConfigurationStore(*args, **kwargs) def get_default_key_store(*args, config, **kwargs): - """ This method returns the default **key** store - that uses an SQLite database internally. + """This method returns the default **key** store + that uses an SQLite database internally. - :params str appname: The appname that is used internally to distinguish - different SQLite files + :params str appname: The appname that is used internally to distinguish + different SQLite files """ kwargs["appname"] = kwargs.get("appname", "graphene") return SqliteEncryptedKeyStore(config=config, **kwargs) diff --git a/graphenestorage/base.py b/graphenestorage/base.py index 877c22b5..0210ece7 100644 --- a/graphenestorage/base.py +++ b/graphenestorage/base.py @@ -12,23 +12,23 @@ # Configuration class InRamConfigurationStore(InRamStore, ConfigInterface): - """ A simple example that stores configuration in RAM. + """A simple example that stores configuration in RAM. - Internally, this works by simply inheriting - :class:`graphenestorage.ram.InRamStore`. The interface is defined in - :class:`graphenestorage.interfaces.ConfigInterface`. + Internally, this works by simply inheriting + :class:`graphenestorage.ram.InRamStore`. The interface is defined in + :class:`graphenestorage.interfaces.ConfigInterface`. """ pass class SqliteConfigurationStore(SQLiteStore, ConfigInterface): - """ This is the configuration storage that stores key/value - pairs in the `config` table of the SQLite3 database. + """This is the configuration storage that stores key/value + pairs in the `config` table of the SQLite3 database. - Internally, this works by simply inheriting - :class:`graphenestorage.sqlite.SQLiteStore`. The interface is defined - in :class:`graphenestorage.interfaces.ConfigInterface`. + Internally, this works by simply inheriting + :class:`graphenestorage.sqlite.SQLiteStore`. The interface is defined + in :class:`graphenestorage.interfaces.ConfigInterface`. """ #: The table name for the configuration @@ -41,11 +41,11 @@ class SqliteConfigurationStore(SQLiteStore, ConfigInterface): # Keys class InRamPlainKeyStore(InRamStore, KeyInterface): - """ A simple in-RAM Store that stores keys unencrypted in RAM + """A simple in-RAM Store that stores keys unencrypted in RAM - Internally, this works by simply inheriting - :class:`graphenestorage.ram.InRamStore`. The interface is defined in - :class:`graphenestorage.interfaces.KeyInterface`. + Internally, this works by simply inheriting + :class:`graphenestorage.ram.InRamStore`. The interface is defined in + :class:`graphenestorage.interfaces.KeyInterface`. """ def getPublicKeys(self): @@ -64,13 +64,13 @@ def delete(self, pub): class SqlitePlainKeyStore(SQLiteStore, KeyInterface): - """ This is the key storage that stores the public key and the - **unencrypted** private key in the `keys` table in the SQLite3 - database. + """This is the key storage that stores the public key and the + **unencrypted** private key in the `keys` table in the SQLite3 + database. - Internally, this works by simply inheriting - :class:`graphenestorage.ram.InRamStore`. The interface is defined in - :class:`graphenestorage.interfaces.KeyInterface`. + Internally, this works by simply inheriting + :class:`graphenestorage.ram.InRamStore`. The interface is defined in + :class:`graphenestorage.interfaces.KeyInterface`. """ #: The table name for the configuration @@ -95,15 +95,14 @@ def delete(self, pub): SQLiteStore.delete(self, str(pub)) def is_encrypted(self): - """ Returns False, as we are not encrypted here - """ + """Returns False, as we are not encrypted here""" return False class KeyEncryption(MasterPassword, EncryptedKeyInterface): - """ This is an interface class that provides the methods required for - EncryptedKeyInterface and links them to the MasterPassword-provided - functionatlity, accordingly. + """This is an interface class that provides the methods required for + EncryptedKeyInterface and links them to the MasterPassword-provided + functionatlity, accordingly. """ def __init__(self, *args, **kwargs): @@ -129,15 +128,15 @@ def is_encrypted(self): class InRamEncryptedKeyStore(InRamStore, KeyEncryption): - """ An in-RAM Store that stores keys **encrypted** in RAM. + """An in-RAM Store that stores keys **encrypted** in RAM. - Internally, this works by simply inheriting - :class:`graphenestorage.ram.InRamStore`. The interface is defined in - :class:`graphenestorage.interfaces.KeyInterface`. + Internally, this works by simply inheriting + :class:`graphenestorage.ram.InRamStore`. The interface is defined in + :class:`graphenestorage.interfaces.KeyInterface`. - .. note:: This module also inherits - :class:`graphenestorage.masterpassword.MasterPassword` which offers - additional methods and deals with encrypting the keys. + .. note:: This module also inherits + :class:`graphenestorage.masterpassword.MasterPassword` which offers + additional methods and deals with encrypting the keys. """ def __init__(self, *args, **kwargs): @@ -146,16 +145,16 @@ def __init__(self, *args, **kwargs): class SqliteEncryptedKeyStore(SQLiteStore, KeyEncryption): - """ This is the key storage that stores the public key and the - **encrypted** private key in the `keys` table in the SQLite3 database. + """This is the key storage that stores the public key and the + **encrypted** private key in the `keys` table in the SQLite3 database. - Internally, this works by simply inheriting - :class:`graphenestorage.ram.InRamStore`. The interface is defined in - :class:`graphenestorage.interfaces.KeyInterface`. + Internally, this works by simply inheriting + :class:`graphenestorage.ram.InRamStore`. The interface is defined in + :class:`graphenestorage.interfaces.KeyInterface`. - .. note:: This module also inherits - :class:`graphenestorage.masterpassword.MasterPassword` which offers - additional methods and deals with encrypting the keys. + .. note:: This module also inherits + :class:`graphenestorage.masterpassword.MasterPassword` which offers + additional methods and deals with encrypting the keys. """ __tablename__ = "keys" diff --git a/graphenestorage/exceptions.py b/graphenestorage/exceptions.py index 6951c5e0..c8a8122b 100644 --- a/graphenestorage/exceptions.py +++ b/graphenestorage/exceptions.py @@ -4,14 +4,12 @@ class WalletLocked(Exception): class WrongMasterPasswordException(Exception): - """ The password provided could not properly unlock the wallet - """ + """The password provided could not properly unlock the wallet""" pass class KeyAlreadyInStoreException(Exception): - """ The key of a key/value pair is already in the store - """ + """The key of a key/value pair is already in the store""" pass diff --git a/graphenestorage/interfaces.py b/graphenestorage/interfaces.py index 09821997..f71af37a 100644 --- a/graphenestorage/interfaces.py +++ b/graphenestorage/interfaces.py @@ -1,32 +1,32 @@ # -*- coding: utf-8 -*- class StoreInterface(dict): - """ The store interface is the most general store that we can have. + """The store interface is the most general store that we can have. - It inherits dict and thus behaves like a dictionary. As such any - key/value store can be used as store with or even without an adaptor. + It inherits dict and thus behaves like a dictionary. As such any + key/value store can be used as store with or even without an adaptor. - .. note:: This class defines ``defaults`` that are used to return - reasonable defaults for the library. + .. note:: This class defines ``defaults`` that are used to return + reasonable defaults for the library. - .. warning:: If you are trying to obtain a value for a key that does - **not** exist in the store, the library will **NOT** raise but - return a ``None`` value. This represents the biggest difference to - a regular ``dict`` class. + .. warning:: If you are trying to obtain a value for a key that does + **not** exist in the store, the library will **NOT** raise but + return a ``None`` value. This represents the biggest difference to + a regular ``dict`` class. - Methods that need to be implemented: + Methods that need to be implemented: - * ``def setdefault(cls, key, value)`` - * ``def __init__(self, *args, **kwargs)`` - * ``def __setitem__(self, key, value)`` - * ``def __getitem__(self, key)`` - * ``def __iter__(self)`` - * ``def __len__(self)`` - * ``def __contains__(self, key)`` + * ``def setdefault(cls, key, value)`` + * ``def __init__(self, *args, **kwargs)`` + * ``def __setitem__(self, key, value)`` + * ``def __getitem__(self, key)`` + * ``def __iter__(self)`` + * ``def __len__(self)`` + * ``def __contains__(self, key)`` - .. note:: Configuration and Key classes are subclasses of this to allow - storing keys separate from configuration. + .. note:: Configuration and Key classes are subclasses of this to allow + storing keys separate from configuration. """ @@ -34,24 +34,22 @@ class StoreInterface(dict): @classmethod def setdefault(cls, key, value): - """ Allows to define default values - """ + """Allows to define default values""" cls.defaults[key] = value def __init__(self, *args, **kwargs): pass def __setitem__(self, key, value): - """ Sets an item in the store - """ + """Sets an item in the store""" return dict.__setitem__(self, key, value) def __getitem__(self, key): - """ Gets an item from the store as if it was a dictionary + """Gets an item from the store as if it was a dictionary - .. note:: Special behavior! If a key is not found, ``None`` is - returned instead of raising an exception, unless a default - value is found, then that is returned. + .. note:: Special behavior! If a key is not found, ``None`` is + returned instead of raising an exception, unless a default + value is found, then that is returned. """ if key in self: return dict.__getitem__(self, key) @@ -61,122 +59,110 @@ def __getitem__(self, key): return None def __iter__(self): - """ Iterates through the store - """ + """Iterates through the store""" return dict.__iter__(self) def __len__(self): - """ return lenght of store - """ + """return lenght of store""" return dict.__len__(self) def __contains__(self, key): - """ Tests if a key is contained in the store. - """ + """Tests if a key is contained in the store.""" return dict.__contains__(self, key) def items(self): - """ Returns all items off the store as tuples - """ + """Returns all items off the store as tuples""" return dict.items(self) def get(self, key, default=None): - """ Return the key if exists or a default value - """ + """Return the key if exists or a default value""" return dict.get(self, key, default) # Specific for this library def delete(self, key): - """ Delete a key from the store - """ + """Delete a key from the store""" raise NotImplementedError def wipe(self): - """ Wipe the store - """ + """Wipe the store""" raise NotImplementedError class KeyInterface(StoreInterface): - """ The KeyInterface defines the interface for key storage. + """The KeyInterface defines the interface for key storage. - .. note:: This class inherits - :class:`graphenestorage.interfaces.StoreInterface` and defines - additional key-specific methods. + .. note:: This class inherits + :class:`graphenestorage.interfaces.StoreInterface` and defines + additional key-specific methods. """ def is_encrypted(self): - """ Returns True/False to indicate required use of unlock - """ + """Returns True/False to indicate required use of unlock""" return False # Interface to deal with encrypted keys def getPublicKeys(self): - """ Returns the public keys stored in the database - """ + """Returns the public keys stored in the database""" raise NotImplementedError def getPrivateKeyForPublicKey(self, pub): - """ Returns the (possibly encrypted) private key that - corresponds to a public key + """Returns the (possibly encrypted) private key that + corresponds to a public key - :param str pub: Public key + :param str pub: Public key - The encryption scheme is BIP38 + The encryption scheme is BIP38 """ raise NotImplementedError def add(self, wif, pub=None): - """ Add a new public/private key pair (correspondence has to be - checked elsewhere!) + """Add a new public/private key pair (correspondence has to be + checked elsewhere!) - :param str pub: Public key - :param str wif: Private key + :param str pub: Public key + :param str wif: Private key """ raise NotImplementedError def delete(self, pub): - """ Delete a pubkey/privatekey pair from the store + """Delete a pubkey/privatekey pair from the store - :param str pub: Public key + :param str pub: Public key """ raise NotImplementedError class EncryptedKeyInterface(KeyInterface): - """ The EncryptedKeyInterface extends KeyInterface to work with encrypted - keys + """The EncryptedKeyInterface extends KeyInterface to work with encrypted + keys """ def is_encrypted(self): - """ Returns True/False to indicate required use of unlock - """ + """Returns True/False to indicate required use of unlock""" return True def unlock(self, password): - """ Tries to unlock the wallet if required + """Tries to unlock the wallet if required - :param str password: Plain password + :param str password: Plain password """ raise NotImplementedError def locked(self): - """ is the wallet locked? - """ + """is the wallet locked?""" return False def lock(self): - """ Lock the wallet again - """ + """Lock the wallet again""" raise NotImplementedError class ConfigInterface(StoreInterface): - """ The BaseKeyStore defines the interface for key storage + """The BaseKeyStore defines the interface for key storage - .. note:: This class inherits - :class:`graphenestorage.interfaces.StoreInterface` and defines - **no** additional configuration-specific methods. + .. note:: This class inherits + :class:`graphenestorage.interfaces.StoreInterface` and defines + **no** additional configuration-specific methods. """ pass diff --git a/graphenestorage/masterpassword.py b/graphenestorage/masterpassword.py index 2737ba41..d671cf56 100644 --- a/graphenestorage/masterpassword.py +++ b/graphenestorage/masterpassword.py @@ -16,15 +16,15 @@ class MasterPassword(object): - """ The keys are encrypted with a Masterpassword that is stored in - the configurationStore. It has a checksum to verify correctness - of the password - The encrypted private keys in `keys` are encrypted with a random - **masterkey/masterpassword** that is stored in the configuration - encrypted by the user-provided password. - - :param ConfigStore config: Configuration store to get access to the - encrypted master password + """The keys are encrypted with a Masterpassword that is stored in + the configurationStore. It has a checksum to verify correctness + of the password + The encrypted private keys in `keys` are encrypted with a random + **masterkey/masterpassword** that is stored in the configuration + encrypted by the user-provided password. + + :param ConfigStore config: Configuration store to get access to the + encrypted master password """ def __init__(self, config=None, **kwargs): @@ -37,24 +37,21 @@ def __init__(self, config=None, **kwargs): @property def masterkey(self): - """ Contains the **decrypted** master key - """ + """Contains the **decrypted** master key""" return self.decrypted_master def has_masterpassword(self): - """ Tells us if the config store knows an encrypted masterpassword - """ + """Tells us if the config store knows an encrypted masterpassword""" return self.config_key in self.config def locked(self): - """ Is the store locked. E.g. Is a valid password known that can be - used to decrypt the master key? + """Is the store locked. E.g. Is a valid password known that can be + used to decrypt the master key? """ return not self.unlocked() def unlocked(self): - """ Is the store unlocked so that I can decrypt the content? - """ + """Is the store unlocked so that I can decrypt the content?""" if self.password is not None: return bool(self.password) else: @@ -70,21 +67,21 @@ def unlocked(self): return False def lock(self): - """ Lock the store so that we can no longer decrypt the content of the - store + """Lock the store so that we can no longer decrypt the content of the + store """ self.password = None self.decrypted_master = None def unlock(self, password): - """ The password is used to encrypt this masterpassword. To - decrypt the keys stored in the keys database, one must use - BIP38, decrypt the masterpassword from the configuration - store with the user password, and use the decrypted - masterpassword to decrypt the BIP38 encrypted private keys - from the keys storage! - - :param str password: Password to use for en-/de-cryption + """The password is used to encrypt this masterpassword. To + decrypt the keys stored in the keys database, one must use + BIP38, decrypt the masterpassword from the configuration + store with the user password, and use the decrypted + masterpassword to decrypt the BIP38 encrypted private keys + from the keys storage! + + :param str password: Password to use for en-/de-cryption """ self.password = password if self.config_key in self.config and self.config[self.config_key]: @@ -94,8 +91,7 @@ def unlock(self, password): self._save_encrypted_masterpassword() def _decrypt_masterpassword(self): - """ Decrypt the encrypted masterkey - """ + """Decrypt the encrypted masterkey""" aes = AESCipher(self.password) checksum, encrypted_master = self.config[self.config_key].split("$") try: @@ -114,10 +110,10 @@ def _save_encrypted_masterpassword(self): self.config[self.config_key] = self._get_encrypted_masterpassword() def _new_masterpassword(self, password): - """ Generate a new random masterkey, encrypt it with the password and - store it in the store. + """Generate a new random masterkey, encrypt it with the password and + store it in the store. - :param str password: Password to use for en-/de-cryption + :param str password: Password to use for en-/de-cryption """ # make sure to not overwrite an existing key if self.config_key in self.config and self.config[self.config_key]: @@ -131,19 +127,19 @@ def _new_masterpassword(self, password): return self.masterkey def _derive_checksum(self, s): - """ Derive the checksum + """Derive the checksum - :param str s: Random string for which to derive the checksum + :param str s: Random string for which to derive the checksum """ checksum = hashlib.sha256(bytes(s, "ascii")).hexdigest() return checksum[:4] def _get_encrypted_masterpassword(self): - """ Obtain the encrypted masterkey + """Obtain the encrypted masterkey - .. note:: The encrypted masterkey is checksummed, so that we can - figure out that a provided password is correct or not. The - checksum is only 4 bytes long! + .. note:: The encrypted masterkey is checksummed, so that we can + figure out that a provided password is correct or not. The + checksum is only 4 bytes long! """ if not self.unlocked(): raise WalletLocked @@ -153,26 +149,25 @@ def _get_encrypted_masterpassword(self): ) def change_password(self, newpassword): - """ Change the password that allows to decrypt the master key - """ + """Change the password that allows to decrypt the master key""" if not self.unlocked(): raise WalletLocked self.password = newpassword self._save_encrypted_masterpassword() def decrypt(self, wif): - """ Decrypt the content according to BIP38 + """Decrypt the content according to BIP38 - :param str wif: Encrypted key + :param str wif: Encrypted key """ if not self.unlocked(): raise WalletLocked return format(bip38.decrypt(wif, self.masterkey), "wif") def encrypt(self, wif): - """ Encrypt the content according to BIP38 + """Encrypt the content according to BIP38 - :param str wif: Unencrypted key + :param str wif: Unencrypted key """ if not self.unlocked(): raise WalletLocked diff --git a/graphenestorage/ram.py b/graphenestorage/ram.py index 25c1c31a..ff2ee38d 100644 --- a/graphenestorage/ram.py +++ b/graphenestorage/ram.py @@ -5,27 +5,25 @@ # StoreInterface is done first, then dict which overwrites the interface # methods class InRamStore(StoreInterface): - """ The InRamStore inherits - :class:`graphenestore.interfaces.StoreInterface` and extends it by two - further calls for wipe and delete. + """The InRamStore inherits + :class:`graphenestore.interfaces.StoreInterface` and extends it by two + further calls for wipe and delete. - The store is syntactically equivalent to a regular dictionary. + The store is syntactically equivalent to a regular dictionary. - .. warning:: If you are trying to obtain a value for a key that does - **not** exist in the store, the library will **NOT** raise but - return a ``None`` value. This represents the biggest difference to - a regular ``dict`` class. + .. warning:: If you are trying to obtain a value for a key that does + **not** exist in the store, the library will **NOT** raise but + return a ``None`` value. This represents the biggest difference to + a regular ``dict`` class. """ # Specific for this library def delete(self, key): - """ Delete a key from the store - """ + """Delete a key from the store""" self.pop(key, None) def wipe(self): - """ Wipe the store - """ + """Wipe the store""" keys = list(self.keys()).copy() for key in keys: self.delete(key) diff --git a/graphenestorage/sqlite.py b/graphenestorage/sqlite.py index 2274bc03..8f22e85b 100644 --- a/graphenestorage/sqlite.py +++ b/graphenestorage/sqlite.py @@ -12,27 +12,27 @@ class SQLiteFile: - """ This class ensures that the user's data is stored in its OS - preotected user directory: + """This class ensures that the user's data is stored in its OS + preotected user directory: - **OSX:** + **OSX:** - * `~/Library/Application Support/` + * `~/Library/Application Support/` - **Windows:** + **Windows:** - * `C:\\Documents and Settings\\\\Application Data\\Local Settings\\\\` - * `C:\\Documents and Settings\\\\Application Data\\\\` + * `C:\\Documents and Settings\\\\Application Data\\Local Settings\\\\` + * `C:\\Documents and Settings\\\\Application Data\\\\` - **Linux:** + **Linux:** - * `~/.local/share/` + * `~/.local/share/` - Furthermore, it offers an interface to generated backups - in the `backups/` directory every now and then. + Furthermore, it offers an interface to generated backups + in the `backups/` directory every now and then. - .. note:: The file name can be overwritten when providing a keyword - argument ``profile``. + .. note:: The file name can be overwritten when providing a keyword + argument ``profile``. """ def __init__(self, *args, **kwargs): @@ -57,14 +57,14 @@ def __init__(self, *args, **kwargs): class SQLiteCommon(object): - """ This class abstracts away common sqlite3 operations. + """This class abstracts away common sqlite3 operations. - This class should not be used directly. + This class should not be used directly. - When inheriting from this class, the following instance members must - be defined: + When inheriting from this class, the following instance members must + be defined: - * ``sqlite_file``: Path to the SQLite Database file + * ``sqlite_file``: Path to the SQLite Database file """ def sql_fetchone(self, query): @@ -108,21 +108,21 @@ def sql_execute(self, query, lastid=False): class SQLiteStore(SQLiteFile, SQLiteCommon, StoreInterface): - """ The SQLiteStore deals with the sqlite3 part of storing data into a - database file. + """The SQLiteStore deals with the sqlite3 part of storing data into a + database file. - .. note:: This module is limited to two columns and merely stores - key/value pairs into the sqlite database + .. note:: This module is limited to two columns and merely stores + key/value pairs into the sqlite database - On first launch, the database file as well as the tables are created - automatically. + On first launch, the database file as well as the tables are created + automatically. - When inheriting from this class, the following three class members must - be defined: + When inheriting from this class, the following three class members must + be defined: - * ``__tablename__``: Name of the table - * ``__key__``: Name of the key column - * ``__value__``: Name of the value column + * ``__tablename__``: Name of the table + * ``__key__``: Name of the key column + * ``__value__``: Name of the value column """ #: @@ -140,8 +140,7 @@ def __init__(self, *args, **kwargs): self.create() def _haveKey(self, key): - """ Is the key `key` available? - """ + """Is the key `key` available?""" query = ( "SELECT {} FROM {} WHERE {}=?".format( self.__value__, self.__tablename__, self.__key__ @@ -151,10 +150,10 @@ def _haveKey(self, key): return True if self.sql_fetchone(query) else False def __setitem__(self, key, value): - """ Sets an item in the store + """Sets an item in the store - :param str key: Key - :param str value: Value + :param str key: Key + :param str value: Value """ if self._haveKey(key): query = ( @@ -173,9 +172,9 @@ def __setitem__(self, key, value): self.sql_execute(query) def __getitem__(self, key): - """ Gets an item from the store as if it was a dictionary + """Gets an item from the store as if it was a dictionary - :param str value: Value + :param str value: Value """ query = ( "SELECT {} FROM {} WHERE {}=?".format( @@ -193,8 +192,7 @@ def __getitem__(self, key): return None def __iter__(self): - """ Iterates through the store - """ + """Iterates through the store""" return iter(self.keys()) def keys(self): @@ -202,17 +200,16 @@ def keys(self): return [x[0] for x in self.sql_fetchall(query)] def __len__(self): - """ return lenght of store - """ + """return lenght of store""" query = ("SELECT id from {}".format(self.__tablename__),) return len(self.sql_fetchall(query)) def __contains__(self, key): - """ Tests if a key is contained in the store. + """Tests if a key is contained in the store. - May test againsts self.defaults + May test againsts self.defaults - :param str value: Value + :param str value: Value """ if self._haveKey(key) or key in self.defaults: return True @@ -220,8 +217,7 @@ def __contains__(self, key): return False def items(self): - """ returns all items off the store as tuples - """ + """returns all items off the store as tuples""" query = ( "SELECT {}, {} from {}".format( self.__key__, self.__value__, self.__tablename__ @@ -233,10 +229,10 @@ def items(self): return r def get(self, key, default=None): - """ Return the key if exists or a default value + """Return the key if exists or a default value - :param str value: Value - :param str default: Default value if key not present + :param str value: Value + :param str default: Default value if key not present """ if key in self: return self.__getitem__(key) @@ -245,9 +241,9 @@ def get(self, key, default=None): # Specific for this library def delete(self, key): - """ Delete a key from the store + """Delete a key from the store - :param str value: Value + :param str value: Value """ query = ( "DELETE FROM {} WHERE {}=?".format(self.__tablename__, self.__key__), @@ -256,14 +252,12 @@ def delete(self, key): self.sql_execute(query) def wipe(self): - """ Wipe the store - """ + """Wipe the store""" query = ("DELETE FROM {}".format(self.__tablename__),) self.sql_execute(query) def exists(self): - """ Check if the database table exists - """ + """Check if the database table exists""" query = ( "SELECT name FROM sqlite_master " + "WHERE type='table' AND name=?", (self.__tablename__,), @@ -271,8 +265,7 @@ def exists(self): return True if self.sql_fetchone(query) else False def create(self): # pragma: no cover - """ Create the new table in the SQLite database - """ + """Create the new table in the SQLite database""" query = ( ( """