[docs]classEtcdStorage(Storage):""" Rate limit storage with etcd as backend. Depends on :pypi:`aetcd`. """STORAGE_SCHEME=["async+etcd"]"""The async storage scheme for etcd"""DEPENDENCIES=["aetcd"]PREFIX="limits"MAX_RETRIES=5def__init__(self,uri:str,max_retries:int=MAX_RETRIES,**options:str,)->None:""" :param uri: etcd location of the form ``async+etcd://host:port``, :param max_retries: Maximum number of attempts to retry in the case of concurrent updates to a rate limit key :param options: all remaining keyword arguments are passed directly to the constructor of :class:`aetcd.client.Client` :raise ConfigurationError: when :pypi:`aetcd` is not available """parsed=urllib.parse.urlparse(uri)self.lib=self.dependencies["aetcd"].moduleself.storage:"aetcd.Client"=self.lib.Client(host=parsed.hostname,port=parsed.port,**options)self.max_retries=max_retries@propertydefbase_exceptions(self,)->Union[Type[Exception],Tuple[Type[Exception],...]]:# pragma: no coverreturnself.lib.ClientError# type: ignore[no-any-return]defprefixed_key(self,key:str)->bytes:returnf"{self.PREFIX}/{key}".encode()