&>ac@sdZddlZddlZddlZddlZddlmZmZmZddl m Z m Z ddl m Z mZmZmZejeZe ZdefdYZdZd Zd efd YZd efd YZdefdYZdefdYZdefdYZdefdYZdefdYZ de efdYZ!de efdYZ"defdYZ#defdYZ$d e$efd!YZ%d"e$efd#YZ&ied$6ed%6e#d&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(tsixtETreet XMLParseError(t EventStreamtNoInitialResponseError(tparse_timestampt merge_dictstis_json_value_headertlowercase_dicttResponseParserFactorycBs#eZdZdZdZRS(cCs i|_dS(N(t _defaults(tself((s1/usr/lib/fence-agents/bundled/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 timestamp string * blob_parser - A callable that can parse a blob type N(R tupdate(R tkwargs((s1/usr/lib/fence-agents/bundled/botocore/parsers.pytset_parser_defaultss cCst|}||jS(N(tPROTOCOL_PARSERSR (R t protocol_namet parser_cls((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt create_parsers (t__name__t __module__R RR(((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR s  cCstj|S(N(R R(tprotocol((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRscsfd}|S(NcsFt|dr0|j}|dkr6d}q6n|}|||S(Nttextt(thasattrRtNone(R tshapetnode_or_stringR(tfunc(s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt_get_text_contents    ((RR((Rs1/usr/lib/fence-agents/bundled/botocore/parsers.pyt _text_contents tResponseParserErrorcBseZRS((RR(((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR stResponseParsercBseZdZdZdZdddZdZdZdZ dZ dZ dZ d Z d Zd Zd Zd ZdZdZdZdZRS(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(R ttimestamp_parsert blob_parser((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR s       cCs tj|S(N(tbase64t b64decode(R tvalue((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR$scCstjd|dtjd|d|ddkr|j|rY|j|}q|j|r~|j||}|S|j||}n|j||}|r|jj dr|St |t r|j di}|d|d <|d}t ||d <||dParse 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_is_modeled_error_shapet_do_modeled_error_parset_do_error_parset _do_parset serializationtgett isinstancetdictR(R tresponseRtparsedtresponse_metadataR-((s1/usr/lib/fence-agents/bundled/botocore/parsers.pytparses&  cCs|dk o|jjdtS(Nt exception(RtmetadataR=tFalse(R R((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR8scCsX|ddkrTd|ks,|ddkr0tS|dj}|jdpS| SdS(NR/iR.s(RtTruetstript startswith(R R@R.((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR6 s cCsPtjdiit|dd6tjjjj|ddd6d6id6S(NslReceived a non protocol specific error response from the service, unable to populate error code and message.R/tCodeRtMessagetErrorR1(R4R5tstrRtmovest http_clientt responsesR=(R R@((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR7s  cCstd|jjdS(Ns %s._do_parse(tNotImplementedErrort __class__R(R R@R((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR;*scCstd|jjdS(Ns%s._do_error_parse(RQRRR(R R@R((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR:-scCstd|jjdS(Ns%s._do_modeled_error_parse(RQRRR(R R@RRA((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR91scCs)t|d|j|j}|||S(Ns _handle_%s(tgetattrt type_namet_default_handle(R Rtnodethandler((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt _parse_shape5s cCs=g}|j}x'|D]}|j|j||qW|S(N(tmembertappendRX(R RRVRAt member_shapetitem((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt _handle_list:s   cCs|S(N((R RR,((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRUCscCs3|j}|djd}t|d|||S(Ntcontexttoperation_nameR.(R&R=R(R R@Rtparsertname((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt_create_event_streamFs cCst|dS(Ni(tlist(R R,((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt_get_first_keyKscCsw|jrst|dkr7d}t||jn|j|}||jkrsd}tj||tSnt S(NisCInvalid service response: %s must have one and only one member set.sqReceived a tagged union response with member unknown to client: %s. Please upgrade SDK for full response support.( tis_tagged_uniontlenR RaRdtmembersR4tinfoRGRF(R RR,t error_msgttagtmsg((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt _has_unknown_tagged_union_memberNs cCsii|d6d6S(NRatSDK_UNKNOWN_MEMBER((R Rj((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt#_handle_unknown_tagged_union_memberasN(RRt__doc__tDEFAULT_ENCODINGRR'R R$RCR8R6R7R;R:R9RXR]RURbRdRlRn(((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR!s&   0          tBaseXMLResponseParsercBseZdddZdZdZdZdZdZdZ dZ dZ d Z e d Ze d Ze d Ze d Ze dZe dZeZeZeZRS(cCs/tt|j||tjd|_dS(Ns{.*}(tsuperRqR tretcompilet _namespace_re(R R(R)((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR fsc Csi}|j}|j}|jjdp-d}|jjdpEd}|jjdrvt|t rv|g}nx|D]}xo|D]g} |j| } | |kr|j|| } q| |kr|j|| } qtd| qW| || Rct _node_tagRXR ( R RRVRAt key_shapet value_shapetkey_location_nametvalue_location_namet keyval_nodet single_pairttag_nametkey_nametval_name((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt _handle_mapks"  "     cCs|jjd|jS(NR(RutsubRj(R RV((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRxscCsG|jjdr.t|t r.|g}ntt|j||S(NRw(R<R=R>RcRrRqR](R RRV((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR]s" cCsi}|j}|jjdtr6|j|}n|j|}|j||rs|j|}|j|Sx|D]}||}d|j ksz|j jdrqzn|j ||} |j| } | dk r|j || ||RcRRxRZ(R t parent_nodeRR\Rv((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRs  cCsny>tjdtjd|j}|j||j}Wn)tk ri}td||fnX|S(NttargettencodingsTUnable to parse response (%s), invalid XML received. Further retries may succeed: %s(Rt XMLParsert TreeBuilderRptfeedtcloseRR (R t xml_stringR`trootte((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyt_parse_xml_string_to_doms    cCs_xX|jD]J\}}t|rJ|j|}|j|||s(RRRR'R;R9RR(((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRs   tBaseRestParsercBsbeZdZdZdZdZdZdZdZdZ dZ d Z RS( cCs0i}|j||d<|j||||S(NR1(t_populate_response_metadatat_add_modeled_parse(R R@RR((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR;Hs  cCsI|dkr|S|j}|j|||||j||||dS(N(RRgRR(R R@RRR((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyROs     cCsi}|j||||S(N(R(R R@RR((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR9WscCsdi}|d}d|kr-|d|dtbytesRRpRRXR ( R R@RRRtpayload_member_namet body_shapeR.RR((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRis"     c Cs|d}x|D]}||}|jjd}|dkrEqq|dkrn|j||d||}ntt|j||S(NRRt,( R<R=R>RcRRHRrRR](R RRVRR((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR]s+( RRR;RR9RRRRRRR](((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRFs       tRestJSONParsercBs)eZeZdZdZdZRS(cCs |j|S(N(R(R R((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyRscCs/tt|j||}|j|||S(N(RrRR:t_inject_error_code(R R@RR((s1/usr/lib/fence-agents/bundled/botocore/parsers.pyR:scCs|j|d}d|dkrU|dd}|jdd}||ddts>    "  5%XN'rM