about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py')
-rw-r--r--.venv/lib/python3.12/site-packages/azure/core/rest/_helpers.py423
1 files changed, 423 insertions, 0 deletions
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
+        )