# --------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # --------------------------------------------------------- from functools import wraps from typing import Any, Callable, Optional from typing_extensions import Concatenate, ParamSpec, Self from azure.core.configuration import Configuration from azure.core.pipeline import Pipeline from azure.core.pipeline.policies import ( CustomHookPolicy, HeadersPolicy, HttpLoggingPolicy, NetworkTraceLoggingPolicy, ProxyPolicy, RedirectPolicy, RetryPolicy, UserAgentPolicy, ) from azure.core.pipeline.transport import ( # pylint: disable=non-abstract-transport-import,no-name-in-module HttpTransport, RequestsTransport, ) from azure.core.rest import HttpRequest, HttpResponse def _request_function(f: Callable[["HttpPipeline"], None]): """A decorator that provides the implementation for the request-style convenience functions of the HttpPipeline class. :param Callable[[], None] f: A function whose name will be used as the http request method :return: An HTTP request function :rtype: Callable """ # This is a hack to provide richer typing for the decorated function # The outer _ function allows us to pattern match on the parameter types # of HttpRequest and forward those types to the decorated function P = ParamSpec("P") def _(_: Callable[Concatenate[str, P], Any] = HttpRequest): @wraps(f) # pylint: disable-next=docstring-missing-param def decorated(self: "HttpPipeline", *args: P.args, **kwargs: P.kwargs) -> HttpResponse: """A function that sends an HTTP request and returns the response. Accepts the same parameters as azure.core.rest.HttpRequest, except for the method. All other kwargs are forwarded to azure.core.Pipeline.run :return: The request response :rtype: HttpResponse """ request = HttpRequest( f.__name__.upper(), *args, params=kwargs.pop("params", None), headers=kwargs.pop("headers", None), json=kwargs.pop("json", None), content=kwargs.pop("content", None), data=kwargs.pop("data", None), files=kwargs.pop("files", None), ) return self.run(request, **kwargs).http_response return decorated return _() class HttpPipeline(Pipeline): """A *very* thin wrapper over azure.core.pipeline.Pipeline that facilitates sending miscellaneous http requests by adding: * A requests-style api for sending http requests * Facilities for populating policies for the client, include defaults, and re-using policies from an existing client. """ def __init__( self, *, transport: Optional[HttpTransport] = None, config: Optional[Configuration] = None, user_agent_policy: Optional[UserAgentPolicy] = None, headers_policy: Optional[HeadersPolicy] = None, proxy_policy: Optional[ProxyPolicy] = None, logging_policy: Optional[NetworkTraceLoggingPolicy] = None, http_logging_policy: Optional[HttpLoggingPolicy] = None, retry_policy: Optional[RetryPolicy] = None, custom_hook_policy: Optional[CustomHookPolicy] = None, redirect_policy: Optional[RedirectPolicy] = None, **kwargs ): """ :param HttpTransport transport: Http Transport used for requests, defaults to RequestsTransport :param Configuration config: :param UserAgentPolicy user_agent_policy: :param HeadersPolicy headers_policy: :param ProxyPolicy proxy_policy: :param NetworkTraceLoggingPolicy logging_policy: :param HttpLoggingPolicy http_logging_policy: :param RetryPolicy retry_policy: :param CustomHookPolicy custom_hook_policy: :param RedirectPolicy redirect_policy: """ config = config or Configuration() config.headers_policy = headers_policy or config.headers_policy or HeadersPolicy(**kwargs) config.proxy_policy = proxy_policy or config.proxy_policy or ProxyPolicy(**kwargs) config.redirect_policy = redirect_policy or config.redirect_policy or RedirectPolicy(**kwargs) config.retry_policy = retry_policy or config.retry_policy or RetryPolicy(**kwargs) config.custom_hook_policy = custom_hook_policy or config.custom_hook_policy or CustomHookPolicy(**kwargs) config.logging_policy = logging_policy or config.logging_policy or NetworkTraceLoggingPolicy(**kwargs) config.http_logging_policy = http_logging_policy or config.http_logging_policy or HttpLoggingPolicy(**kwargs) config.user_agent_policy = user_agent_policy or config.user_agent_policy or UserAgentPolicy(**kwargs) config.polling_interval = kwargs.get("polling_interval", 30) super().__init__( # RequestsTransport normally should not be imported outside of azure.core, since transports # are meant to be user configurable. # RequestsTransport is only used in this file as the default transport when not user specified. transport=transport or RequestsTransport(**kwargs), policies=[ config.headers_policy, config.user_agent_policy, config.proxy_policy, config.redirect_policy, config.retry_policy, config.authentication_policy, config.custom_hook_policy, config.logging_policy, ], ) self._config = config def with_policies(self, **kwargs) -> Self: """A named constructor which facilitates creating a new pipeline using an existing one as a base. Accepts the same parameters as __init__ :return: new Pipeline object with combined config of current object and specified overrides :rtype: Self """ cls = self.__class__ return cls(config=self._config, transport=kwargs.pop("transport", self._transport), **kwargs) @_request_function def delete(self) -> None: """Sends a DELETE request.""" @_request_function def get(self) -> None: """Sends a GET request.""" @_request_function def head(self) -> None: """Sends a HEAD request.""" @_request_function def options(self) -> None: """Sends a OPTIONS request.""" @_request_function def patch(self) -> None: """Sends a PATCH request.""" @_request_function def post(self) -> None: """Sends a POST request.""" @_request_function def put(self) -> None: """Sends a PUT request."""