o ?cU@svdZddlZddlZddlZddlZddlmZmZmZddl m Z m Z ddl m Z mZmZmZeeZeZGdddZdd Zd d ZGd d d eZGdddZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeeZ GdddeeZ!GdddeZ"Gd d!d!eZ#Gd"d#d#e#eZ$Gd$d%d%e#eZ%eee"e$e%d&Z&dS)'aResponse 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": , } } N)ETree XMLParseErrorsix) EventStreamNoInitialResponseError)is_json_value_headerlowercase_dict merge_dictsparse_timestampc@s$eZdZddZddZddZdS)ResponseParserFactorycCs i|_dSN) _defaults)selfrk/private/var/folders/cw/wlscbxl13mj6wd668h7l9g9sllkg5j/T/pip-target-b31awkwq/lib/python/botocore/parsers.py__init__ zResponseParserFactory.__init__cKs|j|dS)aOSet 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 update)rkwargsrrrset_parser_defaultss z)ResponseParserFactory.set_parser_defaultscCst|}|di|jS)Nr)PROTOCOL_PARSERSr )rZ protocol_nameZ parser_clsrrr create_parsersz#ResponseParserFactory.create_parserN)__name__ __module__ __qualname__rrrrrrrr s r cCs t|Sr )r r)protocolrrrr rcsfdd}|S)Ncs.t|dr|j}|durd}n|}|||S)Ntext)hasattrr)rshapenode_or_stringrfuncrr_get_text_contents  z(_text_content.._get_text_contentr)r#r$rr"r _text_contents  r%c@s eZdZdS)ResponseParserErrorN)rrrrrrrr&sr&c@seZdZdZdZdZd&ddZddZdd Zd d Z d d Z ddZ ddZ ddZ ddZddZddZddZddZddZd d!Zd"d#Zd$d%ZdS)'ResponseParseraoBase 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. zutf-8NcCsL|durt}||_|dur|j}||_d|_|jdur$||||_dSdSr )DEFAULT_TIMESTAMP_PARSER_timestamp_parser_default_blob_parser _blob_parser_event_stream_parserEVENT_STREAM_PARSER_CLSrZtimestamp_parserZ blob_parserrrrrs  zResponseParser.__init__cCs t|Sr )base64 b64decodervaluerrrr*s z#ResponseParser._default_blob_parsercCstd|dtd|d|ddkr5||r!||}n||r.|||}|S|||}n|||}|rE|j drE|St |t rj| di}|d|d <|d}t ||d <||d<| |||S) a>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. zResponse headers: %sheaderszResponse body: %sbody status_codei- eventstreamResponseMetadataZHTTPStatusCodeZ HTTPHeaders)LOGdebug_is_generic_error_response_do_generic_error_parse_is_modeled_error_shape_do_modeled_error_parse_do_error_parse _do_parse serializationget isinstancedictr_add_checksum_response_metadata)rresponser parsedresponse_metadatar3rrrparses(           zResponseParser.parsecCs2|didi}|d}|r||d<dSdS)NcontextZchecksumZresponse_algorithmZChecksumAlgorithmrA)rrErGZchecksum_context algorithmrrrrDs   z.ResponseParser._add_checksum_response_metadatacCs|duo |jddS)N exceptionF)metadatarA)rr rrrr<sz&ResponseParser._is_modeled_error_shapecCsD|ddkr d|vs|ddurdS|d}|dp| SdS)Nr5ir4Ts)strip startswith)rrEr4rrrr:s  z)ResponseParser._is_generic_error_responsecCs4tdt|dtjjj|dddidS)NzlReceived a non protocol specific error response from the service, unable to populate error code and message.r5rCodeMessageErrorr7)r8r9strrmoves http_client responsesrArrErrrr;+s  z&ResponseParser._do_generic_error_parsecCstd|jj)Nz %s._do_parseNotImplementedError __class__rrrEr rrrr?<zResponseParser._do_parsecCt|jjd)Nz._do_error_parserZr]rrrr>?szResponseParser._do_error_parsecCr_)Nz._do_modeled_error_parserZ)rrEr rFrrrr=Bs z&ResponseParser._do_modeled_error_parsecCs t|d|j|j}|||S)NZ_handle_)getattr type_name_default_handle)rr nodehandlerrrr _parse_shapeGs zResponseParser._parse_shapecCs*g}|j}|D] }||||q|Sr )memberappendre)rr rcrF member_shapeitemrrr _handle_listMs zResponseParser._handle_listcC|Sr rrr r2rrrrbVszResponseParser._default_handlecCs&|j}|dd}t|d|||S)NrIZoperation_namer4)r,rAr)rrEr parsernamerrr_create_event_streamYsz#ResponseParser._create_event_streamcCs t|dSNr)listr1rrr_get_first_key^rzResponseParser._get_first_keycCsR|jr't|dkrd}t||j||}||jvr'd}t||dSdS)NzCInvalid service response: %s must have one and only one member set.zqReceived a tagged union response with member unknown to client: %s. Please upgrade SDK for full response support.TF)Zis_tagged_unionlenr&rnrrmembersr8info)rr r2 error_msgtagmsgrrr _has_unknown_tagged_union_memberas   z/ResponseParser._has_unknown_tagged_union_membercCs dd|iiS)NZSDK_UNKNOWN_MEMBERrnr)rrxrrr#_handle_unknown_tagged_union_membertrz2ResponseParser._handle_unknown_tagged_union_memberNN)rrr__doc__DEFAULT_ENCODINGr-rr*rHrDr<r:r;r?r>r=rerjrbrorrrzr{rrrrr's*   1  r'cseZdZd"fdd ZddZddZfdd Zd d Zd d ZddZ ddZ ddZ ddZ e ddZe ddZe ddZe ddZe ddZe d d!ZeZeZeZZS)#BaseXMLResponseParserNcst||td|_dS)Nz{.*})superrrecompile _namespace_rer.r\rrryszBaseXMLResponseParser.__init__c Csi}|j}|j}|jdpd}|jdpd}|jdr&t|ts&|g}|D]+}|D]"} || } | |kr>||| } q,| |krI||| } q,td| | || <q(|S)Nrnkeyr2 flattenedzUnknown tag: %s) rr2r@rArBrq _node_tagrer&) rr rcrF key_shape value_shapeZkey_location_nameZvalue_location_nameZ keyval_nodeZ single_pairZtag_nameZkey_nameZval_namerrr _handle_map}s"   z!BaseXMLResponseParser._handle_mapcCs|jd|jSNr)rsubrx)rrcrrrrr^zBaseXMLResponseParser._node_tagcs*|jdrt|ts|g}t||S)Nr)r@rArBrqrrj)rr rcrrrrjsz"BaseXMLResponseParser._handle_listcCsi}|j}|jddr||}||}|||r&||}||S|D]]}||}d|jvs9|jdr:q(| ||} || } | durR| || ||<q(|jdri} |jd} |j D]\} }|j | ddd| }|| |<qd| | vr| | ||<q(|S) NrLFlocation eventheaderZ xmlAttributern:r)rurMrA_get_error_root_build_name_to_xml_noderzrrr{r@_member_key_namereattribitemsrrsplit)rr rcrFruxml_dictrx member_namerhZxml_nameZ member_nodeattribsZ location_namerr2Znew_keyrrr_handle_structuresB            z'BaseXMLResponseParser._handle_structurecCs2||dkr|D] }||dkr|Sq |S)NZ ErrorResponserTr)r original_rootchildrrrrs z%BaseXMLResponseParser._get_error_rootcCsL|jdkr|jdr|jjd}|dur|S|jd}|dur$|S|S)Nrqrrn)rar@rArf)rr rZlist_member_serialized_nameZserialized_namerrrrs z&BaseXMLResponseParser._member_key_namecCstt|tr ||dSi}|D]'}||}||vr3t||tr*|||q|||g||<q|||<q|Srp)rBrqrrrg)rZ parent_noderrirrrrrs   z-BaseXMLResponseParser._build_name_to_xml_nodec CsVztjt|jd}|||}W|Sty*}ztd||fd}~ww)N)targetencodingzTUnable to parse response (%s), invalid XML received. Further retries may succeed: %s)r XMLParser TreeBuilderr~feedcloserr&)r xml_stringrmrooterrr_parse_xml_string_to_doms   z.BaseXMLResponseParser._parse_xml_string_to_domcCsB|D]\}}t|r||}||||<q|j||<q|Sr )rrqr_replace_nodesr)rrFrr2Zsub_dictrrrrs   z$BaseXMLResponseParser._replace_nodescCs|dkrdSdS)NtrueTFrrr rrrr_handle_boolean sz%BaseXMLResponseParser._handle_booleancCt|Sr )floatrrrr _handle_floatz#BaseXMLResponseParser._handle_floatcC ||Sr r)rrrr_handle_timestamp z'BaseXMLResponseParser._handle_timestampcCrr intrrrr_handle_integerrz%BaseXMLResponseParser._handle_integercCrkr rrrrr_handle_stringsz$BaseXMLResponseParser._handle_stringcCrr r+rrrr _handle_blob rz"BaseXMLResponseParser._handle_blobr|)rrrrrrrjrrrrrrr%rrrrrrZ_handle_characterZ_handle_double _handle_long __classcell__rrrrrxs4  $       rc@s>eZdZddZddZddZddd Zd d Zd d ZdS) QueryParsercCs\|d}||}||}||d|vr||dd|vr,d|di|d<|S)Nr4Errors RequestIdr7)rrrrpop)rrEr xml_contentsrrFrrrr>*s   zQueryParser._do_error_parsecC|j||ddS)NFinject_metadata_parse_body_as_xmlr]rrrr=:r^z#QueryParser._do_modeled_error_parsecCr)NTrrr]rrrr?=r^zQueryParser._do_parseTcCs^|d}||}i}|dur%|}d|jvr||jd|}|||}|r-||||S)Nr4Z resultWrapper)rr@_find_result_wrapped_shapere_inject_response_metadata)rrEr rrrrFstartrrrr@s     zQueryParser._parse_body_as_xmlcCs||}||Sr )r)rZ element_nameZ xml_root_nodemappingrrrrOs z&QueryParser._find_result_wrapped_shapecCsR||}|d}|dur'||}|D] \}}|j||<q||d<dSdSNr7)rrArr)rrc inject_intor child_nodeZ sub_mappingrr2rrrrSs     z%QueryParser._inject_response_metadataN)T) rrrr>r=r?rrrrrrrr)s  rcs,eZdZddZfddZddZZS)EC2QueryParsercCs2||}|d}|durd|ji|d<dSdS)NZ requestIdrr7)rrAr)rrcrrrrrrr^s  z(EC2QueryParser._inject_response_metadatacs,t||}d|vrd|di|d<|S)NZ RequestIDrr7)rr>r)rrEr originalrrrr>ds   zEC2QueryParser._do_error_parsecCs@|D]}||dkr|D]}||dkr|Sq q|S)NrrTr)rrrZ errors_childrrrrxs zEC2QueryParser._get_error_root)rrrrr>rrrrrrr]s rc@sDeZdZddZddZddZddZd d Zd d Zd dZ dS)BaseJSONParserc Csi}|jr |}|S|j}|durdSi}|||r$||}||S|D] }||}|jd|}||} | durF|||| ||<q&|S)Nrn)Zis_document_typerurzrrr{r@rAre) rr r2 final_parsed member_shapesrxrrh json_nameZ raw_valuerrrrs*    z BaseJSONParser._handle_structurec CsFi}|j}|j}|D]\}}|||}|||}|||<q |Sr )rr2rre) rr r2rFrrrZ actual_keyZ actual_valuerrrrs   zBaseJSONParser._handle_mapcCrr rrlrrrrrzBaseJSONParser._handle_blobcCrr rrlrrrrrz BaseJSONParser._handle_timestampcCs||d}dddid}|d|dd|dd<|d}|d |o*t|}|durBd |vr<|d d d }||dd <|||d |S)Nr4rrRrQrSmessagerRrTr5Z__type#rsrQr3)_parse_body_as_jsonrArUrsplitr)rrEr r4errorZ response_codecoderrrr>s   zBaseJSONParser._do_error_parsecCs$d|vr|d|did<dSdS)Nx-amzn-requestidr7r) setdefault)rrFr3rrrrs z(BaseJSONParser._inject_response_metadatacCs@|siS||j}zt|}|WStyd|iYSw)Nr)decoder~jsonloads ValueError)r body_contentsr4original_parsedrrrrs    z"BaseJSONParser._parse_body_as_jsonN) rrrrrrrr>rrrrrrrs  rc@s4eZdZddZddZddZddZd d Zd S) BaseEventStreamParsercCsji}|jdr!|dd}|j|}|r|||||<|S||||j|||||j||S)Nr6r3z :event-type)r@rArur?_parse_non_payload_attrs_parse_payload)rrEr rZ event_typeZ event_shaperrrr?s   zBaseEventStreamParser._do_parsec Cs|dd}|j|}|dur/||d}|||}d||d|dddi}|Sd|dd d|dd ddi}|S) Nr3z:exception-typer4rTrRrrrPz :error-codez:error-message)rAru_initial_body_parsere)rrEr Zexception_typeZexception_shaperr4rrrrr>s"   z%BaseEventStreamParser._do_error_parsec Cs|jdrS|D]6}||}|jdr>|d}|jdkr |}n|jdkr,||j}n ||} ||| }|||<dSq||d} ||| } || dSdS)NeventZ eventpayloadr4blobstring)r@rArarr~rrer) rrEr rrrnrhr4Z parsed_bodyZ raw_parser body_parsedrrrrs(      z$BaseEventStreamParser._parse_payloadc CsZ|d}|D]$}||}|jdr*||vr*||}|jdkr&||d}|||<qdS)Nr3r timestampg@@)r@rArar)) rrEr rrr3rnrhr2rrrrs  z.BaseEventStreamParser._parse_non_payload_attrscCtdNrr[rrrrrr%z)BaseEventStreamParser._initial_body_parseN)rrrr?r>rrrrrrrrs  rc@eZdZddZdS)EventStreamJSONParsercC ||Sr rrrrrr.rz)EventStreamJSONParser._initial_body_parseNrrrrrrrrr- rc@r)EventStreamXMLParsercC|stdS||SrrElementrrrrrrr3  z(EventStreamXMLParser._initial_body_parseNrrrrrr2rrc@s2eZdZeZ ddZddZddZddZd S) JSONParsercCsJi}|dur|j}|r||||}n||d|}|||d|S)Nr4r3)Zevent_stream_name_handle_event_stream_handle_json_bodyr)rrEr rF event_namerrrr??szJSONParser._do_parsecCs||d|S)Nr4)rr]rrrr=Jr^z"JSONParser._do_modeled_error_parsec CsX|j|}|||}z|}Wn tyd}t|w||j|}|||<|S)Nz,First event was not of type initial-response)ruroZget_initial_responserr&rpayload) rrEr rZevent_stream_shapeZ event_streamrrwrFrrrrMs    zJSONParser._handle_event_streamcCs||}|||Sr )rre)rZraw_bodyr Z parsed_jsonrrrrYs  zJSONParser._handle_json_bodyN) rrrrr-r?r=rrrrrrr9s  rcsdeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ fddZ Z S)BaseRestParsercCs$i}|||d<|||||Sr)_populate_response_metadata_add_modeled_parserrEr rrrrr?bs zBaseRestParser._do_parsecCs6|dur|S|j}||||||||||dSr )rurr)rrEr rrrrrrjsz!BaseRestParser._add_modeled_parsecCsi}|||||Sr )rrrrrr=ssz&BaseRestParser._do_modeled_error_parsecCsLi}|d}d|vr|d|d<|Sd|vr$|d|d<|dd|d<|S)Nr3rrx-amz-request-id x-amz-id-2rHostIdrJ)rrErMr3rrrrxs  z*BaseRestParser._populate_response_metadatac Csd|jvrK|jd}||}|jdr |||}|||<dS|jdvr:|d}t|tr4||j}|||<dS||d}| ||||<dS||d}| ||} | | dS)Nrr6)rrr4) r@rArorarBbytesrr~rrer) rrEr rrZpayload_member_nameZ body_shaper4rrrrrrs$           zBaseRestParser._parse_payloadc Cs|d}|D]F}||}|jd}|durq|dkr&|||d||<q|dkr3|||||<q|dkrL|jd|} | |vrL|||| ||<qdS)Nr3rZ statusCoder5headerrn)r@rAre_parse_header_map) rrEr rrr3rnrhr header_namerrrrs,   z'BaseRestParser._parse_non_payload_attrscCsNi}|jdd}|D]}||r$|t|d}||||<q |S)Nrnr)r@rAlowerrOrt)rr r3rFprefixr rnrrrr s z BaseRestParser._parse_header_mapcCrrrrrrrrrz"BaseRestParser._initial_body_parsecCs,|}t|rt||j}t|}|Sr )rr/r0rr~rr)rr r2rFdecodedrrrrs  zBaseRestParser._handle_stringcs@|jd}|dkrt|tsdd|dD}t||S)NrrcSsg|]}|qSr)rN).0rrrr sz/BaseRestParser._handle_list..,)r@rArBrqrrrj)rr rcrrrrrjs zBaseRestParser._handle_list)rrrr?rr=rrrr rrrjrrrrrras   rcs<eZdZeZddZfddZddZddZeZ Z S) RestJSONParsercCrr rrrrrrrz"RestJSONParser._initial_body_parsecst||}||||Sr )rr>_inject_error_code)rrEr rrrrr>s zRestJSONParser._do_error_parsecCsx||d}d|dvr"|dd}|dd}||dd<dSd|vs*d|vr:|d|dd |dd<dSdS) Nr4zx-amzn-errortyper3rrrTrQrr)rrrA)rrrEr4rrrrrs   z!RestJSONParser._inject_error_codecCrr rrlrrrrszRestJSONParser._handle_integer) rrrrr-rr>rrrrrrrrrs  rcsDeZdZeZddZddZddZddZe fd d Z Z S) RestXMLParsercCrrrrrrrrrz!RestXMLParser._initial_body_parsecCs@|drz||WStytjdddYnw||S)Nr4z2Exception caught when parsing error response body:T)exc_info)_parse_error_from_bodyr&r8r9_parse_error_from_http_statusr]rrrr>s    zRestXMLParser._do_error_parsecCsHt|dtjjj|ddd|ddd|dddddS) Nr5rrPr3rr)rrrS)rUrrVrWrXrArYrrrrs  z+RestXMLParser._parse_error_from_http_statuscCs|d}||}||}|||jdkr.||}|dd|dd||dSd|vr;d|di|d<ddddi}t|||S) Nr4rTrrrrSr7r)rrrrxrrr )rrErrrFrMdefaultrrrr*s         z$RestXMLParser._parse_error_from_bodycst||}|Sr )rrrrrrrAszRestXMLParser._handle_string) rrrrr-rr>rrr%rrrrrrrsr)Zec2queryrz rest-jsonzrest-xml)'r}r/rloggingrZbotocore.compatrrrZbotocore.eventstreamrrZbotocore.utilsrrr r getLoggerrr8r(r rr% Exceptionr&r'rrrrrrrrrrrrrrrrsD h ?24$YS(xP