ee[c@sdZddlZddlZddlZddlZddlZddlmZm Z ddl m Z ddl m Z mZmZejeZe ZdefdYZdZd Zd efd YZd efd YZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZ de efdYZ!de efdYZ"defdYZ#d e#efd!YZ$d"e#efd#YZ%ied$6ed%6ed&6e$d'6e%d(6Z&dS()sResponse parsers for the various protocol types. The module contains classes that can take an HTTP response, and given an output shape, parse the response into a dict according to the rules in the output shape. There are many similarities amongst the different protocols with regard to response parsing, and the code is structured in a way to avoid code duplication when possible. The diagram below is a diagram showing the inheritance hierarchy of the response classes. :: +--------------+ |ResponseParser| +--------------+ ^ ^ ^ +--------------------+ | +-------------------+ | | | +----------+----------+ +------+-------+ +-------+------+ |BaseXMLResponseParser| |BaseRestParser| |BaseJSONParser| +---------------------+ +--------------+ +--------------+ ^ ^ ^ ^ ^ ^ | | | | | | | | | | | | | ++----------+-+ +-+-----------++ | | |RestXMLParser| |RestJSONParser| | +-----+-----+ +-------------+ +--------------+ +----+-----+ |QueryParser| |JSONParser| +-----------+ +----------+ The diagram above shows that there is a base class, ``ResponseParser`` that contains logic that is similar amongst all the different protocols (``query``, ``json``, ``rest-json``, ``rest-xml``). Amongst the various services there is shared logic that can be grouped several ways: * The ``query`` and ``rest-xml`` both have XML bodies that are parsed in the same way. * The ``json`` and ``rest-json`` protocols both have JSON bodies that are parsed in the same way. * The ``rest-json`` and ``rest-xml`` protocols have additional attributes besides body parameters that are parsed the same (headers, query string, status code). This is reflected in the class diagram above. The ``BaseXMLResponseParser`` and the BaseJSONParser contain logic for parsing the XML/JSON body, and the BaseRestParser contains logic for parsing out attributes that come from other parts of the HTTP response. Classes like the ``RestXMLParser`` inherit from the ``BaseXMLResponseParser`` to get the XML body parsing logic and the ``BaseRestParser`` to get the HTTP header/status code/query string parsing. Additionally, there are event stream parsers that are used by the other parsers to wrap streaming bodies that represent a stream of events. The BaseEventStreamParser extends from ResponseParser and defines the logic for parsing values from the headers and payload of a message from the underlying binary encoding protocol. Currently, event streams support parsing bodies encoded as JSON and XML through the following hierarchy. +--------------+ |ResponseParser| +--------------+ ^ ^ ^ +--------------------+ | +------------------+ | | | +----------+----------+ +----------+----------+ +-------+------+ |BaseXMLResponseParser| |BaseEventStreamParser| |BaseJSONParser| +---------------------+ +---------------------+ +--------------+ ^ ^ ^ ^ | | | | | | | | +-+----------------+-+ +-+-----------------+-+ |EventStreamXMLParser| |EventStreamJSONParser| +--------------------+ +---------------------+ Return Values ============= Each call to ``parse()`` returns a dict has this form:: Standard Response { "ResponseMetadata": {"RequestId": } } Error response { "ResponseMetadata": {"RequestId": } "Error": { "Code": , "Message": , "Type": , } } iN(tsixt XMLParseError(t EventStream(tparse_timestampt merge_dictstis_json_value_headertResponseParserFactorycBs#eZdZdZdZRS(cCs i|_dS(N(t _defaults(tself((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyt__init__scKs|jj|dS(sOSet default arguments when a parser instance is created. You can specify any kwargs that are allowed by a ResponseParser class. There are currently two arguments: * timestamp_parser - A callable that can parse a timetsamp string * blob_parser - A callable that can parse a blob type N(Rtupdate(Rtkwargs((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pytset_parser_defaultss cCst|}||jS(N(tPROTOCOL_PARSERSR(Rt protocol_namet parser_cls((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyt create_parsers (t__name__t __module__R R R(((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyRs  cCstj|S(N(RR(tprotocol((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyRscsfd}|S(NcsFt|dr0|j}|dkr6d}q6n|}|||S(Nttextt(thasattrRtNone(Rtshapetnode_or_stringR(tfunc(s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyt_get_text_contents    ((RR((Rs4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyt _text_contents tResponseParserErrorcBseZRS((RR(((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyRstResponseParsercBszeZdZdZd Zd d dZdZdZdZ dZ dZ dZ d Z d Zd ZRS( soBase class for response parsing. This class represents the interface that all ResponseParsers for the various protocols must implement. This class will take an HTTP response and a model shape and parse the HTTP response into a dictionary. There is a single public method exposed: ``parse``. See the ``parse`` docstring for more info. sutf-8cCss|dkrt}n||_|dkr6|j}n||_d|_|jdk ro|j|||_ndS(N(RtDEFAULT_TIMESTAMP_PARSERt_timestamp_parsert_default_blob_parsert _blob_parsert_event_stream_parsertEVENT_STREAM_PARSER_CLS(Rttimestamp_parsert blob_parser((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyR s       cCs tj|S(N(tbase64t b64decode(Rtvalue((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyR!scCstjd|dtjd|d|ddkrn|j|rY|j|}q|j||}n|j||}|r|jjdr|St|t r|jdi}|d|d Parse the HTTP response given a shape. :param response: The HTTP response dictionary. This is a dictionary that represents the HTTP request. The dictionary must have the following keys, ``body``, ``headers``, and ``status_code``. :param shape: The model shape describing the expected output. :return: Returns a dictionary representing the parsed response described by the model. In addition to the shape described from the model, each response will also have a ``ResponseMetadata`` which contains metadata about the response, which contains at least two keys containing ``RequestId`` and ``HTTPStatusCode``. Some responses may populate additional keys, but ``RequestId`` will always be present. sResponse headers: %stheaderssResponse body: %stbodyt status_codei-t eventstreamtResponseMetadatatHTTPStatusCodet HTTPHeaders( tLOGtdebugt_is_generic_error_responset_do_generic_error_parset_do_error_parset _do_parset serializationtgett isinstancetdict(RtresponseRtparsedtresponse_metadata((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pytparses cCs8|ddkr4|dj}|jdp3| SdS(NR,iR+s(tstript startswith(RR;R+((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyR3s cCsPtjdiit|dd6tjjjj|ddd6d6id6S(NslReceived a non protocol specific error response from the service, unable to populate error code and message.R,tCodeRtMessagetErrorR.(R1R2tstrRtmovest http_clientt responsesR8(RR;((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyR4s  cCstd|jjdS(Ns %s._do_parse(tNotImplementedErrort __class__R(RR;R((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyR6scCstd|jjdS(Ns%s._do_error_parse(RHRIR(RR;R((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyR5 scCs)t|d|j|j}|||S(Ns _handle_%s(tgetattrt type_namet_default_handle(RRtnodethandler((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyt _parse_shape$s cCs=g}|j}x'|D]}|j|j||qW|S(N(tmembertappendRO(RRRMR<t member_shapetitem((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyt _handle_list)s   cCs|S(N((RRR)((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyRL2sN(RRt__doc__tDEFAULT_ENCODINGRR$R R!R>R3R4R6R5RORTRL(((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyRs   (     tBaseXMLResponseParsercBseZdddZdZdZdZdZdZdZ dZ dZ e d Z e d Ze d Ze d Ze d Ze dZeZeZeZRS(cCs/tt|j||tjd|_dS(Ns{.*}(tsuperRWR tretcompilet _namespace_re(RR%R&((s4/tmp/pip-install-xdEqop/botocore/botocore/parsers.pyR 7sc Csi}|j}|j}|jjdp-d}|jjdpEd}|jjdrvt|t rv|g}nx|D]}xo|D]g} |j| } | |kr|j|| } q| |kr|j|| } qtd| qW| || ts@       .QBeM