mantelo.internal.api
====================

.. py:module:: mantelo.internal.api

.. autoapi-nested-parse::

   This module is highly inspired from the awesome slumber library. I decided to port it to mantelo
   (with some improvements) due to the lack of active development in slumber since 2018.

   Please, do not use :class:`~.API` directly, but use :class:`~.KeycloakAdmin` instead.



Attributes
----------

.. autoapisummary::

   mantelo.internal.api.DecodedResponse
   mantelo.internal.api.HttpResponse


Classes
-------

.. autoapisummary::

   mantelo.internal.api.Store
   mantelo.internal.api.Resource
   mantelo.internal.api.API


Functions
---------

.. autoapisummary::

   mantelo.internal.api.url_join


Module Contents
---------------

.. py:data:: DecodedResponse
   :type:  TypeAlias
   :value: dict | str | bytes


   The decoded response as a dict, or as a string if no serializer is defined
   or the body is empty. If the body cannot be decoded, the raw bytes are returned
   instead of throwing an error.


.. py:data:: HttpResponse
   :type:  TypeAlias
   :value: DecodedResponse | tuple[requests.Response, DecodedResponse]


   Either the decoded response or a tuple with the raw response and the decoded body
   (see :py:meth:`Resource.as_raw`).


.. py:function:: url_join(base: str, *args: Any) -> str

   Join any number of segments to a base URL.
   Segments not of type string will be converted to strings using :func:`str`.


.. py:class:: Store

   The holder of all the state for a given resource.
   It is immutable, use :meth:`evolve` to create a new instance with updated values.


   .. py:attribute:: base_url
      :type:  str

      The URL this resource targets.



   .. py:attribute:: session
      :type:  requests.Session

      The session to use for all HTTP requests.



   .. py:attribute:: serializers
      :type:  list[mantelo.internal.serializers.BaseSerializer]

      The serializers available for decoding the response's data.
      The first serializer is the default one, used also for encoding the request's data.



   .. py:attribute:: append_slash
      :type:  bool
      :value: True


      Whether to append a slash to the URL before making the request.



   .. py:attribute:: raw
      :type:  bool
      :value: False


      Whether to return the raw response object along with the decoded body.



   .. py:property:: default_serializer
      :type: mantelo.internal.serializers.BaseSerializer


      The serializer used to encode the request's data.



   .. py:method:: get_serializer(content_type: str) -> mantelo.internal.serializers.BaseSerializer | None

      Get the first serializer that matches the given content type, if any.



   .. py:method:: evolve(**kwargs: Any) -> Store

      Create a new instance with the given values mutated.



.. py:class:: Resource(store: Store)

   The magic behind URL translation.

   It provides the magic of translating python code to URLs and HTTP calls. Each instance of a
   resource is tied to a specific URL, and can evolve to a new URL by calling an unknown property
   or attribute. To finally make an HTTP call, use one of the defined methods (:meth:`get`,
   :meth:`post`, etc).

   By default, all HTTP calls return the decoded body (see :py:class:`HttpResponse`), but you can
   also get hold of the raw response by calling :func:`as_raw`.

   :param store: The store object that holds all the state for this resource.
   :type store: _Store


   .. py:method:: __getattr__(item: str) -> Resource

      Add a path segment to the URL.



   .. py:method:: __call__(id: Any = None, /, url_override: str | None = None) -> Resource

      Add a path segment to the URL, or override the URL entirely.

      Use it instead of :func:`__getattr__` either for readability (e.g.
      :python:`api.user("xxx")`), or because the path segment isn't valid Python (e.g.
      :python:`api("123")`).

      :param id: The path segment to add to the URL.
      :type id: any, optional
      :param url_override: The URL to use instead of the current one.
      :type url_override: string, optional
      :return: A new resource with the updated URL.
      :rtype: Resource



   .. py:method:: as_raw() -> Resource

      Make the HTTP calls return both the raw response object and the decoded body.



   .. py:method:: get(**kwargs: Any) -> HttpResponse

      Do a GET request.

      :param kwargs: The query parameters to send with the request.
      :rtype: HttpResponse



   .. py:method:: options(**kwargs: Any) -> HttpResponse

      Do an OPTION request.

      :param kwargs: The query parameters to send with the request.
      :rtype: HttpResponse



   .. py:method:: head(**kwargs: Any) -> HttpResponse

      Do a HEAD request.

      :param kwargs: The query parameters to send with the request.
      :rtype: HttpResponse



   .. py:method:: post(data: dict | None = None, files: dict | None = None, **kwargs: Any) -> HttpResponse

      Do a POST request.

      :param data: The data to send with the request.
      :type data: dict, optional
      :param files: The files to send with the request. Supersedes :param:data.
          See `requests.post` for more information.
      :type files: dict, optional
      :param kwargs: The query parameters to send with the request.
      :rtype: HttpResponse



   .. py:method:: patch(data: dict | None = None, files: dict | None = None, **kwargs: Any) -> HttpResponse

      Do a PATCH request.
      Parameters are the same as :func:`post`.

      :rtype: HttpResponse



   .. py:method:: put(data: dict | None = None, files: dict | None = None, **kwargs: Any) -> HttpResponse

      Do a PUT request.
      Parameters are the same as :func:`post`.

      :rtype: HttpResponse



   .. py:method:: delete(data: dict | None = None, files: dict | None = None, **kwargs: Any) -> bool | tuple[requests.Response, bool]

      Do a DELETE request.
      Parameters are the same as :func:`post`.

      *Note*: some APIs such as the Keycloak Admin REST Api do not follow the HTTP spec and expect
      a body in the request (e.g.
      ``DELETE /admin/realms/{realm}/users/{user-id}/role-mappings/clients/{client-id}``).


      :return: True if the request was successful, False for 3xx status codes.
      :rtype: bool



   .. py:method:: url() -> str

      Get the URL that will be used for the next HTTP call.



.. py:class:: API(base_url: str, auth: requests.auth.AuthBase | None = None, append_slash: bool = True, session: requests.Session | None = None, serializers: list[mantelo.internal.serializers.BaseSerializer] | None = None, raw: bool = False)

   Bases: :py:obj:`Resource`


   The main entry point for making HTTP calls to a specific API.

   Highly inspired by the awesome `slumber <https://slumber.readthedocs.io/en/stable/>`_ library,
   this class defines default parameters for all the requests to an API, such as the base URL, the
   serializers to use, and the session to use for all requests. Once you have an API object, you
   can start making calls using, e.g. :python:`api.users.get()`.

   Do NOT use it directly, see :class:`KeycloakAdmin` instead.

   :param base_url: The base URL for the API.
   :type base_url: string
   :param auth: The authentication object to use for all requests.
   :type auth: requests.auth.AuthBase, optional
   :param append_slash: Whether to append a slash to the URL before making the request.
   :type append_slash: bool, optional
   :param session: The session to use for all request (API and authentication).
   :type session: requests.Session, optional
   :param serializers: The serializers to use for encoding and decoding the requests and responses.
       The first serializer in the list is used for encoding the request's data.
       Supports JSON by default.
   :type serializers: list[BaseSerializer], optional
   :param raw: Whether to return the raw response object along with the decoded body.
   :type raw: bool, optional


