Blacksmith API
- blacksmith.scan(*modules: str) None
Collect all resources to fillout the registry.
Basically, it import modules registered using
blacksmith.register()
.- Raises
TypeError – malformed module name
ModuleNotFoundError – unknown package name
AttributeError – argument is a module, not a package.
- blacksmith.register(client_name: str, resource: str, service: str, version: Optional[str], path: Optional[str] = None, contract: Optional[Mapping[Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], Tuple[Type[blacksmith.domain.model.params.Request], Optional[Type[blacksmith.domain.model.params.Response]]]]] = None, collection_path: Optional[str] = None, collection_contract: Optional[Mapping[Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], Tuple[Type[blacksmith.domain.model.params.Request], Optional[Type[blacksmith.domain.model.params.Response]]]]] = None, collection_parser: Optional[Type[blacksmith.domain.model.params.AbstractCollectionParser]] = None) None
Register a resource in a client in the default registry.
See
blacksmith.domain.registry.Registry.register()
for the signature.
- class blacksmith.Request
Request Params Model.
Fields must use subclass
PathInfoField()
,HeaderField()
,QueryStringField()
orPostBodyField()
to declare each fields.- to_http_request(method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], url_pattern: str) blacksmith.domain.model.http.HTTPRequest
Convert the request params to an http request in order to serialize the http request for the client.
- class blacksmith.Response
Response Model.
- classmethod from_http_response(response: blacksmith.domain.model.http.HTTPResponse) Optional[blacksmith.domain.model.params.TResponse]
Build the response from the given HTTPResponse.
- blacksmith.HeaderField(default: Any = PydanticUndefined, *, default_factory: Optional[Callable[[], Any]] = None, alias: unicode = None, title: unicode = None, description: unicode = None, const: bool = None, gt: float = None, ge: float = None, lt: float = None, le: float = None, multiple_of: float = None, min_items: int = None, max_items: int = None, min_length: int = None, max_length: int = None, allow_mutation: bool = True, regex: unicode = None, **extra: Any) Any
Used to provide extra information about a field, either for the model schema or complex validation. Some arguments apply only to number fields (
int
,float
,Decimal
) and some apply only tostr
.- Parameters
default – since this is replacing the field’s default, its first argument is used to set the default, use ellipsis (
...
) to indicate the field is requireddefault_factory – callable that will be called when a default value is needed for this field If both default and default_factory are set, an error is raised.
alias – the public name of the field
title – can be any string, used in the schema
description – can be any string, used in the schema
const – this field is required and must take it’s default value
gt – only applies to numbers, requires the field to be “greater than”. The schema will have an
exclusiveMinimum
validation keywordge – only applies to numbers, requires the field to be “greater than or equal to”. The schema will have a
minimum
validation keywordlt – only applies to numbers, requires the field to be “less than”. The schema will have an
exclusiveMaximum
validation keywordle – only applies to numbers, requires the field to be “less than or equal to”. The schema will have a
maximum
validation keywordmultiple_of – only applies to numbers, requires the field to be “a multiple of”. The schema will have a
multipleOf
validation keywordmin_length – only applies to strings, requires the field to have a minimum length. The schema will have a
maximum
validation keywordmax_length – only applies to strings, requires the field to have a maximum length. The schema will have a
maxLength
validation keywordallow_mutation – a boolean which defaults to True. When False, the field raises a TypeError if the field is assigned on an instance. The BaseModel Config must set validate_assignment to True
regex – only applies to strings, requires the field match agains a regular expression pattern string. The schema will have a
pattern
validation keyword**extra – any additional keyword arguments will be added as is to the schema
- blacksmith.PathInfoField(default: Any = PydanticUndefined, *, default_factory: Optional[Callable[[], Any]] = None, alias: unicode = None, title: unicode = None, description: unicode = None, const: bool = None, gt: float = None, ge: float = None, lt: float = None, le: float = None, multiple_of: float = None, min_items: int = None, max_items: int = None, min_length: int = None, max_length: int = None, allow_mutation: bool = True, regex: unicode = None, **extra: Any) Any
Used to provide extra information about a field, either for the model schema or complex validation. Some arguments apply only to number fields (
int
,float
,Decimal
) and some apply only tostr
.- Parameters
default – since this is replacing the field’s default, its first argument is used to set the default, use ellipsis (
...
) to indicate the field is requireddefault_factory – callable that will be called when a default value is needed for this field If both default and default_factory are set, an error is raised.
alias – the public name of the field
title – can be any string, used in the schema
description – can be any string, used in the schema
const – this field is required and must take it’s default value
gt – only applies to numbers, requires the field to be “greater than”. The schema will have an
exclusiveMinimum
validation keywordge – only applies to numbers, requires the field to be “greater than or equal to”. The schema will have a
minimum
validation keywordlt – only applies to numbers, requires the field to be “less than”. The schema will have an
exclusiveMaximum
validation keywordle – only applies to numbers, requires the field to be “less than or equal to”. The schema will have a
maximum
validation keywordmultiple_of – only applies to numbers, requires the field to be “a multiple of”. The schema will have a
multipleOf
validation keywordmin_length – only applies to strings, requires the field to have a minimum length. The schema will have a
maximum
validation keywordmax_length – only applies to strings, requires the field to have a maximum length. The schema will have a
maxLength
validation keywordallow_mutation – a boolean which defaults to True. When False, the field raises a TypeError if the field is assigned on an instance. The BaseModel Config must set validate_assignment to True
regex – only applies to strings, requires the field match agains a regular expression pattern string. The schema will have a
pattern
validation keyword**extra – any additional keyword arguments will be added as is to the schema
- blacksmith.PostBodyField(default: Any = PydanticUndefined, *, default_factory: Optional[Callable[[], Any]] = None, alias: unicode = None, title: unicode = None, description: unicode = None, const: bool = None, gt: float = None, ge: float = None, lt: float = None, le: float = None, multiple_of: float = None, min_items: int = None, max_items: int = None, min_length: int = None, max_length: int = None, allow_mutation: bool = True, regex: unicode = None, **extra: Any) Any
Used to provide extra information about a field, either for the model schema or complex validation. Some arguments apply only to number fields (
int
,float
,Decimal
) and some apply only tostr
.- Parameters
default – since this is replacing the field’s default, its first argument is used to set the default, use ellipsis (
...
) to indicate the field is requireddefault_factory – callable that will be called when a default value is needed for this field If both default and default_factory are set, an error is raised.
alias – the public name of the field
title – can be any string, used in the schema
description – can be any string, used in the schema
const – this field is required and must take it’s default value
gt – only applies to numbers, requires the field to be “greater than”. The schema will have an
exclusiveMinimum
validation keywordge – only applies to numbers, requires the field to be “greater than or equal to”. The schema will have a
minimum
validation keywordlt – only applies to numbers, requires the field to be “less than”. The schema will have an
exclusiveMaximum
validation keywordle – only applies to numbers, requires the field to be “less than or equal to”. The schema will have a
maximum
validation keywordmultiple_of – only applies to numbers, requires the field to be “a multiple of”. The schema will have a
multipleOf
validation keywordmin_length – only applies to strings, requires the field to have a minimum length. The schema will have a
maximum
validation keywordmax_length – only applies to strings, requires the field to have a maximum length. The schema will have a
maxLength
validation keywordallow_mutation – a boolean which defaults to True. When False, the field raises a TypeError if the field is assigned on an instance. The BaseModel Config must set validate_assignment to True
regex – only applies to strings, requires the field match agains a regular expression pattern string. The schema will have a
pattern
validation keyword**extra – any additional keyword arguments will be added as is to the schema
- blacksmith.QueryStringField(default: Any = PydanticUndefined, *, default_factory: Optional[Callable[[], Any]] = None, alias: unicode = None, title: unicode = None, description: unicode = None, const: bool = None, gt: float = None, ge: float = None, lt: float = None, le: float = None, multiple_of: float = None, min_items: int = None, max_items: int = None, min_length: int = None, max_length: int = None, allow_mutation: bool = True, regex: unicode = None, **extra: Any) Any
Used to provide extra information about a field, either for the model schema or complex validation. Some arguments apply only to number fields (
int
,float
,Decimal
) and some apply only tostr
.- Parameters
default – since this is replacing the field’s default, its first argument is used to set the default, use ellipsis (
...
) to indicate the field is requireddefault_factory – callable that will be called when a default value is needed for this field If both default and default_factory are set, an error is raised.
alias – the public name of the field
title – can be any string, used in the schema
description – can be any string, used in the schema
const – this field is required and must take it’s default value
gt – only applies to numbers, requires the field to be “greater than”. The schema will have an
exclusiveMinimum
validation keywordge – only applies to numbers, requires the field to be “greater than or equal to”. The schema will have a
minimum
validation keywordlt – only applies to numbers, requires the field to be “less than”. The schema will have an
exclusiveMaximum
validation keywordle – only applies to numbers, requires the field to be “less than or equal to”. The schema will have a
maximum
validation keywordmultiple_of – only applies to numbers, requires the field to be “a multiple of”. The schema will have a
multipleOf
validation keywordmin_length – only applies to strings, requires the field to have a minimum length. The schema will have a
maximum
validation keywordmax_length – only applies to strings, requires the field to have a maximum length. The schema will have a
maxLength
validation keywordallow_mutation – a boolean which defaults to True. When False, the field raises a TypeError if the field is assigned on an instance. The BaseModel Config must set validate_assignment to True
regex – only applies to strings, requires the field match agains a regular expression pattern string. The schema will have a
pattern
validation keyword**extra – any additional keyword arguments will be added as is to the schema
- class blacksmith.ResponseBox(response: blacksmith.domain.model.http.HTTPResponse, response_schema: Optional[Type[blacksmith.domain.model.params.Response]], method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], path: str, name: str, client_name: str)
Wrap an http response to deseriaze it.
It’s also allow users to write some userfull typing inference such as:
user: User = (await api.user.get({"username": username})).response print(user.username) # declaring the type User make code analyzer happy.
- property json: Optional[Dict[str, Any]]
Return the raw json response.
- property response: blacksmith.domain.model.params.TResponse
Parse the response using the schema.
- Raises
NoResponseSchemaException – if the response_schema has not been set in the contract.
- class blacksmith.CollectionIterator(response: blacksmith.domain.model.http.HTTPResponse, response_schema: Optional[Type[blacksmith.domain.model.params.Response]], collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser])
Deserialize the models in a json response list, item by item.
- property meta: blacksmith.domain.model.params.Metadata
Get the response metadata such as counts in http header, links…
Those metadata are generated by the collection_parser.
- class blacksmith.AbstractCollectionParser(resp: blacksmith.domain.model.http.HTTPResponse)
Signature of the collection parser.
- abstract property meta: blacksmith.domain.model.params.Metadata
Return the metatadata from the response.
Usually, metadata are in a header, but if the API wrap the list,
{ "total_items": 0, "items": [] }
Then, the
Metadata.total_count
can be extracted from the json, instead of the header.
- abstract property json: List[Any]
Return the list part of the response the response.
For instance, if an API wrap the list in a structure like
{ "items": [ {"objkey": "objval"} ] }
then, the
resp.json["items"]
has to be returned.
- class blacksmith.CollectionParser(resp: blacksmith.domain.model.http.HTTPResponse)
Handle the rest collection metadata parser.
Deserialize how a collection is wrapped.
- total_count_header: str = 'Total-Count'
- property meta: blacksmith.domain.model.params.Metadata
Return the metatadata from the response.
Usually, metadata are in a header, but if the API wrap the list,
{ "total_items": 0, "items": [] }
Then, the
Metadata.total_count
can be extracted from the json, instead of the header.
- property json: List[Optional[Any]]
Return the list part of the response the response.
For instance, if an API wrap the list in a structure like
{ "items": [ {"objkey": "objval"} ] }
then, the
resp.json["items"]
has to be returned.
- exception blacksmith.HTTPError(message: str, request: blacksmith.domain.model.http.HTTPRequest, response: blacksmith.domain.model.http.HTTPResponse)
Represent the http error.
- class HTTPRequest(method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], url_pattern: str, path: Dict[str, Union[str, int, float, bool]] = <factory>, querystring: Dict[str, Union[str, int, float, bool, List[Union[str, int, float, bool]]]] = <factory>, headers: Dict[str, str] = <factory>, body: str = '')
Internal representation of an http request.
Note that the HTTP method is not present, because the method is the funcion called.
The HTTP Request is filled out using the
blacksmith.domain.model.params.Request
schema.- body: str = ''
- property url: str
- method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']
- url_pattern: str
- path: Dict[str, Union[str, int, float, bool]]
- querystring: Dict[str, Union[str, int, float, bool, List[Union[str, int, float, bool]]]]
- headers: Dict[str, str]
- class HTTPResponse(status_code: int, headers: Mapping[str, str], json: Optional[Any])
Internal representation of an http response.
- property links: Dict[Optional[str], Dict[str, str]]
- status_code: int
HTTP Status code.
- headers: Mapping[str, str]
Header of the response.
- json: Optional[Any]
Json Body of the response.
- property status_code: int
- property json: Optional[Any]
- property is_client_error: bool
- property is_server_error: bool
- exception blacksmith.HTTPTimeoutError
Represent the http timeout error.
- class blacksmith.HTTPTimeout(read: float = 30.0, connect: float = 15.0)
Request timeout.
- read: float
- connect: float
- class blacksmith.AsyncClientFactory(sd: blacksmith.sd._async.base.AsyncAbstractServiceDiscovery, transport: Optional[blacksmith.service._async.base.AsyncAbstractTransport] = None, registry: blacksmith.domain.registry.Registry = <blacksmith.domain.registry.Registry object>, timeout: Union[blacksmith.domain.model.http.HTTPTimeout, float, Tuple[float, float]] = <blacksmith.domain.model.http.HTTPTimeout object>, proxies: Optional[Union[URL, str, Proxy, Dict[Union[URL, str], Union[None, URL, str, Proxy]]]] = None, verify_certificate: bool = False, collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser] = <class 'blacksmith.domain.model.params.CollectionParser'>)
Client creator, for the given configuration.
- Parameters
sd – Service Discovery instance
transport – HTTP Client that process the call, default use
blacksmith.service._async.adapters.httpx.HttpxTransport
timeout – configure timeout, this parameter is ignored if the transport has been passed
proxies – configure proxies, this parameter is ignored if the transport has been passed
verify_certificate – Reject request if certificate are invalid for https
collection_parser – use to customize the collection parser default use
blacksmith.domain.model.params.CollectionParser
- registry: blacksmith.domain.registry.Registry
- collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser]
- middlewares: List[blacksmith.middleware._async.base.AsyncHTTPMiddleware]
- add_middleware(middleware: blacksmith.middleware._async.base.AsyncHTTPMiddleware) blacksmith.service._async.client.AsyncClientFactory[blacksmith.domain.model.params.TCollectionResponse, blacksmith.domain.model.params.TResponse]
Add a middleware to the client factory and return the client for chaining.
- ..note:: Clients created before the call of this method will also be
altered. The middleware stack is a reference for all clients.
- async initialize() None
- class blacksmith.SyncClientFactory(sd: blacksmith.sd._sync.base.SyncAbstractServiceDiscovery, transport: Optional[blacksmith.service._sync.base.SyncAbstractTransport] = None, registry: blacksmith.domain.registry.Registry = <blacksmith.domain.registry.Registry object>, timeout: Union[blacksmith.domain.model.http.HTTPTimeout, float, Tuple[float, float]] = <blacksmith.domain.model.http.HTTPTimeout object>, proxies: Optional[Union[URL, str, Proxy, Dict[Union[URL, str], Union[None, URL, str, Proxy]]]] = None, verify_certificate: bool = False, collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser] = <class 'blacksmith.domain.model.params.CollectionParser'>)
Client creator, for the given configuration.
- Parameters
sd – Service Discovery instance
transport – HTTP Client that process the call, default use
blacksmith.service._async.adapters.httpx.HttpxTransport
timeout – configure timeout, this parameter is ignored if the transport has been passed
proxies – configure proxies, this parameter is ignored if the transport has been passed
verify_certificate – Reject request if certificate are invalid for https
collection_parser – use to customize the collection parser default use
blacksmith.domain.model.params.CollectionParser
- registry: blacksmith.domain.registry.Registry
- collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser]
- middlewares: List[blacksmith.middleware._sync.base.SyncHTTPMiddleware]
- add_middleware(middleware: blacksmith.middleware._sync.base.SyncHTTPMiddleware) blacksmith.service._sync.client.SyncClientFactory[blacksmith.domain.model.params.TCollectionResponse, blacksmith.domain.model.params.TResponse]
Add a middleware to the client factory and return the client for chaining.
- ..note:: Clients created before the call of this method will also be
altered. The middleware stack is a reference for all clients.
- initialize() None
- class blacksmith.AsyncClient(name: str, endpoint: str, resources: Mapping[str, blacksmith.domain.registry.ApiRoutes], transport: blacksmith.service._async.base.AsyncAbstractTransport, timeout: blacksmith.domain.model.http.HTTPTimeout, collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser], middlewares: List[blacksmith.middleware._async.base.AsyncHTTPMiddleware])
Client representation for the client name.
A client will have dymanic property, based on the registered resources.
- name: str
- endpoint: str
- resources: Mapping[str, blacksmith.domain.registry.ApiRoutes]
- collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser]
- middlewares: List[blacksmith.middleware._async.base.AsyncHTTPMiddleware]
- add_middleware(middleware: blacksmith.middleware._async.base.AsyncHTTPMiddleware) blacksmith.service._async.client.AsyncClient[blacksmith.domain.model.params.TCollectionResponse, blacksmith.domain.model.params.TResponse]
- class blacksmith.SyncClient(name: str, endpoint: str, resources: Mapping[str, blacksmith.domain.registry.ApiRoutes], transport: blacksmith.service._sync.base.SyncAbstractTransport, timeout: blacksmith.domain.model.http.HTTPTimeout, collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser], middlewares: List[blacksmith.middleware._sync.base.SyncHTTPMiddleware])
Client representation for the client name.
A client will have dymanic property, based on the registered resources.
- name: str
- endpoint: str
- resources: Mapping[str, blacksmith.domain.registry.ApiRoutes]
- collection_parser: Type[blacksmith.domain.model.params.AbstractCollectionParser]
- middlewares: List[blacksmith.middleware._sync.base.SyncHTTPMiddleware]
- add_middleware(middleware: blacksmith.middleware._sync.base.SyncHTTPMiddleware) blacksmith.service._sync.client.SyncClient[blacksmith.domain.model.params.TCollectionResponse, blacksmith.domain.model.params.TResponse]
- class blacksmith.AsyncAbstractServiceDiscovery
Define the Service Discovery interface.
- abstract async get_endpoint(service: str, version: Optional[str]) str
Get the endpoint of a service.
- class blacksmith.SyncAbstractServiceDiscovery
Define the Service Discovery interface.
- abstract get_endpoint(service: str, version: Optional[str]) str
Get the endpoint of a service.
- class blacksmith.AsyncConsulDiscovery(addr: str = 'http://consul:8500/v1', service_name_fmt: str = '{service}-{version}', service_url_fmt: str = 'http://{address}:{port}/{version}', unversioned_service_name_fmt: str = '{service}', unversioned_service_url_fmt: str = 'http://{address}:{port}', consul_token: str = '', _client_factory: Callable[[str, str], blacksmith.service._async.client.AsyncClientFactory[blacksmith.sd._async.adapters.consul.Service, Any]] = <function blacksmith_cli>)
A discovery instance based on a Consul server.
- Parameters
service_name_fmt – pattern for name of versionned service
service_url_fmt – pattern for url of versionned service
unversioned_service_name_fmt – pattern for name of unversioned service
unversioned_service_url_fmt – pattern for url of unversioned service
- service_name_fmt: str
- service_url_fmt: str
- unversioned_service_name_fmt: str
- unversioned_service_url_fmt: str
- format_service_name(service: str, version: Optional[str]) str
Build the service name to send to consul.
- format_endoint(version: Optional[str], address: str, port: int) str
Build the rest api endpoint from consul response.
- async resolve(service: str, version: Optional[str]) blacksmith.sd._async.adapters.consul.Service
Get the
Service
from the consul registry.If many instances host the service, the host is choosen randomly.
- async get_endpoint(service: str, version: Optional[str]) str
Get the endpoint from the consul registry
If many instances host the service, the host is choosen randomly.
- class blacksmith.SyncConsulDiscovery(addr: str = 'http://consul:8500/v1', service_name_fmt: str = '{service}-{version}', service_url_fmt: str = 'http://{address}:{port}/{version}', unversioned_service_name_fmt: str = '{service}', unversioned_service_url_fmt: str = 'http://{address}:{port}', consul_token: str = '', _client_factory: Callable[[str, str], blacksmith.service._sync.client.SyncClientFactory[blacksmith.sd._sync.adapters.consul.Service, Any]] = <function blacksmith_cli>)
A discovery instance based on a Consul server.
- Parameters
service_name_fmt – pattern for name of versionned service
service_url_fmt – pattern for url of versionned service
unversioned_service_name_fmt – pattern for name of unversioned service
unversioned_service_url_fmt – pattern for url of unversioned service
- service_name_fmt: str
- service_url_fmt: str
- unversioned_service_name_fmt: str
- unversioned_service_url_fmt: str
- format_service_name(service: str, version: Optional[str]) str
Build the service name to send to consul.
- format_endoint(version: Optional[str], address: str, port: int) str
Build the rest api endpoint from consul response.
- resolve(service: str, version: Optional[str]) blacksmith.sd._sync.adapters.consul.Service
Get the
Service
from the consul registry.If many instances host the service, the host is choosen randomly.
- get_endpoint(service: str, version: Optional[str]) str
Get the endpoint from the consul registry
If many instances host the service, the host is choosen randomly.
- class blacksmith.AsyncRouterDiscovery(service_url_fmt: str = 'http://router/{service}-{version}/{version}', unversioned_service_url_fmt: str = 'http://router/{service}')
Router that implement a Server-Side Service discovery.
This implementation never raise
blacksmith.domain.exceptions.UnregisteredServiceException
when service are unknown, because it only passe very request to the router server that is connected to the service registry.Note
Given pattern in parameter have to match the format of the router server.
- Parameters
service_url_fmt – A pattern used to create endpoint of versionned services.
unversioned_service_url_fmt – A pattern used to create endpoint of unversionned services.
- service_url_fmt: str
- unversioned_service_url_fmt: str
- async get_endpoint(service: str, version: Optional[str]) str
Create and return the endpoint using the given parameters service_url_fmt or unversioned_service_url_fmt if version is None.
- class blacksmith.SyncRouterDiscovery(service_url_fmt: str = 'http://router/{service}-{version}/{version}', unversioned_service_url_fmt: str = 'http://router/{service}')
Router that implement a Server-Side Service discovery.
This implementation never raise
blacksmith.domain.exceptions.UnregisteredServiceException
when service are unknown, because it only passe very request to the router server that is connected to the service registry.Note
Given pattern in parameter have to match the format of the router server.
- Parameters
service_url_fmt – A pattern used to create endpoint of versionned services.
unversioned_service_url_fmt – A pattern used to create endpoint of unversionned services.
- service_url_fmt: str
- unversioned_service_url_fmt: str
- get_endpoint(service: str, version: Optional[str]) str
Create and return the endpoint using the given parameters service_url_fmt or unversioned_service_url_fmt if version is None.
- class blacksmith.AsyncStaticDiscovery(endpoints: Mapping[Tuple[str, Optional[str]], str])
A discovery instance based on a static dictionary.
- endpoints: Mapping[Tuple[str, Optional[str]], str]
- async get_endpoint(service: str, version: Optional[str]) str
Retrieve endpoint using the given parameters from endpoints.
- class blacksmith.SyncStaticDiscovery(endpoints: Mapping[Tuple[str, Optional[str]], str])
A discovery instance based on a static dictionary.
- endpoints: Mapping[Tuple[str, Optional[str]], str]
- get_endpoint(service: str, version: Optional[str]) str
Retrieve endpoint using the given parameters from endpoints.
- class blacksmith.AsyncMiddleware(*args, **kwargs)
Signature of the middleware for the async version.
- class blacksmith.SyncMiddleware(*args, **kwargs)
Signature of the middleware for the sync version.
- class blacksmith.AsyncHTTPMiddleware
Inject data in http query on every requests.
- async initialize() None
Asynchronous initialization of a middleware.
For instance, used to initialize connection to storage backend.
- class blacksmith.SyncHTTPMiddleware
Inject data in http query on every requests.
- initialize() None
Asynchronous initialization of a middleware.
For instance, used to initialize connection to storage backend.
- class blacksmith.AsyncHTTPAddHeadersMiddleware(headers: Dict[str, str])
Generic middleware that inject HTTP headers.
- Params
headers to inject in HTTP requests.
- headers: Dict[str, str]
- class blacksmith.SyncHTTPAddHeadersMiddleware(headers: Dict[str, str])
Generic middleware that inject HTTP headers.
- Params
headers to inject in HTTP requests.
- headers: Dict[str, str]
- class blacksmith.AsyncHTTPAuthorizationMiddleware(scheme: str, value: str)
Authentication Mechanism based on the header Authorization.
- Parameters
scheme – the scheme of the mechanism.
value – the value that authenticate the user using the scheme.
- headers: Dict[str, str]
- class blacksmith.SyncHTTPAuthorizationMiddleware(scheme: str, value: str)
Authentication Mechanism based on the header Authorization.
- Parameters
scheme – the scheme of the mechanism.
value – the value that authenticate the user using the scheme.
- headers: Dict[str, str]
- class blacksmith.AsyncHTTPBearerMiddleware(bearer_token: str)
Authentication Mechanism based on the header Authorization with the Bearer scheme.
- Parameters
value – value of the bearer token.
- headers: Dict[str, str]
- class blacksmith.SyncHTTPBearerMiddleware(bearer_token: str)
Authentication Mechanism based on the header Authorization with the Bearer scheme.
- Parameters
value – value of the bearer token.
- headers: Dict[str, str]
- class blacksmith.AsyncCircuitBreakerMiddleware(threshold: int = 5, ttl: float = 30, listeners: Optional[Iterable[Callable[[str, Literal['circuit_breaker_created', 'state_changed', 'failed', 'recovered'], purgatory.domain.messages.base.Event], None]]] = None, uow: Optional[purgatory.service._async.unit_of_work.AsyncAbstractUnitOfWork] = None, metrics: Optional[blacksmith.domain.model.middleware.prometheus.PrometheusMetrics] = None)
Prevent cascading failure.
The circuit breaker is based on purgatory, the middleware create one circuit breaker per client_name. The parameters are forwarded to all the clients. This middleware does not give the possibility to adapt a threshold or the time the circuit is opened per clients.
- async initialize() None
Asynchronous initialization of a middleware.
For instance, used to initialize connection to storage backend.
- class blacksmith.SyncCircuitBreakerMiddleware(threshold: int = 5, ttl: float = 30, listeners: Optional[Iterable[Callable[[str, Literal['circuit_breaker_created', 'state_changed', 'failed', 'recovered'], purgatory.domain.messages.base.Event], None]]] = None, uow: Optional[purgatory.service._sync.unit_of_work.SyncAbstractUnitOfWork] = None, metrics: Optional[blacksmith.domain.model.middleware.prometheus.PrometheusMetrics] = None)
Prevent cascading failure.
The circuit breaker is based on purgatory, the middleware create one circuit breaker per client_name. The parameters are forwarded to all the clients. This middleware does not give the possibility to adapt a threshold or the time the circuit is opened per clients.
- initialize() None
Asynchronous initialization of a middleware.
For instance, used to initialize connection to storage backend.
- class blacksmith.PrometheusMetrics(buckets: Optional[List[float]] = None, hit_cache_buckets: Optional[List[float]] = None, registry: Optional[Any] = None)
- class blacksmith.AsyncPrometheusMiddleware(metrics: Optional[blacksmith.domain.model.middleware.prometheus.PrometheusMetrics] = None)
Collect the api calls made in a prometheus registry.
It expose a blacksmith_info Gauge to get the blacksmith version, as a label, and a blacksmith_request_latency_seconds_count Counter to get the number of http requests made. The counter blacksmith_request_latency_seconds_count as client_name, method, path and status_code labels.
Note
the service_name and service version is redundant with the client_name, so they are not exposed as labels. By the way, you may have multiple client_name for 1 service name/version.
- class blacksmith.SyncPrometheusMiddleware(metrics: Optional[blacksmith.domain.model.middleware.prometheus.PrometheusMetrics] = None)
Collect the api calls made in a prometheus registry.
It expose a blacksmith_info Gauge to get the blacksmith version, as a label, and a blacksmith_request_latency_seconds_count Counter to get the number of http requests made. The counter blacksmith_request_latency_seconds_count as client_name, method, path and status_code labels.
Note
the service_name and service version is redundant with the client_name, so they are not exposed as labels. By the way, you may have multiple client_name for 1 service name/version.
- class blacksmith.AbstractCachePolicy
Define the Cache Policy
- abstract handle_request(req: blacksmith.domain.model.http.HTTPRequest, client_name: str, path: str) bool
A function to decide if the http request is cachable.
- abstract get_vary_key(client_name: str, path: str, request: blacksmith.domain.model.http.HTTPRequest) str
Create a caching key for the vary part.
- abstract get_response_cache_key(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest, vary: List[str]) str
Create a caching key for the http response.
- abstract get_cache_info_for_response(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest, resp: blacksmith.domain.model.http.HTTPResponse) Tuple[int, str, List[str]]
Return caching info. Tuple (ttl in seconds, vary key, vary list).
- class blacksmith.AbstractSerializer
- abstract static loads(s: str) Any
Load a string to an object
- abstract static dumps(obj: Any) str
Get a value from redis
- class blacksmith.CacheControlPolicy(sep: str = '$')
Initialize the caching using Cache-Control http headers. Also consume the Vary response header to cache response per Vary response headers per request.
- Parameters
sep – Separator used in cache key MUST NOT BE USED in client name.
- handle_request(req: blacksmith.domain.model.http.HTTPRequest, client_name: str, path: str) bool
A function to decide if the http request is cachable.
- get_vary_key(client_name: str, path: str, request: blacksmith.domain.model.http.HTTPRequest) str
Create a caching key for the vary part.
- get_response_cache_key(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest, vary: List[str]) str
Create a caching key for the http response.
- get_cache_info_for_response(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest, resp: blacksmith.domain.model.http.HTTPResponse) Tuple[int, str, List[str]]
Return caching info. Tuple (ttl in seconds, vary key, vary list).
- class blacksmith.JsonSerializer
- static loads(s: str) Any
Load a string to an object
- static dumps(obj: Any) str
Get a value from redis
- class blacksmith.AsyncAbstractCache
Abstract Redis Client.
- abstract async initialize() None
Initialize the cache
- abstract async get(key: str) Optional[str]
Get a value from redis
- abstract async set(key: str, val: str, ex: datetime.timedelta) None
Get a value from redis
- class blacksmith.AsyncHTTPCacheMiddleware(cache: blacksmith.middleware._async.http_cache.AsyncAbstractCache, metrics: Optional[blacksmith.domain.model.middleware.prometheus.PrometheusMetrics] = None, policy: blacksmith.domain.model.middleware.http_cache.AbstractCachePolicy = <blacksmith.domain.model.middleware.http_cache.CacheControlPolicy object>, serializer: Type[blacksmith.domain.model.middleware.http_cache.AbstractSerializer] = <class 'blacksmith.domain.model.middleware.http_cache.JsonSerializer'>)
Http Cache Middleware based on Cache-Control and redis.
- async initialize() None
Asynchronous initialization of a middleware.
For instance, used to initialize connection to storage backend.
- async cache_response(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest, resp: blacksmith.domain.model.http.HTTPResponse) bool
- async get_from_cache(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest) Optional[blacksmith.domain.model.http.HTTPResponse]
- observe_cache_hit(client_name: str, method: str, path: str, status_code: int, latency: float) None
- inc_cache_miss(client_name: str, cachable_state: Literal['uncachable_request', 'uncachable_response', 'cached'], method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], path: str, status_code: int) None
- class blacksmith.SyncHTTPCacheMiddleware(cache: blacksmith.middleware._sync.http_cache.SyncAbstractCache, metrics: Optional[blacksmith.domain.model.middleware.prometheus.PrometheusMetrics] = None, policy: blacksmith.domain.model.middleware.http_cache.AbstractCachePolicy = <blacksmith.domain.model.middleware.http_cache.CacheControlPolicy object>, serializer: Type[blacksmith.domain.model.middleware.http_cache.AbstractSerializer] = <class 'blacksmith.domain.model.middleware.http_cache.JsonSerializer'>)
Http Cache Middleware based on Cache-Control and redis.
- initialize() None
Asynchronous initialization of a middleware.
For instance, used to initialize connection to storage backend.
- cache_response(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest, resp: blacksmith.domain.model.http.HTTPResponse) bool
- get_from_cache(client_name: str, path: str, req: blacksmith.domain.model.http.HTTPRequest) Optional[blacksmith.domain.model.http.HTTPResponse]
- observe_cache_hit(client_name: str, method: str, path: str, status_code: int, latency: float) None
- inc_cache_miss(client_name: str, cachable_state: Literal['uncachable_request', 'uncachable_response', 'cached'], method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], path: str, status_code: int) None
- class blacksmith.AbstractTraceContext(name: str, kind: str = 'SERVER')
Interface of the trace context for the middleware.
See examples with starlette-zipking for an implementation.
- abstract classmethod make_headers() Dict[str, str]
Build headers for the sub requests.
- abstract tag(key: str, value: str) blacksmith.domain.model.middleware.zipkin.AbstractTraceContext
Tag the span
- abstract annotate(value: Optional[str], ts: Optional[float] = None) blacksmith.domain.model.middleware.zipkin.AbstractTraceContext
Annotate the span
- class blacksmith.AsyncZipkinMiddleware(trace: Type[blacksmith.middleware._async.zipkin.AbstractTraceContext])
Zipkin Middleware based on an abstract context manager.
- Parameters
trace – A deferred context manager that manage the trace span stack.
- class blacksmith.AsyncAbstractTransport(verify_certificate: bool = True, proxies: Optional[Union[URL, str, Proxy, Dict[Union[URL, str], Union[None, URL, str, Proxy]]]] = None)
- verify_certificate: bool
- proxies: Optional[Union[URL, str, Proxy, Dict[Union[URL, str], Union[None, URL, str, Proxy]]]]
- class blacksmith.SyncAbstractTransport(verify_certificate: bool = True, proxies: Optional[Union[URL, str, Proxy, Dict[Union[URL, str], Union[None, URL, str, Proxy]]]] = None)
- verify_certificate: bool
- proxies: Optional[Union[URL, str, Proxy, Dict[Union[URL, str], Union[None, URL, str, Proxy]]]]
- class blacksmith.HTTPRequest(method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], url_pattern: str, path: Dict[str, Union[str, int, float, bool]] = <factory>, querystring: Dict[str, Union[str, int, float, bool, List[Union[str, int, float, bool]]]] = <factory>, headers: Dict[str, str] = <factory>, body: str = '')
Internal representation of an http request.
Note that the HTTP method is not present, because the method is the funcion called.
The HTTP Request is filled out using the
blacksmith.domain.model.params.Request
schema.- method: Literal['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']
- url_pattern: str
- path: Dict[str, Union[str, int, float, bool]]
- querystring: Dict[str, Union[str, int, float, bool, List[Union[str, int, float, bool]]]]
- headers: Dict[str, str]
- body: str = ''
- property url: str
- class blacksmith.HTTPResponse(status_code: int, headers: Mapping[str, str], json: Optional[Any])
Internal representation of an http response.
- status_code: int
HTTP Status code.
- headers: Mapping[str, str]
Header of the response.
- json: Optional[Any]
Json Body of the response.
- property links: Dict[Optional[str], Dict[str, str]]