Example #1
0
class RequestManager:
    logger = logging.getLogger("web3.RequestManager")

    def __init__(self, web3, provider=None, middlewares=None):
        self.web3 = web3
        self.pending_requests = {}

        if middlewares is None:
            middlewares = self.default_middlewares(web3)

        self.middleware_onion = NamedElementOnion(middlewares)

        if provider is None:
            self.provider = AutoProvider()
        else:
            self.provider = provider

    web3 = None
    _provider = None

    @property
    def provider(self):
        return self._provider

    @provider.setter
    def provider(self, provider):
        self._provider = provider

    @staticmethod
    def default_middlewares(web3):
        """
        List the default middlewares for the request manager.
        Leaving ens unspecified will prevent the middleware from resolving names.
        """
        return [
            (request_parameter_normalizer, 'request_param_normalizer'),
            (gas_price_strategy_middleware, 'gas_price_strategy'),
            (name_to_address_middleware(web3), 'name_to_address'),
            (attrdict_middleware, 'attrdict'),
            (pythonic_middleware, 'pythonic'),
            (normalize_errors_middleware, 'normalize_errors'),
            (validation_middleware, 'validation'),
            (abi_middleware, 'abi'),
        ]

    #
    # Provider requests and response
    #
    def _make_request(self, method, params):
        request_func = self.provider.request_func(
            self.web3,
            tuple(self.middleware_onion))
        self.logger.debug("Making request. Method: %s", method)
        return request_func(method, params)

    async def _coro_make_request(self, method, params):
        request_func = self.provider.request_func(
            self.web3,
            tuple(self.middleware_onion))
        self.logger.debug("Making request. Method: %s", method)
        return await request_func(method, params)

    def request_blocking(self, method, params):
        """
        Make a synchronous request using the provider
        """
        response = self._make_request(method, params)

        if "error" in response:
            raise ValueError(response["error"])

        if response['result'] is None:
            raise ValueError(f"The call to {method} did not return a value.")

        return response['result']

    async def coro_request(self, method, params):
        """
        Couroutine for making a request using the provider
        """
        response = await self._coro_make_request(method, params)

        if "error" in response:
            raise ValueError(response["error"])

        if response['result'] is None:
            raise ValueError(f"The call to {method} did not return a value.")

        return response['result']

    @deprecated_for("coro_request")
    def request_async(self, raw_method, raw_params):
        request_id = uuid.uuid4()
        self.pending_requests[request_id] = spawn(
            self.request_blocking,
            raw_method=raw_method,
            raw_params=raw_params,
        )
        return request_id

    def receive_blocking(self, request_id, timeout=None):
        try:
            request = self.pending_requests.pop(request_id)
        except KeyError:
            raise KeyError("Request for id:{0} not found".format(request_id))
        else:
            response = request.get(timeout=timeout)

        if "error" in response:
            raise ValueError(response["error"])

        return response['result']

    def receive_async(self, request_id, *args, **kwargs):
        raise NotImplementedError("Callback pattern not implemented")
Example #2
0
class RequestManager:
    logger = logging.getLogger("web3.RequestManager")

    def __init__(
        self,
        web3: 'Web3',
        provider: Optional[BaseProvider] = None,
        middlewares: Optional[Sequence[Tuple[Middleware, str]]] = None
    ) -> None:
        self.web3 = web3
        self.pending_requests: Dict[UUID, ThreadWithReturn[RPCResponse]] = {}

        if middlewares is None:
            middlewares = self.default_middlewares(web3)

        self.middleware_onion: MiddlewareOnion = NamedElementOnion(middlewares)

        if provider is None:
            self.provider = AutoProvider()
        else:
            self.provider = provider

    web3: 'Web3' = None
    _provider = None

    @property
    def provider(self) -> BaseProvider:
        return self._provider

    @provider.setter
    def provider(self, provider: BaseProvider) -> None:
        self._provider = provider

    @staticmethod
    def default_middlewares(
        web3: 'Web3'
    )-> List[Tuple[Middleware, str]]:
        """
        List the default middlewares for the request manager.
        Leaving ens unspecified will prevent the middleware from resolving names.
        """
        return [
            (request_parameter_normalizer, 'request_param_normalizer'),  # Delete
            (gas_price_strategy_middleware, 'gas_price_strategy'),  # Add Async
            (name_to_address_middleware(web3), 'name_to_address'),  # Add Async
            (attrdict_middleware, 'attrdict'),  # Delete
            (pythonic_middleware, 'pythonic'),  # Delete
            (normalize_errors_middleware, 'normalize_errors'),  # Add async
            (validation_middleware, 'validation'),  # Add async
            (abi_middleware, 'abi'),  # Delete
        ]

    #
    # Provider requests and response
    #
    def _make_request(
        self, method: Union[RPCEndpoint, Callable[..., RPCEndpoint]], params: Any
    ) -> RPCResponse:
        request_func = self.provider.request_func(
            self.web3,
            self.middleware_onion)
        self.logger.debug("Making request. Method: %s", method)
        return request_func(method, params)

    async def _coro_make_request(
        self, method: Union[RPCEndpoint, Callable[..., RPCEndpoint]], params: Any
    ) -> RPCResponse:
        request_func = self.provider.request_func(
            self.web3,
            self.middleware_onion)
        self.logger.debug("Making request. Method: %s", method)
        # type ignored b/c request_func is an awaitable in async model
        return await request_func(method, params)  # type: ignore

    def request_blocking(
        self,
        method: Union[RPCEndpoint, Callable[..., RPCEndpoint]],
        params: Any,
        error_formatters: Optional[Callable[..., Any]] = None,
    ) -> Any:
        """
        Make a synchronous request using the provider
        """
        response = self._make_request(method, params)

        if "error" in response:
            apply_error_formatters(error_formatters, response)
            raise ValueError(response["error"])
        elif response['result'] is None:
            apply_error_formatters(error_formatters, response, params)

        return response['result']

    async def coro_request(
        self,
        method: Union[RPCEndpoint, Callable[..., RPCEndpoint]],
        params: Any,
        error_formatters: Optional[Callable[..., Any]] = None,
    ) -> Any:
        """
        Couroutine for making a request using the provider
        """
        response = await self._coro_make_request(method, params)

        if "error" in response:
            apply_error_formatters(error_formatters, response)
            raise ValueError(response["error"])

        if response['result'] is None:
            raise ValueError(f"The call to {method} did not return a value.")

        return response['result']

    @deprecated_for("coro_request")
    def request_async(self, raw_method: str, raw_params: Any) -> UUID:
        request_id = uuid.uuid4()
        self.pending_requests[request_id] = spawn(
            self.request_blocking,
            raw_method=raw_method,
            raw_params=raw_params,
        )
        return request_id

    def receive_blocking(self, request_id: UUID, timeout: Optional[float] = None) -> Any:
        try:
            request = self.pending_requests.pop(request_id)
        except KeyError:
            raise KeyError("Request for id:{0} not found".format(request_id))
        else:
            response = request.get(timeout=timeout)

        if "error" in response:
            raise ValueError(response["error"])

        return response['result']

    def receive_async(self, request_id: UUID, *args: Any, **kwargs: Any) -> NoReturn:
        raise NotImplementedError("Callback pattern not implemented")
Example #3
0
class RequestManager:
    logger = logging.getLogger("web3.RequestManager")

    def __init__(
        self,
        web3: 'Web3',
        provider: Optional[BaseProvider] = None,
        middlewares: Optional[Sequence[Tuple[Middleware,
                                             str]]] = None) -> None:
        self.web3 = web3
        self.pending_requests: Dict[UUID, ThreadWithReturn[RPCResponse]] = {}

        if middlewares is None:
            middlewares = self.default_middlewares(web3)

        self.middleware_onion: MiddlewareOnion = NamedElementOnion(middlewares)

        if provider is None:
            self.provider = AutoProvider()
        else:
            self.provider = provider

    web3: 'Web3' = None
    _provider = None

    @property
    def provider(self) -> BaseProvider:
        return self._provider

    @provider.setter
    def provider(self, provider: BaseProvider) -> None:
        self._provider = provider

    @staticmethod
    def default_middlewares(web3: 'Web3') -> List[Tuple[Middleware, str]]:
        """
        List the default middlewares for the request manager.
        Leaving ens unspecified will prevent the middleware from resolving names.
        """
        return [
            (request_parameter_normalizer,
             'request_param_normalizer'),  # Delete
            (gas_price_strategy_middleware, 'gas_price_strategy'),
            (name_to_address_middleware(web3), 'name_to_address'),  # Add Async
            (attrdict_middleware, 'attrdict'),  # Delete
            (pythonic_middleware, 'pythonic'),  # Delete
            (validation_middleware, 'validation'),
            (abi_middleware, 'abi'),  # Delete
            (buffered_gas_estimate_middleware, 'gas_estimate'),
        ]

    #
    # Provider requests and response
    #
    def _make_request(self, method: Union[RPCEndpoint, Callable[...,
                                                                RPCEndpoint]],
                      params: Any) -> RPCResponse:
        request_func = self.provider.request_func(self.web3,
                                                  self.middleware_onion)
        self.logger.debug("Making request. Method: %s", method)
        return request_func(method, params)

    async def _coro_make_request(self, method: Union[RPCEndpoint,
                                                     Callable[...,
                                                              RPCEndpoint]],
                                 params: Any) -> RPCResponse:
        # type ignored b/c request_func is an awaitable in async model
        request_func = await self.provider.request_func(  # type: ignore
            self.web3, self.middleware_onion)
        self.logger.debug("Making request. Method: %s", method)
        return await request_func(method, params)

    @staticmethod
    def formatted_response(
        response: RPCResponse,
        params: Any,
        error_formatters: Optional[Callable[..., Any]] = None,
        null_result_formatters: Optional[Callable[..., Any]] = None,
    ) -> Any:
        if "error" in response:
            apply_error_formatters(error_formatters, response)
            raise ValueError(response["error"])
        # NULL_RESPONSES includes None, so return False here as the default
        # so we don't apply the null_result_formatters if there is no 'result' key
        elif response.get('result', False) in NULL_RESPONSES:
            # null_result_formatters raise either a BlockNotFound
            # or a TransactionNotFound error, depending on the method called
            apply_null_result_formatters(null_result_formatters, response,
                                         params)
            return response['result']
        elif response.get('result') is not None:
            return response['result']
        else:
            raise BadResponseFormat(
                "The response was in an unexpected format and unable to be parsed. "
                f"The raw response is: {response}")

    def request_blocking(
        self,
        method: Union[RPCEndpoint, Callable[..., RPCEndpoint]],
        params: Any,
        error_formatters: Optional[Callable[..., Any]] = None,
        null_result_formatters: Optional[Callable[..., Any]] = None,
    ) -> Any:
        """
        Make a synchronous request using the provider
        """
        response = self._make_request(method, params)
        return self.formatted_response(response, params, error_formatters,
                                       null_result_formatters)

    async def coro_request(
        self,
        method: Union[RPCEndpoint, Callable[..., RPCEndpoint]],
        params: Any,
        error_formatters: Optional[Callable[..., Any]] = None,
        null_result_formatters: Optional[Callable[..., Any]] = None,
    ) -> Any:
        """
        Couroutine for making a request using the provider
        """
        response = await self._coro_make_request(method, params)
        return self.formatted_response(response, params, error_formatters,
                                       null_result_formatters)

    @deprecated_for("coro_request")
    def request_async(self, raw_method: str, raw_params: Any) -> UUID:
        request_id = uuid.uuid4()
        self.pending_requests[request_id] = spawn(
            self.request_blocking,
            raw_method=raw_method,
            raw_params=raw_params,
        )
        return request_id

    def receive_blocking(self,
                         request_id: UUID,
                         timeout: Optional[float] = None) -> Any:
        try:
            request = self.pending_requests.pop(request_id)
        except KeyError:
            raise KeyError("Request for id:{0} not found".format(request_id))
        else:
            response = request.get(timeout=timeout)

        if "error" in response:
            raise ValueError(response["error"])

        return response['result']

    def receive_async(self, request_id: UUID, *args: Any,
                      **kwargs: Any) -> NoReturn:
        raise NotImplementedError("Callback pattern not implemented")