about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/azure/core/rest
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/azure/core/rest')
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/__init__.py36
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_aiohttp.py228
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py423
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl.py475
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl_async.py155
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_requests_asyncio.py47
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_requests_basic.py104
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_requests_trio.py42
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_rest_py3.py418
9 files changed, 1928 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/__init__.py b/.venv/lib/python3.12/site-packages/azure/core/rest/__init__.py
new file mode 100644
index 00000000..078efaaa
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/__init__.py
@@ -0,0 +1,36 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+from ._rest_py3 import (
+    HttpRequest,
+    HttpResponse,
+    AsyncHttpResponse,
+)
+
+__all__ = [
+    "HttpRequest",
+    "HttpResponse",
+    "AsyncHttpResponse",
+]
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_aiohttp.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_aiohttp.py
new file mode 100644
index 00000000..64833e31
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_aiohttp.py
@@ -0,0 +1,228 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+import collections.abc
+import asyncio
+from itertools import groupby
+from typing import Iterator, cast
+from multidict import CIMultiDict
+from ._http_response_impl_async import (
+    AsyncHttpResponseImpl,
+    AsyncHttpResponseBackcompatMixin,
+)
+from ..pipeline.transport._aiohttp import AioHttpStreamDownloadGenerator
+from ..utils._pipeline_transport_rest_shared import _pad_attr_name, _aiohttp_body_helper
+from ..exceptions import ResponseNotReadError
+
+
+class _ItemsView(collections.abc.ItemsView):
+    def __init__(self, ref):
+        super().__init__(ref)
+        self._ref = ref
+
+    def __iter__(self):
+        for key, groups in groupby(self._ref.__iter__(), lambda x: x[0]):
+            yield tuple([key, ", ".join(group[1] for group in groups)])
+
+    def __contains__(self, item):
+        if not (isinstance(item, (list, tuple)) and len(item) == 2):
+            return False
+        for k, v in self.__iter__():
+            if item[0].lower() == k.lower() and item[1] == v:
+                return True
+        return False
+
+    def __repr__(self):
+        return f"dict_items({list(self.__iter__())})"
+
+
+class _KeysView(collections.abc.KeysView):
+    def __init__(self, items):
+        super().__init__(items)
+        self._items = items
+
+    def __iter__(self) -> Iterator[str]:
+        for key, _ in self._items:
+            yield key
+
+    def __contains__(self, key):
+        try:
+            for k in self.__iter__():
+                if cast(str, key).lower() == k.lower():
+                    return True
+        except AttributeError:  # Catch "lower()" if key not a string
+            pass
+        return False
+
+    def __repr__(self) -> str:
+        return f"dict_keys({list(self.__iter__())})"
+
+
+class _ValuesView(collections.abc.ValuesView):
+    def __init__(self, items):
+        super().__init__(items)
+        self._items = items
+
+    def __iter__(self):
+        for _, value in self._items:
+            yield value
+
+    def __contains__(self, value):
+        for v in self.__iter__():
+            if value == v:
+                return True
+        return False
+
+    def __repr__(self):
+        return f"dict_values({list(self.__iter__())})"
+
+
+class _CIMultiDict(CIMultiDict):
+    """Dictionary with the support for duplicate case-insensitive keys."""
+
+    def __iter__(self):
+        return iter(self.keys())
+
+    def keys(self):
+        """Return a new view of the dictionary's keys.
+
+        :return: A new view of the dictionary's keys
+        :rtype: ~collections.abc.KeysView
+        """
+        return _KeysView(self.items())
+
+    def items(self):
+        """Return a new view of the dictionary's items.
+
+        :return: A new view of the dictionary's items
+        :rtype: ~collections.abc.ItemsView
+        """
+        return _ItemsView(super().items())
+
+    def values(self):
+        """Return a new view of the dictionary's values.
+
+        :return: A new view of the dictionary's values
+        :rtype: ~collections.abc.ValuesView
+        """
+        return _ValuesView(self.items())
+
+    def __getitem__(self, key: str) -> str:
+        return ", ".join(self.getall(key, []))
+
+    def get(self, key, default=None):
+        values = self.getall(key, None)
+        if values:
+            values = ", ".join(values)
+        return values or default
+
+
+class _RestAioHttpTransportResponseBackcompatMixin(AsyncHttpResponseBackcompatMixin):
+    """Backcompat mixin for aiohttp responses.
+
+    Need to add it's own mixin because it has function load_body, which other
+    transport responses don't have, and also because we need to synchronously
+    decompress the body if users call .body()
+    """
+
+    def body(self) -> bytes:
+        """Return the whole body as bytes in memory.
+
+        Have to modify the default behavior here. In AioHttp, we do decompression
+        when accessing the body method. The behavior here is the same as if the
+        caller did an async read of the response first. But for backcompat reasons,
+        we need to support this decompression within the synchronous body method.
+
+        :return: The response's bytes
+        :rtype: bytes
+        """
+        return _aiohttp_body_helper(self)
+
+    async def _load_body(self) -> None:
+        """Load in memory the body, so it could be accessible from sync methods."""
+        self._content = await self.read()  # type: ignore
+
+    def __getattr__(self, attr):
+        backcompat_attrs = ["load_body"]
+        attr = _pad_attr_name(attr, backcompat_attrs)
+        return super().__getattr__(attr)
+
+
+class RestAioHttpTransportResponse(AsyncHttpResponseImpl, _RestAioHttpTransportResponseBackcompatMixin):
+    def __init__(self, *, internal_response, decompress: bool = True, **kwargs):
+        headers = _CIMultiDict(internal_response.headers)
+        super().__init__(
+            internal_response=internal_response,
+            status_code=internal_response.status,
+            headers=headers,
+            content_type=headers.get("content-type"),
+            reason=internal_response.reason,
+            stream_download_generator=AioHttpStreamDownloadGenerator,
+            content=None,
+            **kwargs,
+        )
+        self._decompress = decompress
+        self._decompressed_content = False
+
+    def __getstate__(self):
+        state = self.__dict__.copy()
+        # Remove the unpicklable entries.
+        state["_internal_response"] = None  # aiohttp response are not pickable (see headers comments)
+        state["headers"] = CIMultiDict(self.headers)  # MultiDictProxy is not pickable
+        return state
+
+    @property
+    def content(self) -> bytes:
+        """Return the response's content in bytes.
+
+        :return: The response's content in bytes
+        :rtype: bytes
+        """
+        if self._content is None:
+            raise ResponseNotReadError(self)
+        return _aiohttp_body_helper(self)
+
+    async def read(self) -> bytes:
+        """Read the response's bytes into memory.
+
+        :return: The response's bytes
+        :rtype: bytes
+        """
+        if not self._content:
+            self._stream_download_check()
+            self._content = await self._internal_response.read()
+        await self._set_read_checks()
+        return _aiohttp_body_helper(self)
+
+    async def close(self) -> None:
+        """Close the response.
+
+        :return: None
+        :rtype: None
+        """
+        if not self.is_closed:
+            self._is_closed = True
+            self._internal_response.close()
+            await asyncio.sleep(0)
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py
new file mode 100644
index 00000000..3ef5201d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py
@@ -0,0 +1,423 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+from __future__ import annotations
+import copy
+import codecs
+import email.message
+from json import dumps
+from typing import (
+    Optional,
+    Union,
+    Mapping,
+    Sequence,
+    Tuple,
+    IO,
+    Any,
+    Iterable,
+    MutableMapping,
+    AsyncIterable,
+    cast,
+    Dict,
+    TYPE_CHECKING,
+)
+import xml.etree.ElementTree as ET
+from urllib.parse import urlparse
+from azure.core.serialization import AzureJSONEncoder
+from ..utils._pipeline_transport_rest_shared import (
+    _format_parameters_helper,
+    _pad_attr_name,
+    _prepare_multipart_body_helper,
+    _serialize_request,
+    _format_data_helper,
+    get_file_items,
+)
+
+if TYPE_CHECKING:
+    # This avoid a circular import
+    from ._rest_py3 import HttpRequest
+
+################################### TYPES SECTION #########################
+
+binary_type = str
+PrimitiveData = Optional[Union[str, int, float, bool]]
+
+ParamsType = Mapping[str, Union[PrimitiveData, Sequence[PrimitiveData]]]
+
+FileContent = Union[str, bytes, IO[str], IO[bytes]]
+
+FileType = Union[
+    # file (or bytes)
+    FileContent,
+    # (filename, file (or bytes))
+    Tuple[Optional[str], FileContent],
+    # (filename, file (or bytes), content_type)
+    Tuple[Optional[str], FileContent, Optional[str]],
+]
+
+FilesType = Union[Mapping[str, FileType], Sequence[Tuple[str, FileType]]]
+
+ContentTypeBase = Union[str, bytes, Iterable[bytes]]
+ContentType = Union[str, bytes, Iterable[bytes], AsyncIterable[bytes]]
+
+DataType = Optional[Union[bytes, Dict[str, Union[str, int]]]]
+
+########################### HELPER SECTION #################################
+
+
+def _verify_data_object(name, value):
+    if not isinstance(name, str):
+        raise TypeError("Invalid type for data name. Expected str, got {}: {}".format(type(name), name))
+    if value is not None and not isinstance(value, (str, bytes, int, float)):
+        raise TypeError("Invalid type for data value. Expected primitive type, got {}: {}".format(type(name), name))
+
+
+def set_urlencoded_body(data, has_files):
+    body = {}
+    default_headers = {}
+    for f, d in data.items():
+        if not d:
+            continue
+        if isinstance(d, list):
+            for item in d:
+                _verify_data_object(f, item)
+        else:
+            _verify_data_object(f, d)
+        body[f] = d
+    if not has_files:
+        # little hacky, but for files we don't send a content type with
+        # boundary so requests / aiohttp etc deal with it
+        default_headers["Content-Type"] = "application/x-www-form-urlencoded"
+    return default_headers, body
+
+
+def set_multipart_body(files: FilesType):
+    formatted_files = [(f, _format_data_helper(d)) for f, d in get_file_items(files) if d is not None]
+    return {}, dict(formatted_files) if isinstance(files, Mapping) else formatted_files
+
+
+def set_xml_body(content):
+    headers = {}
+    bytes_content = ET.tostring(content, encoding="utf8")
+    body = bytes_content.replace(b"encoding='utf8'", b"encoding='utf-8'")
+    if body:
+        headers["Content-Length"] = str(len(body))
+    return headers, body
+
+
+def set_content_body(
+    content: Any,
+) -> Tuple[MutableMapping[str, str], Optional[ContentTypeBase]]:
+    headers: MutableMapping[str, str] = {}
+
+    if isinstance(content, ET.Element):
+        # XML body
+        return set_xml_body(content)
+    if isinstance(content, (str, bytes)):
+        headers = {}
+        body = content
+        if isinstance(content, str):
+            headers["Content-Type"] = "text/plain"
+        if body:
+            headers["Content-Length"] = str(len(body))
+        return headers, body
+    if any(hasattr(content, attr) for attr in ["read", "__iter__", "__aiter__"]):
+        return headers, content
+    raise TypeError(
+        "Unexpected type for 'content': '{}'. ".format(type(content))
+        + "We expect 'content' to either be str, bytes, a open file-like object or an iterable/asynciterable."
+    )
+
+
+def set_json_body(json: Any) -> Tuple[Dict[str, str], Any]:
+    headers = {"Content-Type": "application/json"}
+    if hasattr(json, "read"):
+        content_headers, body = set_content_body(json)
+        headers.update(content_headers)
+    else:
+        body = dumps(json, cls=AzureJSONEncoder)
+        headers.update({"Content-Length": str(len(body))})
+    return headers, body
+
+
+def lookup_encoding(encoding: str) -> bool:
+    # including check for whether encoding is known taken from httpx
+    try:
+        codecs.lookup(encoding)
+        return True
+    except LookupError:
+        return False
+
+
+def get_charset_encoding(response) -> Optional[str]:
+    content_type = response.headers.get("Content-Type")
+
+    if not content_type:
+        return None
+    # https://peps.python.org/pep-0594/#cgi
+    m = email.message.Message()
+    m["content-type"] = content_type
+    encoding = cast(str, m.get_param("charset"))  # -> utf-8
+    if encoding is None or not lookup_encoding(encoding):
+        return None
+    return encoding
+
+
+def decode_to_text(encoding: Optional[str], content: bytes) -> str:
+    if not content:
+        return ""
+    if encoding == "utf-8":
+        encoding = "utf-8-sig"
+    if encoding:
+        return content.decode(encoding)
+    return codecs.getincrementaldecoder("utf-8-sig")(errors="replace").decode(content)
+
+
+class HttpRequestBackcompatMixin:
+    def __getattr__(self, attr: str) -> Any:
+        backcompat_attrs = [
+            "files",
+            "data",
+            "multipart_mixed_info",
+            "query",
+            "body",
+            "format_parameters",
+            "set_streamed_data_body",
+            "set_text_body",
+            "set_xml_body",
+            "set_json_body",
+            "set_formdata_body",
+            "set_bytes_body",
+            "set_multipart_mixed",
+            "prepare_multipart_body",
+            "serialize",
+        ]
+        attr = _pad_attr_name(attr, backcompat_attrs)
+        return self.__getattribute__(attr)
+
+    def __setattr__(self, attr: str, value: Any) -> None:
+        backcompat_attrs = [
+            "multipart_mixed_info",
+            "files",
+            "data",
+            "body",
+        ]
+        attr = _pad_attr_name(attr, backcompat_attrs)
+        super(HttpRequestBackcompatMixin, self).__setattr__(attr, value)
+
+    @property
+    def _multipart_mixed_info(
+        self,
+    ) -> Optional[Tuple[Sequence[Any], Sequence[Any], str, Dict[str, Any]]]:
+        """DEPRECATED: Information used to make multipart mixed requests.
+        This is deprecated and will be removed in a later release.
+
+        :rtype: tuple
+        :return: (requests, policies, boundary, kwargs)
+        """
+        try:
+            return self._multipart_mixed_info_val
+        except AttributeError:
+            return None
+
+    @_multipart_mixed_info.setter
+    def _multipart_mixed_info(self, val: Optional[Tuple[Sequence[Any], Sequence[Any], str, Dict[str, Any]]]):
+        """DEPRECATED: Set information to make multipart mixed requests.
+        This is deprecated and will be removed in a later release.
+
+        :param tuple val: (requests, policies, boundary, kwargs)
+        """
+        self._multipart_mixed_info_val = val
+
+    @property
+    def _query(self) -> Dict[str, Any]:
+        """DEPRECATED: Query parameters passed in by user
+        This is deprecated and will be removed in a later release.
+
+        :rtype: dict
+        :return: Query parameters
+        """
+        query = urlparse(self.url).query
+        if query:
+            return {p[0]: p[-1] for p in [p.partition("=") for p in query.split("&")]}
+        return {}
+
+    @property
+    def _body(self) -> DataType:
+        """DEPRECATED: Body of the request. You should use the `content` property instead
+        This is deprecated and will be removed in a later release.
+
+        :rtype: bytes
+        :return: Body of the request
+        """
+        return self._data
+
+    @_body.setter
+    def _body(self, val: DataType) -> None:
+        """DEPRECATED: Set the body of the request
+        This is deprecated and will be removed in a later release.
+
+        :param bytes val: Body of the request
+        """
+        self._data = val
+
+    def _format_parameters(self, params: MutableMapping[str, str]) -> None:
+        """DEPRECATED: Format the query parameters
+        This is deprecated and will be removed in a later release.
+        You should pass the query parameters through the kwarg `params`
+        instead.
+
+        :param dict params: Query parameters
+        """
+        _format_parameters_helper(self, params)
+
+    def _set_streamed_data_body(self, data):
+        """DEPRECATED: Set the streamed request body.
+        This is deprecated and will be removed in a later release.
+        You should pass your stream content through the `content` kwarg instead
+
+        :param data: Streamed data
+        :type data: bytes or iterable
+        """
+        if not isinstance(data, binary_type) and not any(
+            hasattr(data, attr) for attr in ["read", "__iter__", "__aiter__"]
+        ):
+            raise TypeError("A streamable data source must be an open file-like object or iterable.")
+        headers = self._set_body(content=data)
+        self._files = None
+        self.headers.update(headers)
+
+    def _set_text_body(self, data):
+        """DEPRECATED: Set the text body
+        This is deprecated and will be removed in a later release.
+        You should pass your text content through the `content` kwarg instead
+
+        :param str data: Text data
+        """
+        headers = self._set_body(content=data)
+        self.headers.update(headers)
+        self._files = None
+
+    def _set_xml_body(self, data):
+        """DEPRECATED: Set the xml body.
+        This is deprecated and will be removed in a later release.
+        You should pass your xml content through the `content` kwarg instead
+
+        :param data: XML data
+        :type data: xml.etree.ElementTree.Element
+        """
+        headers = self._set_body(content=data)
+        self.headers.update(headers)
+        self._files = None
+
+    def _set_json_body(self, data):
+        """DEPRECATED: Set the json request body.
+        This is deprecated and will be removed in a later release.
+        You should pass your json content through the `json` kwarg instead
+
+        :param data: JSON data
+        :type data: dict
+        """
+        headers = self._set_body(json=data)
+        self.headers.update(headers)
+        self._files = None
+
+    def _set_formdata_body(self, data=None):
+        """DEPRECATED: Set the formrequest body.
+        This is deprecated and will be removed in a later release.
+        You should pass your stream content through the `files` kwarg instead
+
+        :param data: Form data
+        :type data: dict
+        """
+        if data is None:
+            data = {}
+        content_type = self.headers.pop("Content-Type", None) if self.headers else None
+
+        if content_type and content_type.lower() == "application/x-www-form-urlencoded":
+            headers = self._set_body(data=data)
+            self._files = None
+        else:  # Assume "multipart/form-data"
+            headers = self._set_body(files=data)
+            self._data = None
+        self.headers.update(headers)
+
+    def _set_bytes_body(self, data):
+        """DEPRECATED: Set the bytes request body.
+        This is deprecated and will be removed in a later release.
+        You should pass your bytes content through the `content` kwarg instead
+
+        :param bytes data: Bytes data
+        """
+        headers = self._set_body(content=data)
+        # we don't want default Content-Type
+        # in 2.7, byte strings are still strings, so they get set with text/plain content type
+
+        headers.pop("Content-Type", None)
+        self.headers.update(headers)
+        self._files = None
+
+    def _set_multipart_mixed(self, *requests: HttpRequest, **kwargs: Any) -> None:
+        """DEPRECATED: Set the multipart mixed info.
+        This is deprecated and will be removed in a later release.
+
+        :param requests: Requests to be sent in the multipart request
+        :type requests: list[HttpRequest]
+        """
+        self.multipart_mixed_info: Tuple[Sequence[HttpRequest], Sequence[Any], str, Dict[str, Any]] = (
+            requests,
+            kwargs.pop("policies", []),
+            kwargs.pop("boundary", None),
+            kwargs,
+        )
+
+    def _prepare_multipart_body(self, content_index=0):
+        """DEPRECATED: Prepare your request body for multipart requests.
+        This is deprecated and will be removed in a later release.
+
+        :param int content_index: The index of the request to be sent in the multipart request
+        :returns: The updated index after all parts in this request have been added.
+        :rtype: int
+        """
+        return _prepare_multipart_body_helper(self, content_index)
+
+    def _serialize(self):
+        """DEPRECATED: Serialize this request using application/http spec.
+        This is deprecated and will be removed in a later release.
+
+        :rtype: bytes
+        :return: The serialized request
+        """
+        return _serialize_request(self)
+
+    def _add_backcompat_properties(self, request, memo):
+        """While deepcopying, we also need to add the private backcompat attrs.
+
+        :param HttpRequest request: The request to copy from
+        :param dict memo: The memo dict used by deepcopy
+        """
+        request._multipart_mixed_info = copy.deepcopy(  # pylint: disable=protected-access
+            self._multipart_mixed_info, memo
+        )
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl.py
new file mode 100644
index 00000000..4357f1de
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl.py
@@ -0,0 +1,475 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+from json import loads
+from typing import Any, Optional, Iterator, MutableMapping, Callable
+from http.client import HTTPResponse as _HTTPResponse
+from ._helpers import (
+    get_charset_encoding,
+    decode_to_text,
+)
+from ..exceptions import (
+    HttpResponseError,
+    ResponseNotReadError,
+    StreamConsumedError,
+    StreamClosedError,
+)
+from ._rest_py3 import (
+    _HttpResponseBase,
+    HttpResponse as _HttpResponse,
+    HttpRequest as _HttpRequest,
+)
+from ..utils._utils import case_insensitive_dict
+from ..utils._pipeline_transport_rest_shared import (
+    _pad_attr_name,
+    BytesIOSocket,
+    _decode_parts_helper,
+    _get_raw_parts_helper,
+    _parts_helper,
+)
+
+
+class _HttpResponseBackcompatMixinBase:
+    """Base Backcompat mixin for responses.
+
+    This mixin is used by both sync and async HttpResponse
+    backcompat mixins.
+    """
+
+    def __getattr__(self, attr):
+        backcompat_attrs = [
+            "body",
+            "internal_response",
+            "block_size",
+            "stream_download",
+        ]
+        attr = _pad_attr_name(attr, backcompat_attrs)
+        return self.__getattribute__(attr)
+
+    def __setattr__(self, attr, value):
+        backcompat_attrs = [
+            "block_size",
+            "internal_response",
+            "request",
+            "status_code",
+            "headers",
+            "reason",
+            "content_type",
+            "stream_download",
+        ]
+        attr = _pad_attr_name(attr, backcompat_attrs)
+        super(_HttpResponseBackcompatMixinBase, self).__setattr__(attr, value)
+
+    def _body(self):
+        """DEPRECATED: Get the response body.
+        This is deprecated and will be removed in a later release.
+        You should get it through the `content` property instead
+
+        :return: The response body.
+        :rtype: bytes
+        """
+        self.read()
+        return self.content
+
+    def _decode_parts(self, message, http_response_type, requests):
+        """Helper for _decode_parts.
+
+        Rebuild an HTTP response from pure string.
+
+        :param message: The body as an email.Message type
+        :type message: ~email.message.Message
+        :param http_response_type: The type of response to build
+        :type http_response_type: type
+        :param requests: A list of requests to process
+        :type requests: list[~azure.core.rest.HttpRequest]
+        :return: A list of responses
+        :rtype: list[~azure.core.rest.HttpResponse]
+        """
+
+        def _deserialize_response(http_response_as_bytes, http_request, http_response_type):
+            local_socket = BytesIOSocket(http_response_as_bytes)
+            response = _HTTPResponse(local_socket, method=http_request.method)
+            response.begin()
+            return http_response_type(request=http_request, internal_response=response)
+
+        return _decode_parts_helper(
+            self,
+            message,
+            http_response_type or RestHttpClientTransportResponse,
+            requests,
+            _deserialize_response,
+        )
+
+    def _get_raw_parts(self, http_response_type=None):
+        """Helper for get_raw_parts
+
+        Assuming this body is multipart, return the iterator or parts.
+
+        If parts are application/http use http_response_type or HttpClientTransportResponse
+        as envelope.
+
+        :param http_response_type: The type of response to build
+        :type http_response_type: type
+        :return: An iterator of responses
+        :rtype: Iterator[~azure.core.rest.HttpResponse]
+        """
+        return _get_raw_parts_helper(self, http_response_type or RestHttpClientTransportResponse)
+
+    def _stream_download(self, pipeline, **kwargs):
+        """DEPRECATED: Generator for streaming request body data.
+        This is deprecated and will be removed in a later release.
+        You should use `iter_bytes` or `iter_raw` instead.
+
+        :param pipeline: The pipeline object
+        :type pipeline: ~azure.core.pipeline.Pipeline
+        :return: An iterator for streaming request body data.
+        :rtype: iterator[bytes]
+        """
+        return self._stream_download_generator(pipeline, self, **kwargs)
+
+
+class HttpResponseBackcompatMixin(_HttpResponseBackcompatMixinBase):
+    """Backcompat mixin for sync HttpResponses"""
+
+    def __getattr__(self, attr):
+        backcompat_attrs = ["parts"]
+        attr = _pad_attr_name(attr, backcompat_attrs)
+        return super(HttpResponseBackcompatMixin, self).__getattr__(attr)
+
+    def parts(self):
+        """DEPRECATED: Assuming the content-type is multipart/mixed, will return the parts as an async iterator.
+        This is deprecated and will be removed in a later release.
+
+        :rtype: Iterator
+        :return: The parts of the response
+        :raises ValueError: If the content is not multipart/mixed
+        """
+        return _parts_helper(self)
+
+
+class _HttpResponseBaseImpl(
+    _HttpResponseBase, _HttpResponseBackcompatMixinBase
+):  # pylint: disable=too-many-instance-attributes
+    """Base Implementation class for azure.core.rest.HttpRespone and azure.core.rest.AsyncHttpResponse
+
+    Since the rest responses are abstract base classes, we need to implement them for each of our transport
+    responses. This is the base implementation class shared by HttpResponseImpl and AsyncHttpResponseImpl.
+    The transport responses will be built on top of HttpResponseImpl and AsyncHttpResponseImpl
+
+    :keyword request: The request that led to the response
+    :type request: ~azure.core.rest.HttpRequest
+    :keyword any internal_response: The response we get directly from the transport. For example, for our requests
+     transport, this will be a requests.Response.
+    :keyword optional[int] block_size: The block size we are using in our transport
+    :keyword int status_code: The status code of the response
+    :keyword str reason: The HTTP reason
+    :keyword str content_type: The content type of the response
+    :keyword MutableMapping[str, str] headers: The response headers
+    :keyword Callable stream_download_generator: The stream download generator that we use to stream the response.
+    """
+
+    def __init__(self, **kwargs) -> None:
+        super(_HttpResponseBaseImpl, self).__init__()
+        self._request = kwargs.pop("request")
+        self._internal_response = kwargs.pop("internal_response")
+        self._block_size: int = kwargs.pop("block_size", None) or 4096
+        self._status_code: int = kwargs.pop("status_code")
+        self._reason: str = kwargs.pop("reason")
+        self._content_type: str = kwargs.pop("content_type")
+        self._headers: MutableMapping[str, str] = kwargs.pop("headers")
+        self._stream_download_generator: Callable = kwargs.pop("stream_download_generator")
+        self._is_closed = False
+        self._is_stream_consumed = False
+        self._json = None  # this is filled in ContentDecodePolicy, when we deserialize
+        self._content: Optional[bytes] = None
+        self._text: Optional[str] = None
+
+    @property
+    def request(self) -> _HttpRequest:
+        """The request that resulted in this response.
+
+        :rtype: ~azure.core.rest.HttpRequest
+        :return: The request that resulted in this response.
+        """
+        return self._request
+
+    @property
+    def url(self) -> str:
+        """The URL that resulted in this response.
+
+        :rtype: str
+        :return: The URL that resulted in this response.
+        """
+        return self.request.url
+
+    @property
+    def is_closed(self) -> bool:
+        """Whether the network connection has been closed yet.
+
+        :rtype: bool
+        :return: Whether the network connection has been closed yet.
+        """
+        return self._is_closed
+
+    @property
+    def is_stream_consumed(self) -> bool:
+        """Whether the stream has been consumed.
+
+        :rtype: bool
+        :return: Whether the stream has been consumed.
+        """
+        return self._is_stream_consumed
+
+    @property
+    def status_code(self) -> int:
+        """The status code of this response.
+
+        :rtype: int
+        :return: The status code of this response.
+        """
+        return self._status_code
+
+    @property
+    def headers(self) -> MutableMapping[str, str]:
+        """The response headers.
+
+        :rtype: MutableMapping[str, str]
+        :return: The response headers.
+        """
+        return self._headers
+
+    @property
+    def content_type(self) -> Optional[str]:
+        """The content type of the response.
+
+        :rtype: optional[str]
+        :return: The content type of the response.
+        """
+        return self._content_type
+
+    @property
+    def reason(self) -> str:
+        """The reason phrase for this response.
+
+        :rtype: str
+        :return: The reason phrase for this response.
+        """
+        return self._reason
+
+    @property
+    def encoding(self) -> Optional[str]:
+        """Returns the response encoding.
+
+        :return: The response encoding. We either return the encoding set by the user,
+         or try extracting the encoding from the response's content type. If all fails,
+         we return `None`.
+        :rtype: optional[str]
+        """
+        try:
+            return self._encoding
+        except AttributeError:
+            self._encoding: Optional[str] = get_charset_encoding(self)
+            return self._encoding
+
+    @encoding.setter
+    def encoding(self, value: str) -> None:
+        """Sets the response encoding.
+
+        :param str value: Sets the response encoding.
+        """
+        self._encoding = value
+        self._text = None  # clear text cache
+        self._json = None  # clear json cache as well
+
+    def text(self, encoding: Optional[str] = None) -> str:
+        """Returns the response body as a string
+
+        :param optional[str] encoding: The encoding you want to decode the text with. Can
+         also be set independently through our encoding property
+        :return: The response's content decoded as a string.
+        :rtype: str
+        """
+        if encoding:
+            return decode_to_text(encoding, self.content)
+        if self._text:
+            return self._text
+        self._text = decode_to_text(self.encoding, self.content)
+        return self._text
+
+    def json(self) -> Any:
+        """Returns the whole body as a json object.
+
+        :return: The JSON deserialized response body
+        :rtype: any
+        :raises json.decoder.JSONDecodeError or ValueError (in python 2.7) if object is not JSON decodable:
+        """
+        # this will trigger errors if response is not read in
+        self.content  # pylint: disable=pointless-statement
+        if not self._json:
+            self._json = loads(self.text())
+        return self._json
+
+    def _stream_download_check(self):
+        if self.is_stream_consumed:
+            raise StreamConsumedError(self)
+        if self.is_closed:
+            raise StreamClosedError(self)
+
+        self._is_stream_consumed = True
+
+    def raise_for_status(self) -> None:
+        """Raises an HttpResponseError if the response has an error status code.
+
+        If response is good, does nothing.
+        """
+        if self.status_code >= 400:
+            raise HttpResponseError(response=self)
+
+    @property
+    def content(self) -> bytes:
+        """Return the response's content in bytes.
+
+        :return: The response's content in bytes.
+        :rtype: bytes
+        """
+        if self._content is None:
+            raise ResponseNotReadError(self)
+        return self._content
+
+    def __repr__(self) -> str:
+        content_type_str = ", Content-Type: {}".format(self.content_type) if self.content_type else ""
+        return "<HttpResponse: {} {}{}>".format(self.status_code, self.reason, content_type_str)
+
+
+class HttpResponseImpl(_HttpResponseBaseImpl, _HttpResponse, HttpResponseBackcompatMixin):
+    """HttpResponseImpl built on top of our HttpResponse protocol class.
+
+    Since ~azure.core.rest.HttpResponse is an abstract base class, we need to
+    implement HttpResponse for each of our transports. This is an implementation
+    that each of the sync transport responses can be built on.
+
+    :keyword request: The request that led to the response
+    :type request: ~azure.core.rest.HttpRequest
+    :keyword any internal_response: The response we get directly from the transport. For example, for our requests
+     transport, this will be a requests.Response.
+    :keyword optional[int] block_size: The block size we are using in our transport
+    :keyword int status_code: The status code of the response
+    :keyword str reason: The HTTP reason
+    :keyword str content_type: The content type of the response
+    :keyword MutableMapping[str, str] headers: The response headers
+    :keyword Callable stream_download_generator: The stream download generator that we use to stream the response.
+    """
+
+    def __enter__(self) -> "HttpResponseImpl":
+        return self
+
+    def close(self) -> None:
+        if not self.is_closed:
+            self._is_closed = True
+            self._internal_response.close()
+
+    def __exit__(self, *args) -> None:
+        self.close()
+
+    def _set_read_checks(self):
+        self._is_stream_consumed = True
+        self.close()
+
+    def read(self) -> bytes:
+        """Read the response's bytes.
+
+        :return: The response's bytes
+        :rtype: bytes
+        """
+        if self._content is None:
+            self._content = b"".join(self.iter_bytes())
+        self._set_read_checks()
+        return self.content
+
+    def iter_bytes(self, **kwargs) -> Iterator[bytes]:
+        """Iterates over the response's bytes. Will decompress in the process.
+
+        :return: An iterator of bytes from the response
+        :rtype: Iterator[str]
+        """
+        if self._content is not None:
+            chunk_size = self._block_size
+            for i in range(0, len(self.content), chunk_size):
+                yield self.content[i : i + chunk_size]
+        else:
+            self._stream_download_check()
+            yield from self._stream_download_generator(
+                response=self,
+                pipeline=None,
+                decompress=True,
+            )
+        self.close()
+
+    def iter_raw(self, **kwargs) -> Iterator[bytes]:
+        """Iterates over the response's bytes. Will not decompress in the process.
+
+        :return: An iterator of bytes from the response
+        :rtype: Iterator[str]
+        """
+        self._stream_download_check()
+        yield from self._stream_download_generator(response=self, pipeline=None, decompress=False)
+        self.close()
+
+
+class _RestHttpClientTransportResponseBackcompatBaseMixin(_HttpResponseBackcompatMixinBase):
+    def body(self):
+        if self._content is None:
+            self._content = self.internal_response.read()
+        return self.content
+
+
+class _RestHttpClientTransportResponseBase(_HttpResponseBaseImpl, _RestHttpClientTransportResponseBackcompatBaseMixin):
+    def __init__(self, **kwargs):
+        internal_response = kwargs.pop("internal_response")
+        headers = case_insensitive_dict(internal_response.getheaders())
+        super(_RestHttpClientTransportResponseBase, self).__init__(
+            internal_response=internal_response,
+            status_code=internal_response.status,
+            reason=internal_response.reason,
+            headers=headers,
+            content_type=headers.get("Content-Type"),
+            stream_download_generator=None,
+            **kwargs
+        )
+
+
+class RestHttpClientTransportResponse(_RestHttpClientTransportResponseBase, HttpResponseImpl):
+    """Create a Rest HTTPResponse from an http.client response."""
+
+    def iter_bytes(self, **kwargs):
+        raise TypeError("We do not support iter_bytes for this transport response")
+
+    def iter_raw(self, **kwargs):
+        raise TypeError("We do not support iter_raw for this transport response")
+
+    def read(self):
+        if self._content is None:
+            self._content = self._internal_response.read()
+        return self._content
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl_async.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl_async.py
new file mode 100644
index 00000000..e582a103
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_http_response_impl_async.py
@@ -0,0 +1,155 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+from typing import Any, AsyncIterator, Optional, Type
+from types import TracebackType
+from ._rest_py3 import AsyncHttpResponse as _AsyncHttpResponse
+from ._http_response_impl import (
+    _HttpResponseBaseImpl,
+    _HttpResponseBackcompatMixinBase,
+    _RestHttpClientTransportResponseBase,
+)
+from ..utils._pipeline_transport_rest_shared import _pad_attr_name
+from ..utils._pipeline_transport_rest_shared_async import _PartGenerator
+
+
+class AsyncHttpResponseBackcompatMixin(_HttpResponseBackcompatMixinBase):
+    """Backcompat mixin for async responses"""
+
+    def __getattr__(self, attr):
+        backcompat_attrs = ["parts"]
+        attr = _pad_attr_name(attr, backcompat_attrs)
+        return super().__getattr__(attr)
+
+    def parts(self):
+        """DEPRECATED: Assuming the content-type is multipart/mixed, will return the parts as an async iterator.
+        This is deprecated and will be removed in a later release.
+        :rtype: AsyncIterator
+        :return: The parts of the response
+        :raises ValueError: If the content is not multipart/mixed
+        """
+        if not self.content_type or not self.content_type.startswith("multipart/mixed"):
+            raise ValueError("You can't get parts if the response is not multipart/mixed")
+
+        return _PartGenerator(self, default_http_response_type=RestAsyncHttpClientTransportResponse)
+
+
+class AsyncHttpResponseImpl(_HttpResponseBaseImpl, _AsyncHttpResponse, AsyncHttpResponseBackcompatMixin):
+    """AsyncHttpResponseImpl built on top of our HttpResponse protocol class.
+
+    Since ~azure.core.rest.AsyncHttpResponse is an abstract base class, we need to
+    implement HttpResponse for each of our transports. This is an implementation
+    that each of the sync transport responses can be built on.
+
+    :keyword request: The request that led to the response
+    :type request: ~azure.core.rest.HttpRequest
+    :keyword any internal_response: The response we get directly from the transport. For example, for our requests
+     transport, this will be a requests.Response.
+    :keyword optional[int] block_size: The block size we are using in our transport
+    :keyword int status_code: The status code of the response
+    :keyword str reason: The HTTP reason
+    :keyword str content_type: The content type of the response
+    :keyword MutableMapping[str, str] headers: The response headers
+    :keyword Callable stream_download_generator: The stream download generator that we use to stream the response.
+    """
+
+    async def _set_read_checks(self):
+        self._is_stream_consumed = True
+        await self.close()
+
+    async def read(self) -> bytes:
+        """Read the response's bytes into memory.
+
+        :return: The response's bytes
+        :rtype: bytes
+        """
+        if self._content is None:
+            parts = []
+            async for part in self.iter_bytes():
+                parts.append(part)
+            self._content = b"".join(parts)
+        await self._set_read_checks()
+        return self._content
+
+    async def iter_raw(self, **kwargs: Any) -> AsyncIterator[bytes]:
+        """Asynchronously iterates over the response's bytes. Will not decompress in the process
+        :return: An async iterator of bytes from the response
+        :rtype: AsyncIterator[bytes]
+        """
+        self._stream_download_check()
+        async for part in self._stream_download_generator(response=self, pipeline=None, decompress=False):
+            yield part
+        await self.close()
+
+    async def iter_bytes(self, **kwargs: Any) -> AsyncIterator[bytes]:
+        """Asynchronously iterates over the response's bytes. Will decompress in the process
+        :return: An async iterator of bytes from the response
+        :rtype: AsyncIterator[bytes]
+        """
+        if self._content is not None:
+            for i in range(0, len(self.content), self._block_size):
+                yield self.content[i : i + self._block_size]
+        else:
+            self._stream_download_check()
+            async for part in self._stream_download_generator(response=self, pipeline=None, decompress=True):
+                yield part
+            await self.close()
+
+    async def close(self) -> None:
+        """Close the response.
+
+        :return: None
+        :rtype: None
+        """
+        if not self.is_closed:
+            self._is_closed = True
+            await self._internal_response.close()
+
+    async def __aexit__(
+        self,
+        exc_type: Optional[Type[BaseException]] = None,
+        exc_value: Optional[BaseException] = None,
+        traceback: Optional[TracebackType] = None,
+    ) -> None:
+        await self.close()
+
+    def __repr__(self) -> str:
+        content_type_str = ", Content-Type: {}".format(self.content_type) if self.content_type else ""
+        return "<AsyncHttpResponse: {} {}{}>".format(self.status_code, self.reason, content_type_str)
+
+
+class RestAsyncHttpClientTransportResponse(_RestHttpClientTransportResponseBase, AsyncHttpResponseImpl):
+    """Create a Rest HTTPResponse from an http.client response."""
+
+    async def iter_bytes(self, **kwargs):
+        raise TypeError("We do not support iter_bytes for this transport response")
+
+    async def iter_raw(self, **kwargs):
+        raise TypeError("We do not support iter_raw for this transport response")
+
+    async def read(self):
+        if self._content is None:
+            self._content = self._internal_response.read()
+        return self._content
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_asyncio.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_asyncio.py
new file mode 100644
index 00000000..35e89667
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_asyncio.py
@@ -0,0 +1,47 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+import asyncio
+from ._http_response_impl_async import AsyncHttpResponseImpl
+from ._requests_basic import _RestRequestsTransportResponseBase
+from ..pipeline.transport._requests_asyncio import AsyncioStreamDownloadGenerator
+
+
+class RestAsyncioRequestsTransportResponse(AsyncHttpResponseImpl, _RestRequestsTransportResponseBase):  # type: ignore
+    """Asynchronous streaming of data from the response."""
+
+    def __init__(self, **kwargs):
+        super().__init__(stream_download_generator=AsyncioStreamDownloadGenerator, **kwargs)
+
+    async def close(self) -> None:
+        """Close the response.
+
+        :return: None
+        :rtype: None
+        """
+        if not self.is_closed:
+            self._is_closed = True
+            self._internal_response.close()
+            await asyncio.sleep(0)
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_basic.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_basic.py
new file mode 100644
index 00000000..d5ee4504
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_basic.py
@@ -0,0 +1,104 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+import collections.abc as collections
+from requests.structures import (  # pylint: disable=networking-import-outside-azure-core-transport
+    CaseInsensitiveDict,
+)
+
+from ._http_response_impl import (
+    _HttpResponseBaseImpl,
+    HttpResponseImpl,
+    _HttpResponseBackcompatMixinBase,
+)
+from ..pipeline.transport._requests_basic import StreamDownloadGenerator
+
+
+class _ItemsView(collections.ItemsView):
+    def __contains__(self, item):
+        if not (isinstance(item, (list, tuple)) and len(item) == 2):
+            return False  # requests raises here, we just return False
+        for k, v in self.__iter__():
+            if item[0].lower() == k.lower() and item[1] == v:
+                return True
+        return False
+
+    def __repr__(self):
+        return "ItemsView({})".format(dict(self.__iter__()))
+
+
+class _CaseInsensitiveDict(CaseInsensitiveDict):
+    """Overriding default requests dict so we can unify
+    to not raise if users pass in incorrect items to contains.
+    Instead, we return False
+    """
+
+    def items(self):
+        """Return a new view of the dictionary's items.
+
+        :rtype: ~collections.abc.ItemsView[str, str]
+        :returns: a view object that displays a list of (key, value) tuple pairs
+        """
+        return _ItemsView(self)
+
+
+class _RestRequestsTransportResponseBaseMixin(_HttpResponseBackcompatMixinBase):
+    """Backcompat mixin for the sync and async requests responses
+
+    Overriding the default mixin behavior here because we need to synchronously
+    read the response's content for the async requests responses
+    """
+
+    def _body(self):
+        # Since requests is not an async library, for backcompat, users should
+        # be able to access the body directly without loading it first (like we have to do
+        # in aiohttp). So here, we set self._content to self._internal_response.content,
+        # which is similar to read, without the async call.
+        if self._content is None:
+            self._content = self._internal_response.content
+        return self._content
+
+
+class _RestRequestsTransportResponseBase(_HttpResponseBaseImpl, _RestRequestsTransportResponseBaseMixin):
+    def __init__(self, **kwargs):
+        internal_response = kwargs.pop("internal_response")
+        content = None
+        if internal_response._content_consumed:
+            content = internal_response.content
+        headers = _CaseInsensitiveDict(internal_response.headers)
+        super(_RestRequestsTransportResponseBase, self).__init__(
+            internal_response=internal_response,
+            status_code=internal_response.status_code,
+            headers=headers,
+            reason=internal_response.reason,
+            content_type=headers.get("content-type"),
+            content=content,
+            **kwargs
+        )
+
+
+class RestRequestsTransportResponse(HttpResponseImpl, _RestRequestsTransportResponseBase):
+    def __init__(self, **kwargs):
+        super(RestRequestsTransportResponse, self).__init__(stream_download_generator=StreamDownloadGenerator, **kwargs)
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_trio.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_trio.py
new file mode 100644
index 00000000..bad6e85b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_requests_trio.py
@@ -0,0 +1,42 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+import trio  # pylint: disable=networking-import-outside-azure-core-transport
+from ._http_response_impl_async import AsyncHttpResponseImpl
+from ._requests_basic import _RestRequestsTransportResponseBase
+from ..pipeline.transport._requests_trio import TrioStreamDownloadGenerator
+
+
+class RestTrioRequestsTransportResponse(AsyncHttpResponseImpl, _RestRequestsTransportResponseBase):  # type: ignore
+    """Asynchronous streaming of data from the response."""
+
+    def __init__(self, **kwargs):
+        super().__init__(stream_download_generator=TrioStreamDownloadGenerator, **kwargs)
+
+    async def close(self) -> None:
+        if not self.is_closed:
+            self._is_closed = True
+            self._internal_response.close()
+            await trio.sleep(0)
diff --git a/.venv/lib/python3.12/site-packages/azure/core/rest/_rest_py3.py b/.venv/lib/python3.12/site-packages/azure/core/rest/_rest_py3.py
new file mode 100644
index 00000000..61ac041b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/core/rest/_rest_py3.py
@@ -0,0 +1,418 @@
+# --------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+#
+# The MIT License (MIT)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the ""Software""), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# --------------------------------------------------------------------------
+import abc
+import copy
+from typing import (
+    Any,
+    AsyncIterable,
+    AsyncIterator,
+    Iterable,
+    Iterator,
+    Optional,
+    Union,
+    MutableMapping,
+    Dict,
+    AsyncContextManager,
+)
+
+from ..utils._utils import case_insensitive_dict
+
+from ._helpers import (
+    ParamsType,
+    FilesType,
+    set_json_body,
+    set_multipart_body,
+    set_urlencoded_body,
+    _format_parameters_helper,
+    HttpRequestBackcompatMixin,
+    set_content_body,
+)
+
+ContentType = Union[str, bytes, Iterable[bytes], AsyncIterable[bytes]]
+
+################################## CLASSES ######################################
+
+
+class HttpRequest(HttpRequestBackcompatMixin):
+    """An HTTP request.
+
+    It should be passed to your client's `send_request` method.
+
+    >>> from azure.core.rest import HttpRequest
+    >>> request = HttpRequest('GET', 'http://www.example.com')
+    <HttpRequest [GET], url: 'http://www.example.com'>
+    >>> response = client.send_request(request)
+    <HttpResponse: 200 OK>
+
+    :param str method: HTTP method (GET, HEAD, etc.)
+    :param str url: The url for your request
+    :keyword mapping params: Query parameters to be mapped into your URL. Your input
+     should be a mapping of query name to query value(s).
+    :keyword mapping headers: HTTP headers you want in your request. Your input should
+     be a mapping of header name to header value.
+    :keyword any json: A JSON serializable object. We handle JSON-serialization for your
+     object, so use this for more complicated data structures than `data`.
+    :keyword content: Content you want in your request body. Think of it as the kwarg you should input
+     if your data doesn't fit into `json`, `data`, or `files`. Accepts a bytes type, or a generator
+     that yields bytes.
+    :paramtype content: str or bytes or iterable[bytes] or asynciterable[bytes]
+    :keyword dict data: Form data you want in your request body. Use for form-encoded data, i.e.
+     HTML forms.
+    :keyword mapping files: Files you want to in your request body. Use for uploading files with
+     multipart encoding. Your input should be a mapping of file name to file content.
+     Use the `data` kwarg in addition if you want to include non-file data files as part of your request.
+    :ivar str url: The URL this request is against.
+    :ivar str method: The method type of this request.
+    :ivar mapping headers: The HTTP headers you passed in to your request
+    :ivar any content: The content passed in for the request
+    """
+
+    def __init__(
+        self,
+        method: str,
+        url: str,
+        *,
+        params: Optional[ParamsType] = None,
+        headers: Optional[MutableMapping[str, str]] = None,
+        json: Any = None,
+        content: Optional[ContentType] = None,
+        data: Optional[Dict[str, Any]] = None,
+        files: Optional[FilesType] = None,
+        **kwargs: Any
+    ):
+        self.url = url
+        self.method = method
+
+        if params:
+            _format_parameters_helper(self, params)
+        self._files = None
+        self._data: Any = None
+
+        default_headers = self._set_body(
+            content=content,
+            data=data,
+            files=files,
+            json=json,
+        )
+        self.headers: MutableMapping[str, str] = case_insensitive_dict(default_headers)
+        self.headers.update(headers or {})
+
+        if kwargs:
+            raise TypeError(
+                "You have passed in kwargs '{}' that are not valid kwargs.".format("', '".join(list(kwargs.keys())))
+            )
+
+    def _set_body(
+        self,
+        content: Optional[ContentType] = None,
+        data: Optional[Dict[str, Any]] = None,
+        files: Optional[FilesType] = None,
+        json: Any = None,
+    ) -> MutableMapping[str, str]:
+        """Sets the body of the request, and returns the default headers.
+
+        :param content: Content you want in your request body.
+        :type content: str or bytes or iterable[bytes] or asynciterable[bytes]
+        :param dict data: Form data you want in your request body.
+        :param dict files: Files you want to in your request body.
+        :param any json: A JSON serializable object.
+        :return: The default headers for the request
+        :rtype: MutableMapping[str, str]
+        """
+        default_headers: MutableMapping[str, str] = {}
+        if data is not None and not isinstance(data, dict):
+            # should we warn?
+            content = data
+        if content is not None:
+            default_headers, self._data = set_content_body(content)
+            return default_headers
+        if json is not None:
+            default_headers, self._data = set_json_body(json)
+            return default_headers
+        if files:
+            default_headers, self._files = set_multipart_body(files)
+        if data:
+            default_headers, self._data = set_urlencoded_body(data, has_files=bool(files))
+        return default_headers
+
+    @property
+    def content(self) -> Any:
+        """Get's the request's content
+
+        :return: The request's content
+        :rtype: any
+        """
+        return self._data or self._files
+
+    def __repr__(self) -> str:
+        return "<HttpRequest [{}], url: '{}'>".format(self.method, self.url)
+
+    def __deepcopy__(self, memo: Optional[Dict[int, Any]] = None) -> "HttpRequest":
+        try:
+            request = HttpRequest(
+                method=self.method,
+                url=self.url,
+                headers=self.headers,
+            )
+            request._data = copy.deepcopy(self._data, memo)
+            request._files = copy.deepcopy(self._files, memo)
+            self._add_backcompat_properties(request, memo)
+            return request
+        except (ValueError, TypeError):
+            return copy.copy(self)
+
+
+class _HttpResponseBase(abc.ABC):
+    """Base abstract base class for HttpResponses."""
+
+    @property
+    @abc.abstractmethod
+    def request(self) -> HttpRequest:
+        """The request that resulted in this response.
+
+        :rtype: ~azure.core.rest.HttpRequest
+        :return: The request that resulted in this response.
+        """
+
+    @property
+    @abc.abstractmethod
+    def status_code(self) -> int:
+        """The status code of this response.
+
+        :rtype: int
+        :return: The status code of this response.
+        """
+
+    @property
+    @abc.abstractmethod
+    def headers(self) -> MutableMapping[str, str]:
+        """The response headers. Must be case-insensitive.
+
+        :rtype: MutableMapping[str, str]
+        :return: The response headers. Must be case-insensitive.
+        """
+
+    @property
+    @abc.abstractmethod
+    def reason(self) -> str:
+        """The reason phrase for this response.
+
+        :rtype: str
+        :return: The reason phrase for this response.
+        """
+
+    @property
+    @abc.abstractmethod
+    def content_type(self) -> Optional[str]:
+        """The content type of the response.
+
+        :rtype: str
+        :return: The content type of the response.
+        """
+
+    @property
+    @abc.abstractmethod
+    def is_closed(self) -> bool:
+        """Whether the network connection has been closed yet.
+
+        :rtype: bool
+        :return: Whether the network connection has been closed yet.
+        """
+
+    @property
+    @abc.abstractmethod
+    def is_stream_consumed(self) -> bool:
+        """Whether the stream has been consumed.
+
+        :rtype: bool
+        :return: Whether the stream has been consumed.
+        """
+
+    @property
+    @abc.abstractmethod
+    def encoding(self) -> Optional[str]:
+        """Returns the response encoding.
+
+        :return: The response encoding. We either return the encoding set by the user,
+         or try extracting the encoding from the response's content type. If all fails,
+         we return `None`.
+        :rtype: optional[str]
+        """
+
+    @encoding.setter
+    def encoding(self, value: Optional[str]) -> None:
+        """Sets the response encoding.
+
+        :param optional[str] value: The encoding to set
+        """
+
+    @property
+    @abc.abstractmethod
+    def url(self) -> str:
+        """The URL that resulted in this response.
+
+        :rtype: str
+        :return: The URL that resulted in this response.
+        """
+
+    @property
+    @abc.abstractmethod
+    def content(self) -> bytes:
+        """Return the response's content in bytes.
+
+        :rtype: bytes
+        :return: The response's content in bytes.
+        """
+
+    @abc.abstractmethod
+    def text(self, encoding: Optional[str] = None) -> str:
+        """Returns the response body as a string.
+
+        :param optional[str] encoding: The encoding you want to decode the text with. Can
+         also be set independently through our encoding property
+        :return: The response's content decoded as a string.
+        :rtype: str
+        """
+
+    @abc.abstractmethod
+    def json(self) -> Any:
+        """Returns the whole body as a json object.
+
+        :return: The JSON deserialized response body
+        :rtype: any
+        :raises json.decoder.JSONDecodeError or ValueError (in python 2.7) if object is not JSON decodable:
+        """
+
+    @abc.abstractmethod
+    def raise_for_status(self) -> None:
+        """Raises an HttpResponseError if the response has an error status code.
+
+        If response is good, does nothing.
+
+        :raises ~azure.core.HttpResponseError if the object has an error status code.:
+        """
+
+
+class HttpResponse(_HttpResponseBase):
+    """Abstract base class for HTTP responses.
+
+    Use this abstract base class to create your own transport responses.
+
+    Responses implementing this ABC are returned from your client's `send_request` method
+    if you pass in an :class:`~azure.core.rest.HttpRequest`
+
+    >>> from azure.core.rest import HttpRequest
+    >>> request = HttpRequest('GET', 'http://www.example.com')
+    <HttpRequest [GET], url: 'http://www.example.com'>
+    >>> response = client.send_request(request)
+    <HttpResponse: 200 OK>
+    """
+
+    @abc.abstractmethod
+    def __enter__(self) -> "HttpResponse": ...
+
+    @abc.abstractmethod
+    def __exit__(self, *args: Any) -> None: ...
+
+    @abc.abstractmethod
+    def close(self) -> None: ...
+
+    @abc.abstractmethod
+    def read(self) -> bytes:
+        """Read the response's bytes.
+
+        :return: The read in bytes
+        :rtype: bytes
+        """
+
+    @abc.abstractmethod
+    def iter_raw(self, **kwargs: Any) -> Iterator[bytes]:
+        """Iterates over the response's bytes. Will not decompress in the process.
+
+        :return: An iterator of bytes from the response
+        :rtype: Iterator[str]
+        """
+
+    @abc.abstractmethod
+    def iter_bytes(self, **kwargs: Any) -> Iterator[bytes]:
+        """Iterates over the response's bytes. Will decompress in the process.
+
+        :return: An iterator of bytes from the response
+        :rtype: Iterator[str]
+        """
+
+    def __repr__(self) -> str:
+        content_type_str = ", Content-Type: {}".format(self.content_type) if self.content_type else ""
+        return "<HttpResponse: {} {}{}>".format(self.status_code, self.reason, content_type_str)
+
+
+class AsyncHttpResponse(_HttpResponseBase, AsyncContextManager["AsyncHttpResponse"]):
+    """Abstract base class for Async HTTP responses.
+
+    Use this abstract base class to create your own transport responses.
+
+    Responses implementing this ABC are returned from your async client's `send_request`
+    method if you pass in an :class:`~azure.core.rest.HttpRequest`
+
+    >>> from azure.core.rest import HttpRequest
+    >>> request = HttpRequest('GET', 'http://www.example.com')
+    <HttpRequest [GET], url: 'http://www.example.com'>
+    >>> response = await client.send_request(request)
+    <AsyncHttpResponse: 200 OK>
+    """
+
+    @abc.abstractmethod
+    async def read(self) -> bytes:
+        """Read the response's bytes into memory.
+
+        :return: The response's bytes
+        :rtype: bytes
+        """
+
+    @abc.abstractmethod
+    async def iter_raw(self, **kwargs: Any) -> AsyncIterator[bytes]:
+        """Asynchronously iterates over the response's bytes. Will not decompress in the process.
+
+        :return: An async iterator of bytes from the response
+        :rtype: AsyncIterator[bytes]
+        """
+        raise NotImplementedError()
+        # getting around mypy behavior, see https://github.com/python/mypy/issues/10732
+        yield  # pylint: disable=unreachable
+
+    @abc.abstractmethod
+    async def iter_bytes(self, **kwargs: Any) -> AsyncIterator[bytes]:
+        """Asynchronously iterates over the response's bytes. Will decompress in the process.
+
+        :return: An async iterator of bytes from the response
+        :rtype: AsyncIterator[bytes]
+        """
+        raise NotImplementedError()
+        # getting around mypy behavior, see https://github.com/python/mypy/issues/10732
+        yield  # pylint: disable=unreachable
+
+    @abc.abstractmethod
+    async def close(self) -> None: ...