U!\c@s$dZddlZddlZddlZddlZddlZddlmZm Z ddl m Z m Z ddl mZmZmZmZejeZeZdefdYZdZd Zd efd YZd efd YZdefdYZdefdYZdefdYZdefdYZ defdYZ!de!e fdYZ"de!efdYZ#de fdYZ$defdYZ%d e%e fd!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(tsixt XMLParseError(t EventStreamtNoInitialResponseError(tparse_timestampt merge_dictstis_json_value_headertlowercase_dicttResponseParserFactorycBs#eZdZdZdZRS(cCs i|_dS(N(t _defaults(tself((s4/tmp/pip-install-usGedi/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(R tupdate(R tkwargs((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pytset_parser_defaultss cCst|}||jS(N(tPROTOCOL_PARSERSR (R t protocol_namet parser_cls((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt create_parsers (t__name__t __module__R RR(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs  cCstj|S(N(RR(tprotocol((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRscsfd}|S(NcsFt|dr0|j}|dkr6d}q6n|}|||S(Nttextt(thasattrRtNone(R tshapetnode_or_stringR(tfunc(s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt_get_text_contents    ((RR((Rs4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt _text_contents tResponseParserErrorcBseZRS((RR(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRstResponseParsercBseZdZdZd Zd d dZdZdZdZ dZ dZ dZ d Z d Zd 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(R ttimestamp_parsert blob_parser((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR s       cCs tj|S(N(tbase64t b64decode(R tvalue((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR#scCstjd|dtjd|d|ddkrn|j|rY|j|}q|j||}n|j||}|r|jjdr|St|t r|jdi}|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_do_error_parset _do_parset serializationtgett isinstancetdictR(R tresponseRtparsedtresponse_metadataR,((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pytparses   cCsX|ddkrTd|ks,|ddkr0tS|dj}|jdpS| SdS(NR.iR-s(RtTruetstript startswith(R R=R-((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR5s cCsPtjdiit|dd6tjjjj|ddd6d6id6S(NslReceived a non protocol specific error response from the service, unable to populate error code and message.R.tCodeRtMessagetErrorR0(R3R4tstrRtmovest http_clientt responsesR:(R R=((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR6s  cCstd|jjdS(Ns %s._do_parse(tNotImplementedErrort __class__R(R R=R((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR8$scCstd|jjdS(Ns%s._do_error_parse(RKRLR(R R=R((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR7'scCs)t|d|j|j}|||S(Ns _handle_%s(tgetattrt type_namet_default_handle(R Rtnodethandler((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt _parse_shape+s cCs=g}|j}x'|D]}|j|j||qW|S(N(tmembertappendRR(R RRPR>t member_shapetitem((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt _handle_list0s   cCs|S(N((R RR+((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRO9scCs3|j}|djd}t|d|||S(Ntcontexttoperation_nameR-(R%R:R(R R=Rtparsertname((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt_create_event_stream<s N(RRt__doc__tDEFAULT_ENCODINGRR&R R#R@R5R6R8R7RRRWROR\(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR s   ,     tBaseXMLResponseParsercBseZdddZdZdZdZdZdZdZ dZ dZ e d Z e d Ze d Ze d Ze d Ze dZeZeZeZRS(cCs/tt|j||tjd|_dS(Ns{.*}(tsuperR_R tretcompilet _namespace_re(R R'R(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR Csc Csi}|j}|j}|jjdp-d}|jjdpEd}|jjdrvt|t rv|g}nx|D]}xo|D]g} |j| } | |kr|j|| } q| |kr|j|| } qtd| qW| || t key_shapet value_shapetkey_location_nametvalue_location_namet keyval_nodet single_pairttag_nametkey_nametval_name((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt _handle_mapHs"  "     cCs|jjd|jS(NR(Rctsubttag(R RP((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRg]scCsG|jjdr.t|t r.|g}ntt|j||S(NRe(R9R:R;RfR`R_RW(R RRP((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRW`s" cCs?i}|j}|j|}x|D]}||}d|jks%|jjdr\q%n|j||}|j|} | dk r|j|| ||Rxtxml_dictt member_nameRUtxml_namet member_nodetattribst location_nameRdR+tnew_key((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt_handle_structurejs.       cCso|jdkrI|jjdrI|jjjd}|dk rI|Sn|jjd}|dk rk|S|S(NRfReR[(RNR9R:RSR(R RRtlist_member_serialized_nametserialized_name((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRzs!    cCst|tr |j|dSi}xq|D]i}|j|}||krt||tru||j|q|||g||RdR+tsub_dict((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs  cCs|dkrtStSdS(Nttrue(RAtFalse(R RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt_handle_booleans cCs t|S(N(tfloat(R RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt _handle_floatscCs |j|S(N(R"(R RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt_handle_timestampscCs t|S(N(tint(R RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt_handle_integerscCs|S(N((R RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt_handle_stringscCs |j|S(N(R$(R RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyt _handle_blobsN(RRRR RqRgRWRRzRyRRRRRRRRRt_handle_charactert_handle_doublet _handle_long(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR_Bs$      t QueryParsercBs,eZdZdZdZdZRS(cCs|d}|j|}|j|}|j|d|krZ|j|jdnd|kri|jdd6|d((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR7s    cCs|d}|j|}i}|dk rq|}d|jkr\|j|jd|}n|j||}n|j|||S(NR-t resultWrapper(RRR9t_find_result_wrapped_shapeRRt_inject_response_metadata(R R=RRRR>tstart((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR8s    cCs|j|}||S(N(Ry(R t element_namet xml_root_nodetmapping((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRscCst|j|}|jd}|dk rp|j|}x'|jD]\}}|j||RhRiRdt actual_keyt actual_value((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRq?s  cCs |j|S(N(R$(R RR+((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRIscCs |j|S(N(R"(R RR+((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRLscCs|j|d}iidd6dd6d6id6}|jd|jdd|dd<|jd}|jd |ot|}|dk rd |kr|jd d d }n||ddR,((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRjs cCsS|s iS|j|j}ytj|}|SWntk rNi|d6SXdS(NR(tdecodeR^tjsontloadst ValueError(R t body_contentsR-toriginal_parsed((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRos ( RRRRqRRR7RR(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR+s     tBaseEventStreamParsercBs5eZdZdZdZdZdZRS(cCsi}|jjdr_|djd}|jj|}|r|j||||t event_name((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR8s  c Csx|j|}|j||}y|j}Wn#tk rTd}t|nX|j|j|}|||<|S(Ns,First event was not of type initial-response(RxR\tget_initial_responseRRRtpayload( R R=RRtevent_stream_shapet event_streamRt error_msgR>((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs   cCs|j|}|j||S(N(RRR(R traw_bodyRt parsed_json((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs(RRRR&R8RR(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs tBaseRestParsercBsGeZdZdZdZdZdZdZdZRS(cCsbi}|j||d<|dkr)|S|j}|j|||||j|||||S(NR0(t_populate_response_metadataRRxRR(R R=RRR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR8s     cCsdi}|d}d|kr-|d|dtprefixRR[((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRCs cCstddS(NR(RK(R R((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRPscCsC|}t|r?tj|j|j}tj|}n|S(N(RR)R*RR^RR(R RR+R>tdecoded((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRWs  ( RRR8RRRRRR(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs   tRestJSONParsercBs)eZeZdZdZdZRS(cCs |j|S(N(R(R R((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRcscCs/tt|j||}|j|||S(N(R`RR7t_inject_error_code(R R=RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyR7fscCs|j|d}d|dkrU|dd}|jdd}||ddRtdefault((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs    cCstt|j||}|S(N(R`RR(R RR((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRs( RRRR&RR7RRRR(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pyRzs    tec2tqueryRs rest-jsonsrest-xml()R]RaR)Rtxml.etree.cElementTreeRtloggingtbotocore.compatRRtbotocore.eventstreamRRtbotocore.utilsRRRRt getLoggerRR3R!tobjectRRRt ExceptionRR R_RRRRRRRRRRR(((s4/tmp/pip-install-usGedi/botocore/botocore/parsers.pytts@     "  .QN$cM