Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
__init__.py330 linesDownload Raw Back to pipeline
1# --------------------------------------------------------------------------2#3# Copyright (c) Microsoft Corporation. All rights reserved.4#5# The MIT License (MIT)6#7# Permission is hereby granted, free of charge, to any person obtaining a copy8# of this software and associated documentation files (the ""Software""), to9# deal in the Software without restriction, including without limitation the10# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or11# sell copies of the Software, and to permit persons to whom the Software is12# furnished to do so, subject to the following conditions:13#14# The above copyright notice and this permission notice shall be included in15# all copies or substantial portions of the Software.16#17# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS23# IN THE SOFTWARE.24#25# --------------------------------------------------------------------------26from __future__ import absolute_import  # we have a "requests" module that conflicts with "requests" on Py2.727import abc28try:29    import configparser30    from configparser import NoOptionError31except ImportError:32    import ConfigParser as configparser  # type: ignore33    from ConfigParser import NoOptionError  # type: ignore34import json35import logging36import os.path37try:38    from urlparse import urlparse39except ImportError:40    from urllib.parse import urlparse41import xml.etree.ElementTree as ET42 43from typing import TYPE_CHECKING, Generic, TypeVar, cast, IO, List, Union, Any, Mapping, Dict, Optional, Tuple, Callable, Iterator  # pylint: disable=unused-import44 45HTTPResponseType = TypeVar("HTTPResponseType")46HTTPRequestType = TypeVar("HTTPRequestType")47 48# This file is NOT using any "requests" HTTP implementation49# However, the CaseInsensitiveDict is handy.50# If one day we reach the point where "requests" can be skip totally,51# might provide our own implementation52from requests.structures import CaseInsensitiveDict53 54 55_LOGGER = logging.getLogger(__name__)56 57try:58    ABC = abc.ABC59except AttributeError: # Python 2.7, abc exists, but not ABC60    ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})  # type: ignore61 62try:63    from contextlib import AbstractContextManager  # type: ignore64except ImportError: # Python <= 3.565    class AbstractContextManager(object):  # type: ignore66        def __enter__(self):67            """Return `self` upon entering the runtime context."""68            return self69 70        @abc.abstractmethod71        def __exit__(self, exc_type, exc_value, traceback):72            """Raise any exception triggered within the runtime context."""73            return None74 75class HTTPPolicy(ABC, Generic[HTTPRequestType, HTTPResponseType]):76    """An http policy ABC.77    """78    def __init__(self):79        self.next = None80 81    @abc.abstractmethod82    def send(self, request, **kwargs):83        # type: (Request[HTTPRequestType], Any) -> Response[HTTPRequestType, HTTPResponseType]84        """Mutate the request.85 86        Context content is dependent of the HTTPSender.87        """88        pass89 90class SansIOHTTPPolicy(Generic[HTTPRequestType, HTTPResponseType]):91    """Represents a sans I/O policy.92 93    This policy can act before the I/O, and after the I/O.94    Use this policy if the actual I/O in the middle is an implementation95    detail.96 97    Context is not available, since it's implementation dependent.98    if a policy needs a context of the Sender, it can't be universal.99 100    Example: setting a UserAgent does not need to be tight to101    sync or async implementation or specific HTTP lib102    """103    def on_request(self, request, **kwargs):104        # type: (Request[HTTPRequestType], Any) -> None105        """Is executed before sending the request to next policy.106        """107        pass108 109    def on_response(self, request, response, **kwargs):110        # type: (Request[HTTPRequestType], Response[HTTPRequestType, HTTPResponseType], Any) -> None111        """Is executed after the request comes back from the policy.112        """113        pass114 115    def on_exception(self, request, **kwargs):116        # type: (Request[HTTPRequestType], Any) -> bool117        """Is executed if an exception comes back from the following118        policy.119 120        Return True if the exception has been handled and should not121        be forwarded to the caller.122 123        This method is executed inside the exception handler.124        To get the exception, raise and catch it:125 126            try:127                raise128            except MyError:129                do_something()130 131        or use132 133            exc_type, exc_value, exc_traceback = sys.exc_info()134        """135        return False136 137class _SansIOHTTPPolicyRunner(HTTPPolicy, Generic[HTTPRequestType, HTTPResponseType]):138    """Sync implementation of the SansIO policy.139    """140 141    def __init__(self, policy):142        # type: (SansIOHTTPPolicy) -> None143        super(_SansIOHTTPPolicyRunner, self).__init__()144        self._policy = policy145 146    def send(self, request, **kwargs):147        # type: (Request[HTTPRequestType], Any) -> Response[HTTPRequestType, HTTPResponseType]148        self._policy.on_request(request, **kwargs)149        try:150            response = self.next.send(request, **kwargs)151        except Exception:152            if not self._policy.on_exception(request, **kwargs):153                raise154        else:155            self._policy.on_response(request, response, **kwargs)156        return response157 158class Pipeline(AbstractContextManager, Generic[HTTPRequestType, HTTPResponseType]):159    """A pipeline implementation.160 161    This is implemented as a context manager, that will activate the context162    of the HTTP sender.163    """164 165    def __init__(self, policies=None, sender=None):166        # type: (List[Union[HTTPPolicy, SansIOHTTPPolicy]], HTTPSender) -> None167        self._impl_policies = []  # type: List[HTTPPolicy]168        if not sender:169            # Import default only if nothing is provided170            from .requests import PipelineRequestsHTTPSender171            self._sender = cast(HTTPSender, PipelineRequestsHTTPSender())172        else:173            self._sender = sender174        for policy in (policies or []):175            if isinstance(policy, SansIOHTTPPolicy):176                self._impl_policies.append(_SansIOHTTPPolicyRunner(policy))177            else:178                self._impl_policies.append(policy)179        for index in range(len(self._impl_policies)-1):180            self._impl_policies[index].next = self._impl_policies[index+1]181        if self._impl_policies:182            self._impl_policies[-1].next = self._sender183 184    def __enter__(self):185        # type: () -> Pipeline186        self._sender.__enter__()187        return self188 189    def __exit__(self, *exc_details):  # pylint: disable=arguments-differ190        self._sender.__exit__(*exc_details)191 192    def run(self, request, **kwargs):193        # type: (HTTPRequestType, Any) -> Response194        context = self._sender.build_context()195        pipeline_request = Request(request, context)  # type: Request[HTTPRequestType]196        first_node = self._impl_policies[0] if self._impl_policies else self._sender197        return first_node.send(pipeline_request, **kwargs)  # type: ignore198 199class HTTPSender(AbstractContextManager, ABC, Generic[HTTPRequestType, HTTPResponseType]):200    """An http sender ABC.201    """202 203    @abc.abstractmethod204    def send(self, request, **config):205        # type: (Request[HTTPRequestType], Any) -> Response[HTTPRequestType, HTTPResponseType]206        """Send the request using this HTTP sender.207        """208        pass209 210    def build_context(self):211        # type: () -> Any212        """Allow the sender to build a context that will be passed213        across the pipeline with the request.214 215        Return type has no constraints. Implementation is not216        required and None by default.217        """218        return None219 220 221class Request(Generic[HTTPRequestType]):222    """Represents a HTTP request in a Pipeline.223 224    URL can be given without query parameters, to be added later using "format_parameters".225 226    Instance can be created without data, to be added later using "add_content"227 228    Instance can be created without files, to be added later using "add_formdata"229 230    :param str method: HTTP method (GET, HEAD, etc.)231    :param str url: At least complete scheme/host/path232    :param dict[str,str] headers: HTTP headers233    :param files: Files list.234    :param data: Body to be sent.235    :type data: bytes or str.236    """237    def __init__(self, http_request, context=None):238        # type: (HTTPRequestType, Optional[Any]) -> None239        self.http_request = http_request240        self.context = context241 242 243class Response(Generic[HTTPRequestType, HTTPResponseType]):244    """A pipeline response object.245 246    The Response interface exposes an HTTP response object as it returns through the pipeline of Policy objects.247    This ensures that Policy objects have access to the HTTP response.248 249    This also have a "context" dictionary where policy can put additional fields.250    Policy SHOULD update the "context" dictionary with additional post-processed field if they create them.251    However, nothing prevents a policy to actually sub-class this class a return it instead of the initial instance.252    """253    def __init__(self, request, http_response, context=None):254        # type: (Request[HTTPRequestType], HTTPResponseType, Optional[Dict[str, Any]]) -> None255        self.request = request256        self.http_response = http_response257        self.context = context or {}258 259 260# ClientRawResponse is in Pipeline for compat, but technically there is nothing Pipeline here, this is deserialization261 262if TYPE_CHECKING:263    from ..universal_http import ClientResponse264 265class ClientRawResponse(object):266    """Wrapper for response object.267    This allows for additional data to be gathereded from the response,268    for example deserialized headers.269    It also allows the raw response object to be passed back to the user.270 271    :param output: Deserialized response object. This is the type that would have been returned272     directly by the main operation without raw=True.273    :param response: Raw response object (by default requests.Response instance)274    :type response: ~requests.Response275    """276 277    def __init__(self, output, response):278        # type: (Union[Any], Optional[Union[Response, ClientResponse]]) -> None279        from ..serialization import Deserializer280 281        if isinstance(response, Response):282            # If pipeline response, remove that layer283            response = response.http_response284 285        try:286            # If universal driver, remove that layer287            self.response = response.internal_response  # type: ignore288        except AttributeError:289            self.response = response290 291        self.output = output292        self.headers = {}  # type: Dict[str, Optional[Any]]293        self._deserialize = Deserializer()294 295    def add_headers(self, header_dict):296        # type: (Dict[str, str]) -> None297        """Deserialize a specific header.298 299        :param dict header_dict: A dictionary containing the name of the300         header and the type to deserialize to.301        """302        if not self.response:303            return304        for name, data_type in header_dict.items():305            value = self.response.headers.get(name)306            value = self._deserialize(data_type, value)307            self.headers[name] = value308 309 310 311__all__ = [312    'Request',313    'Response',314    'Pipeline',315    'HTTPPolicy',316    'SansIOHTTPPolicy',317    'HTTPSender',318    # backward compat319    'ClientRawResponse',320]321 322try:323    from .async_abc import AsyncPipeline, AsyncHTTPPolicy, AsyncHTTPSender  # pylint: disable=unused-import324    from .async_abc import __all__ as _async_all325    __all__ += _async_all326except SyntaxError: # Python 2327    pass328except ImportError: # pyinstaller won't include Py3 files in Py2.7 mode329    pass330 
codekingpro/portable-devtools · Team Ai