Fixes annotation syntax errors and several agent-related interfaces.

pull/2037/head
Kieran Prasch 2020-05-24 02:39:02 -07:00 committed by Kieran R. Prasch
parent e5f167eb20
commit db42705a57
12 changed files with 46 additions and 31 deletions

View File

@ -25,6 +25,7 @@ from constant_sorrow.constants import NOT_RUNNING, UNKNOWN_DEVELOPMENT_CHAIN_ID
from cytoolz.dicttoolz import dissoc
from eth_account import Account
from eth_account.messages import encode_defunct
from eth_typing.evm import BlockNumber, ChecksumAddress
from eth_utils import to_canonical_address, to_checksum_address
from geth import LoggingMixin
from geth.accounts import create_new_account, get_accounts
@ -38,6 +39,8 @@ from geth.process import BaseGethProcess
from twisted.logger import Logger
from typing import Union
from web3 import Web3
from web3.contract import Contract
from web3.types import Wei, TxReceipt
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, DEPLOY_DIR, USER_LOG_DIR
@ -236,26 +239,26 @@ class EthereumClient:
def net_version(self) -> int:
return int(self.w3.net.version)
def get_contract(self, **kwargs):
def get_contract(self, **kwargs) -> Contract:
return self.w3.eth.contract(**kwargs)
@property
def gas_price(self):
def gas_price(self) -> Wei:
return self.w3.eth.gasPrice
@property
def block_number(self) -> int:
def block_number(self) -> BlockNumber:
return self.w3.eth.blockNumber
@property
def coinbase(self) -> str:
def coinbase(self) -> ChecksumAddress:
return self.w3.eth.coinbase
def wait_for_receipt(self, transaction_hash: str, timeout: int) -> dict:
def wait_for_receipt(self, transaction_hash: str, timeout: int) -> TxReceipt:
receipt = self.w3.eth.waitForTransactionReceipt(transaction_hash=transaction_hash, timeout=timeout)
return receipt
def sign_transaction(self, transaction_dict: dict):
def sign_transaction(self, transaction_dict: dict) -> bytes:
raise NotImplementedError
def get_transaction(self, transaction_hash) -> str:
@ -275,16 +278,14 @@ class EthereumClient:
"""
return self.w3.eth.sign(account, data=message)
def _has_latest_block(self):
def _has_latest_block(self) -> bool:
# check that our local chain data is up to date
return (
time.time() -
self.w3.eth.getBlock(self.w3.eth.blockNumber)['timestamp']
) < 30
def sync(self,
timeout: int = 120,
quiet: bool = False):
def sync(self, timeout: int = 120, quiet: bool = False):
# Provide compatibility with local chains
if self.is_local:

View File

@ -27,6 +27,7 @@ from constant_sorrow.constants import (
from datetime import datetime
from twisted.logger import Logger
from typing import Callable, Optional, Union
from web3.types import TxReceipt, Wei
ContractInterfaces = Union[
CONTRACT_CALL,
@ -136,7 +137,7 @@ COLLECT_CONTRACT_API = True
def contract_api(interface: Optional[ContractInterfaces] = UNKNOWN_CONTRACT_INTERFACE) -> Callable:
"""Decorator factory for contract API markers"""
def decorator(agent_method: Callable) -> Callable:
def decorator(agent_method: Callable) -> Callable[..., Union[TxReceipt, Wei, int, str, bool]]:
"""
Marks an agent method as containing contract interactions (transaction or call)
and validates outbound checksum addresses for EIP-55 compliance.

View File

@ -14,6 +14,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from web3.contract import Contract
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
@ -42,11 +43,11 @@ class EventRecord:
class ContractEvents:
def __init__(self, contract):
def __init__(self, contract: Contract):
self.contract = contract
self.names = tuple(e.event_name for e in contract.events)
def __get_web3_event_by_name(self, event_name):
def __get_web3_event_by_name(self, event_name: str):
if event_name not in self.names:
raise TypeError(f"Event '{event_name}' doesn't exist in this contract. Valid events are {self.names}")
event_method = getattr(self.contract.events, event_name)

View File

@ -30,7 +30,7 @@ from eth_tester import EthereumTester
from eth_tester.exceptions import TransactionFailed as TestTransactionFailed
from eth_utils import to_checksum_address
from twisted.logger import Logger
from typing import Callable, List, Tuple, Union
from typing import Callable, List, NamedTuple, Tuple, Union
from urllib.parse import urlparse
from web3 import HTTPProvider, IPCProvider, Web3, WebsocketProvider, middleware
from web3.contract import Contract, ContractConstructor, ContractFunction
@ -932,9 +932,10 @@ class BlockchainInterfaceFactory:
_interfaces = dict()
_default_interface_class = BlockchainInterface
CachedInterface = collections.namedtuple('CachedInterface', ['interface', # type: BlockchainInterface
'sync', # type: bool
'emitter']) # type: StdoutEmitter
class CachedInterface(NamedTuple):
interface: BlockchainInterface
sync: bool
emitter: StdoutEmitter
class FactoryError(Exception):
pass

View File

@ -23,14 +23,14 @@ import itertools
import os
import re
from twisted.logger import Logger
from typing import List, Set
from typing import List, NamedTuple, Optional, Set
from nucypher.blockchain.eth.sol import SOLIDITY_COMPILER_VERSION
SourceDirs = collections.namedtuple('SourceDirs', ['root_source_dir', # type: str
'other_source_dirs', # type: Set[str]
])
SourceDirs.__new__.__defaults__ = (None,)
class SourceDirs(NamedTuple):
root_source_dir: str
other_source_dirs: Optional[Set[str]] = None
class SolidityCompiler:

View File

@ -117,7 +117,7 @@ class Character(Learner):
if federated_only:
if registry or provider_uri:
raise ValueError(f"Cannot init federated-only character with {registry or provider_uri}.")
self.federated_only = bool(federated_only) # type: bool
self.federated_only: bool = federated_only
#
# Powers
@ -218,7 +218,7 @@ class Character(Learner):
#
elif federated_only:
try:
self._set_checksum_address() # type: str
self._set_checksum_address()
except NoSigningPower:
self._checksum_address = NO_BLOCKCHAIN_CONNECTION
if checksum_address:

View File

@ -18,18 +18,23 @@
from bytestring_splitter import BytestringSplittingError
from cryptography.exceptions import InternalError
class SpecificationError(ValueError):
"""The protocol request is completely unusable"""
class MissingField(SpecificationError):
"""The protocol request cannot be deserialized because it is missing required fields"""
class InvalidInputData(SpecificationError):
"""Input data does not match the input specification"""
class InvalidOutputData(SpecificationError):
"""Response data does not match the output specification"""
class InvalidArgumentCombo(SpecificationError):
"""Arguments specified are incompatible"""

View File

@ -1,3 +1,4 @@
# noinspection Mypy
"""
This file is part of nucypher.

View File

@ -14,6 +14,8 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from bytestring_splitter import BytestringKwargifier, VariableLengthBytestring
from constant_sorrow.constants import NOT_SIGNED, UNKNOWN_SENDER

View File

@ -14,6 +14,8 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from bytestring_splitter import BytestringSplitter
from umbral.config import default_params
from umbral.keys import UmbralPublicKey

View File

@ -1017,13 +1017,15 @@ class Teacher:
# Known Nodes
#
def seed_node_metadata(self, as_teacher_uri=False):
def seed_node_metadata(self, as_teacher_uri=False) -> SeednodeMetadata:
if as_teacher_uri:
teacher_uri = f'{self.checksum_address}@{self.rest_server.rest_interface.host}:{self.rest_server.rest_interface.port}'
return teacher_uri
return SeednodeMetadata(self.checksum_address, # type: str
self.rest_server.rest_interface.host, # type: str
self.rest_server.rest_interface.port) # type: int
return SeednodeMetadata(
self.checksum_address,
self.rest_server.rest_interface.host,
self.rest_server.rest_interface.port
)
def sorted_nodes(self):
nodes_to_consider = list(self.known_nodes.values()) + [self]

View File

@ -18,8 +18,6 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import subprocess
import sys
@ -27,6 +25,7 @@ from pathlib import Path
from setuptools import find_packages, setup
from setuptools.command.develop import develop
from setuptools.command.install import install
from typing import Dict
#
# Metadata
@ -49,7 +48,7 @@ PYPI_CLASSIFIERS = [
"Topic :: Security"
]
ABOUT = dict()
ABOUT: Dict[str, str] = dict()
SOURCE_METADATA_PATH = BASE_DIR / PACKAGE_NAME / "__about__.py"
with open(str(SOURCE_METADATA_PATH.resolve())) as f:
exec(f.read(), ABOUT)