o <&aX@szdZddlZddlZddlZddlZddlmZmZmZddl m Z m Z ddl m Z mZmZmZeeZe ZGdddeZdd Zd d ZGd d d eZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZ Gddde eZ!Gddde eZ"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)sixETree XMLParseError) EventStreamNoInitialResponseError)parse_timestamp merge_dictsis_json_value_headerlowercase_dictc@s$eZdZddZddZddZdS)ResponseParserFactorycCs i|_dSN) _defaults)selfr2/usr/lib/python3/dist-packages/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 )r protocol_name 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#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_CLSrtimestamp_parser 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 rd| 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- eventstreamResponseMetadataHTTPStatusCode 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 )rresponser"parsedresponse_metadatar7rrrparses&          zResponseParser.parsecCs|duo |jddS)N exceptionF)metadatarG)rr"rrrrBsz&ResponseParser._is_modeled_error_shapecCsD|ddkr d|vs|ddurdS|d}|dp| SdS)Nr9ir8Ts)strip startswith)rrJr8rrrr@ 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.r9r CodeMessageErrorr;)r>r?strrmoves http_client responsesrGrrJrrrrAs   z&ResponseParser._do_generic_error_parsecCtd|jj)Nz %s._do_parseNotImplementedError __class__rrrJr"rrrrE*zResponseParser._do_parsecCr\)Nz%s._do_error_parser]r`rrrrD- zResponseParser._do_error_parsecCr\)Nz%s._do_modeled_error_parser])rrJr"rKrrrrC1rbz&ResponseParser._do_modeled_error_parsecCst|d|j|j}|||S)Nz _handle_%s)getattr type_name_default_handle)rr"nodehandlerrrr _parse_shape5s  zResponseParser._parse_shapecCs*g}|j}|D] }||||q|Sr )memberappendrh)rr"rfrK member_shapeitemrrr _handle_list:s zResponseParser._handle_listcC|Sr rrr"r6rrrreCszResponseParser._default_handlecCs&|j}|dd}t|d|||S)Ncontextoperation_namer8)r.rGr)rrJr"parsernamerrr_create_event_streamFsz#ResponseParser._create_event_streamcCs t|dSNr)listr5rrr_get_first_keyKrzResponseParser._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)is_tagged_unionlenr(rsrwmembersr>info)rr"r6 error_msgtagmsgrrr _has_unknown_tagged_union_memberNs   z/ResponseParser._has_unknown_tagged_union_membercCs dd|iiS)NSDK_UNKNOWN_MEMBERrsr)rr~rrr#_handle_unknown_tagged_union_memberarz2ResponseParser._handle_unknown_tagged_union_memberNN)rrr__doc__DEFAULT_ENCODINGr/rr,rMrBr@rArErDrCrhrmrertrwrrrrrrr)s(   0   r)cseZdZd"fdd ZddZddZfdd Zd d Zd d ZddZ ddZ ddZ ddZ e ddZe ddZe ddZe ddZe ddZe d d!ZeZeZeZZS)#BaseXMLResponseParserNcs"tt|||td|_dS)Nz{.*})superrrrecompile _namespace_rer0r_rrrfs zBaseXMLResponseParser.__init__c Csi}|j}|j}|jdpd}|jdpd}|jdr&t|ts&|g}|D]+}|D]"} || } | |kr>||| } q,| |krI||| } q,td| | || <q(|S)Nrskeyr6 flattenedzUnknown tag: %s) rr6rFrGrHrv _node_tagrhr() rr"rfrK key_shape value_shapekey_location_namevalue_location_name keyval_node single_pairtag_namekey_nameval_namerrr _handle_mapks"   z!BaseXMLResponseParser._handle_mapcCs|jd|jSNr )rsubr~)rrfrrrrrazBaseXMLResponseParser._node_tagcs.|jdrt|ts|g}tt|||S)Nr)rFrGrHrvrrrm)rr"rfrrrrmsz"BaseXMLResponseParser._handle_listcCsi}|j}|jddr||}||}|||r&||}||S|D]]}||}d|jvs9|jdr:q(| ||} || } | durR| || ||<q(|jdri} |jd} |j D]\} }|j | ddd| }|| |<qd| | vr| | ||<q(|S) NrNFlocation eventheader xmlAttributers:r)r{rOrG_get_error_root_build_name_to_xml_noderrwrrF_member_key_namerhattribitemsrrsplit)rr"rfrKr{xml_dictr~ member_namerkxml_name member_nodeattribs location_namerr6new_keyrrr_handle_structures@             z'BaseXMLResponseParser._handle_structurecCs2||dkr|D] }||dkr|Sq |S)N ErrorResponserVr)r original_rootchildrrrrs z%BaseXMLResponseParser._get_error_rootcCsL|jdkr|jdr|jjd}|dur|S|jd}|dur$|S|S)Nrvrrs)rdrFrGri)rr"rlist_member_serialized_nameserialized_namerrrrs z&BaseXMLResponseParser._member_key_namecCstt|tr ||dSi}|D]'}||}||vr3t||tr*|||q|||g||<q|||<q|Sru)rHrvrrrj)r parent_noderrlrrrrrs   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 TreeBuilderrfeedcloserr()r xml_stringrrrooterrr_parse_xml_string_to_doms   z.BaseXMLResponseParser._parse_xml_string_to_domcCsB|D]\}}t|r||}||||<q|j||<q|Sr )rrvr_replace_nodesr)rrKrr6sub_dictrrrrs   z$BaseXMLResponseParser._replace_nodescCs|dkrdSdS)NtrueTFrrr"rrrr_handle_booleansz%BaseXMLResponseParser._handle_booleancCt|Sr )floatrrrr _handle_floatz#BaseXMLResponseParser._handle_floatcC ||Sr r+rrrr_handle_timestamp z'BaseXMLResponseParser._handle_timestampcCrr )intrrrr_handle_integerrz%BaseXMLResponseParser._handle_integercCrnr rrrrr_handle_stringsz$BaseXMLResponseParser._handle_stringcCrr r-rrrr _handle_blobrz"BaseXMLResponseParser._handle_blobr)rrrrrrrmrrrrrrr'rrrrrr_handle_character_handle_double _handle_long __classcell__rrrrres4          rc@s>eZdZddZddZddZddd Zd d Zd d ZdS) QueryParsercCs\|d}||}||}||d|vr||dd|vr,d|di|d<|S)Nr8Errors RequestIdr;)rrrrpop)rrJr" xml_contentsrrKrrrrDs   zQueryParser._do_error_parsecC|j||ddS)NFinject_metadata_parse_body_as_xmlr`rrrrC#raz#QueryParser._do_modeled_error_parsecCr)NTrrr`rrrrE&razQueryParser._do_parseTcCs^|d}||}i}|dur%|}d|jvr||jd|}|||}|r-||||S)Nr8 resultWrapper)rrF_find_result_wrapped_shaperh_inject_response_metadata)rrJr"rrrrKstartrrrr)s    zQueryParser._parse_body_as_xmlcCs||}||Sr )r)r element_name xml_root_nodemappingrrrr8s z&QueryParser._find_result_wrapped_shapecCsR||}|d}|dur'||}|D] \}}|j||<q||d<dSdSNr;)rrGrr)rrf inject_intor child_node sub_mappingrr6rrrr<s     z%QueryParser._inject_response_metadataN)T) rrrrDrCrErrrrrrrrs  rcs,eZdZddZfddZddZZS)EC2QueryParsercCs2||}|d}|durd|ji|d<dSdS)N requestIdrr;)rrGr)rrfrrrrrrrHs  z(EC2QueryParser._inject_response_metadatacs0tt|||}d|vrd|di|d<|S)N RequestIDrr;)rrrDr)rrJr"originalrrrrDNs   zEC2QueryParser._do_error_parsecCs@|D]}||dkr|D]}||dkr|Sq q|S)NrrVr)rrr errors_childrrrrbs zEC2QueryParser._get_error_root)rrrrrDrrrrrrrFs rc@sDeZdZddZddZddZddZd d Zd d Zd dZ dS)BaseJSONParserc Csi}|jr |}|S|j}|durdSi}|||r$||}||S|D] }||}|jd|}||} | durF|||| ||<q&|S)Nrs)is_document_typer{rrwrrFrGrh) rr"r6 final_parsed member_shapesr~rrk json_name raw_valuerrrrms,    z BaseJSONParser._handle_structurec CsFi}|j}|j}|D]\}}|||}|||}|||<q |Sr )rr6rrh) rr"r6rKrrr actual_key actual_valuerrrrs   zBaseJSONParser._handle_mapcCrr rrorrrrrzBaseJSONParser._handle_blobcCrr rrorrrrrz BaseJSONParser._handle_timestampcCs||d}dddid}|d|dd|dd<|d}|d |o*t|}|durBd |vr<|d d d }||dd <|||d |S)Nr8r rTrSrUmessagerTrVr9__type#rxrSr7)_parse_body_as_jsonrGrWrsplitr)rrJr"r8error response_codecoderrrrDs   zBaseJSONParser._do_error_parsecCs$d|vr|d|did<dSdS)Nx-amzn-requestidr;r) setdefault)rrKr7rrrrsz(BaseJSONParser._inject_response_metadatacCs@|siS||j}zt|}|WStyd|iYSw)Nr)decoderjsonloads ValueError)r body_contentsr8original_parsedrrrrs    z"BaseJSONParser._parse_body_as_jsonN) rrrrrrrrDrrrrrrrks  rc@s4eZdZddZddZddZddZd d Zd S) BaseEventStreamParsercCsji}|jdr!|dd}|j|}|r|||||<|S||||j|||||j||S)Nr:r7z :event-type)rFrGr{rE_parse_non_payload_attrs_parse_payload)rrJr"r event_type event_shaperrrrEs  zBaseEventStreamParser._do_parsec Cs|dd}|j|}|dur/||d}|||}d||d|dddi}|Sd|dd d|dd ddi}|S) Nr7z:exception-typer8rVrTrr rRz :error-codez:error-message)rGr{_initial_body_parserh)rrJr"exception_typeexception_shaperr8rrrrrDs"   z%BaseEventStreamParser._do_error_parsec Cs|jdrS|D]6}||}|jdr>|d}|jdkr |}n|jdkr,||j}n ||} ||| }|||<dSq||d} ||| } || dSdS)Nevent eventpayloadr8blobstring)rFrGrdrrr rhr) rrJr"rrrsrkr8 parsed_body raw_parser body_parsedrrrr s$       z$BaseEventStreamParser._parse_payloadc CsZ|d}|D]$}||}|jdr*||vr*||}|jdkr&||d}|||<qdS)Nr7r timestampg@@)rFrGrdr+) rrJr"rrr7rsrkr6rrrrs  z.BaseEventStreamParser._parse_non_payload_attrscCtdNr r^rrrrrr  z)BaseEventStreamParser._initial_body_parseN)rrrrErDr rr rrrrrs   rc@eZdZddZdS)EventStreamJSONParsercC ||Sr rrrrrr rz)EventStreamJSONParser._initial_body_parseNrrrr rrrrr rc@r)EventStreamXMLParsercC|stdS||SrrElementrrrrrrr   z(EventStreamXMLParser._initial_body_parseNr rrrrr"r!r"c@s2eZdZeZ ddZddZddZddZd S) JSONParsercCsJi}|dur|j}|r||||}n||d|}|||d|S)Nr8r7)event_stream_name_handle_event_stream_handle_json_bodyr)rrJr"rK event_namerrrrE$szJSONParser._do_parsecCs||d|S)Nr8)r+r`rrrrC/raz"JSONParser._do_modeled_error_parsec CsX|j|}|||}z|}Wn tyd}t|w||j|}|||<|S)Nz,First event was not of type initial-response)r{rtget_initial_responserr(r+payload) rrJr"r,event_stream_shape event_streamrr}rKrrrr*2s    zJSONParser._handle_event_streamcCs||}|||Sr )rrh)rraw_bodyr" parsed_jsonrrrr+>s  zJSONParser._handle_json_bodyN) rrrrr/rErCr*r+rrrrr(s  r(csdeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ fddZ Z S)BaseRestParsercCs$i}|||d<|||||Sr)_populate_response_metadata_add_modeled_parserrJr"rrrrrEHs zBaseRestParser._do_parsecCs6|dur|S|j}||||||||||dSr )r{rr )rrJr"rrrrrr5Osz!BaseRestParser._add_modeled_parsecCsi}|||||Sr )r5r6rrrrCWsz&BaseRestParser._do_modeled_error_parsecCsLi}|d}d|vr|d|d<|Sd|vr$|d|d<|dd|d<|S)Nr7rrx-amz-request-id x-amz-id-2r HostId)rG)rrJrOr7rrrr4\s  z*BaseRestParser._populate_response_metadatac Csd|jvrK|jd}||}|jdr |||}|||<dS|jdvr:|d}t|tr4||j}|||<dS||d}| ||||<dS||d}| ||} | | dS)Nr.r:)rrr8) rFrGrtrdrHbytesrrr rhr) rrJr"rrpayload_member_name body_shaper8rrrrrr is$           zBaseRestParser._parse_payloadc Cs|d}|D]F}||}|jd}|durq|dkr&|||d||<q|dkr3|||||<q|dkrL|jd|} | |vrL|||| ||<qdS)Nr7r statusCoder9headerrs)rFrGrh_parse_header_map) rrJr"rrr7rsrkr header_namerrrrs,   z'BaseRestParser._parse_non_payload_attrscCsNi}|jdd}|D]}||r$|t|d}||||<q |S)Nrsr )rFrGlowerrQrz)rr"r7rKprefixr@rsrrrr?s z BaseRestParser._parse_header_mapcCrrrrrrrr rz"BaseRestParser._initial_body_parsecCs,|}t|rt||j}t|}|Sr )r r3r4rrrr)rr"r6rKdecodedrrrrs  zBaseRestParser._handle_stringcsD|jd}|dkrt|tsdd|dD}tt|||S)Nrr>cSsg|]}|qSr)rP).0rrrr sz/BaseRestParser._handle_list..,)rFrGrHrvrrr3rm)rr"rfrrrrrms zBaseRestParser._handle_list)rrrrEr5rCr4r rr?r rrmrrrrrr3Fs  r3cs0eZdZeZddZfddZddZZS)RestJSONParsercCrr rrrrrr rz"RestJSONParser._initial_body_parsecs"tt|||}||||Sr )rrGrD_inject_error_code)rrJr"rrrrrDs zRestJSONParser._do_error_parsecCsx||d}d|dvr"|dd}|dd}||dd<dSd|vs*d|vr:|d|dd |dd<dSdS) Nr8zx-amzn-errortyper7rrrVrSrr )r rrG)rrrJr8rrrrrHs   z!RestJSONParser._inject_error_code) rrrrr/r rDrHrrrrrrGs  rGcsDeZdZeZddZddZddZddZe fd d Z Z S) RestXMLParsercCr#rr$r&rrrr r'z!RestXMLParser._initial_body_parsecCs@|drz||WStytjdddYnw||S)Nr8z2Exception caught when parsing error response body:T)exc_info)_parse_error_from_bodyr(r>r?_parse_error_from_http_statusr`rrrrDs    zRestXMLParser._do_error_parsecCsHt|dtjjj|ddd|ddd|dddddS) Nr9r rRr7r7r8)rr9rU)rWrrXrYrZrGr[rrrrLs  z+RestXMLParser._parse_error_from_http_statuscCs|d}||}||}|||jdkr.||}|dd|dd||dSd|vr;d|di|d<ddddi}t|||S) Nr8rVrr r9rUr;r)rrrr~r4rr)rrJrrrKrOdefaultrrrrKs         z$RestXMLParser._parse_error_from_bodycstt|||}|Sr )rrIrrrrrrszRestXMLParser._handle_string) rrrr"r/r rDrLrKr'rrrrrrrIs rI)ec2queryrz rest-jsonzrest-xml)(rrr3rloggingbotocore.compatrrrbotocore.eventstreamrrbotocore.utilsrrr r getLoggerrr>r*objectr rr' Exceptionr(r)rrrrrrr"r(r3rGrIrrrrrsD h 0-5%XN'rN