B ㊇c%@szdZddlZddlZddlZddlZddlZddlmZm Z ddl m Z m Z ddl mZmZmZmZeeZeZGdddZdd Zd d ZGd d d eZGdddZGdddeZGdddeZGdddeZGdddeZGdddeZ 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)ETree XMLParseError) EventStreamNoInitialResponseError)is_json_value_headerlowercase_dict merge_dictsparse_timestampc@s$eZdZddZddZddZdS)ResponseParserFactorycCs i|_dS)N) _defaults)selfr k/private/var/folders/8c/hx9_v10d5x38qmnzt13b7b8j1k3n5b/T/pip-target-x6xd5gna/lib/python/botocore/parsers.py__init__szResponseParserFactory.__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)r kwargsr r rset_parser_defaultss z)ResponseParserFactory.set_parser_defaultscCst|}|f|jS)N)PROTOCOL_PARSERSr )r Z protocol_nameZ parser_clsr r r create_parsersz#ResponseParserFactory.create_parserN)__name__ __module__ __qualname__rrrr r r rr s r cCs t|S)N)r r)protocolr r rrsrcsfdd}|S)Ncs.t|dr|j}|dkr"d}n|}|||S)Ntext)hasattrr)r shapenode_or_stringr)funcr r_get_text_contents  z(_text_content.._get_text_contentr )rrr )rr _text_contents r c@s eZdZdS)ResponseParserErrorN)rrrr r r rr!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-8NcCsH|dkr t}||_|dkr |j}||_d|_|jdk rD||||_dS)N)DEFAULT_TIMESTAMP_PARSER_timestamp_parser_default_blob_parser _blob_parser_event_stream_parserEVENT_STREAM_PARSER_CLS)r timestamp_parser blob_parserr r rrs zResponseParser.__init__cCs t|S)N)base64 b64decode)r valuer r rr%sz#ResponseParser._default_blob_parsercCstd|dtd|d|ddkrj||rB||}qv||r\|||}|S|||}n |||}|r|j dr|St |t r| 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)r responserparsedresponse_metadatar.r r rparses(           zResponseParser.parsecCs.|didi}|d}|r*||d<dS)NcontextZchecksumZresponse_algorithmZChecksumAlgorithm)r<)r r@rBZchecksum_context algorithmr r rr?s z.ResponseParser._add_checksum_response_metadatacCs|dk o|jddS)N exceptionF)metadatar<)r rr r rr7sz&ResponseParser._is_modeled_error_shapecCsD|ddkr@d|ks |ddkr$dS|d}|dp>| SdS)Nr0ir/Ts)strip startswith)r r@r/r r rr5s  z)ResponseParser._is_generic_error_responsecCs2tdt|dtjj|dddidS)NzlReceived a non protocol specific error response from the service, unable to populate error code and message.r0r)CodeMessage)Errorr2)r3r4strhttpclient responsesr<)r r@r r rr6,s  z&ResponseParser._do_generic_error_parsecCstd|jjdS)Nz %s._do_parse)NotImplementedError __class__r)r r@rr r rr:=szResponseParser._do_parsecCst|jjddS)Nz._do_error_parse)rQrRr)r r@rr r rr9@szResponseParser._do_error_parsecCst|jjddS)Nz._do_modeled_error_parse)rQrRr)r r@rrAr r rr8Csz&ResponseParser._do_modeled_error_parsecCs t|d|j|j}|||S)NZ_handle_)getattr type_name_default_handle)r rnodehandlerr r r _parse_shapeHszResponseParser._parse_shapecCs.g}|j}x|D]}||||qW|S)N)memberappendrX)r rrVrA member_shapeitemr r r _handle_listNs  zResponseParser._handle_listcCs|S)Nr )r rr-r r rrUWszResponseParser._default_handlecCs&|j}|dd}t|d|||S)NrDZoperation_namer/)r'r<r)r r@rparsernamer r r_create_event_streamZsz#ResponseParser._create_event_streamcCs t|dS)Nr)list)r r-r r r_get_first_key_szResponseParser._get_first_keycCsR|jrNt|dkr$d}t||j||}||jkrNd}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!r_rbmembersr3info)r rr- error_msgtagmsgr r r _has_unknown_tagged_union_memberbs   z/ResponseParser._has_unknown_tagged_union_membercCs dd|iiS)NZSDK_UNKNOWN_MEMBERr_r )r rhr r r#_handle_unknown_tagged_union_memberusz2ResponseParser._handle_unknown_tagged_union_member)NN)rrr__doc__DEFAULT_ENCODINGr(rr%rCr?r7r5r6r:r9r8rXr]rUr`rbrjrkr r r rr"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_re)r r)r*)rRr rrzszBaseXMLResponseParser.__init__c Csi}|j}|j}|jdpd}|jdp.d}|jdrLt|tsL|g}xd|D]\}xN|D]F} || } | |kr||| } q\| |kr||| } q\td| q\W| || <qRW|S)Nr_keyr- flattenedzUnknown tag: %s) rsr-r;r<r=ra _node_tagrXr!) r rrVrA key_shape value_shapeZkey_location_nameZvalue_location_nameZ keyval_nodeZ single_pairZtag_nameZkey_nameval_namer r r _handle_map~s"    z!BaseXMLResponseParser._handle_mapcCs|jd|jS)Nr)rrsubrh)r rVr r rruszBaseXMLResponseParser._node_tagcs*|jdrt|ts|g}t||S)Nrt)r;r<r=raror])r rrV)rRr rr]sz"BaseXMLResponseParser._handle_listcCsi}|j}|jddr"||}||}|||rL||}||Sx|D]}||}d|jksR|jdrvqR| ||} || } | dk r| || ||<qR|jdrRi} |jd} x:|j D],\} }|j | ddd| }|| |<qW| | krR| | ||<qRW|S) NrFFlocation eventheaderZ xmlAttributer_:r)rerGr<_get_error_root_build_name_to_xml_noderjrbrkr;_member_key_namerXattribitemsrrrzsplit)r rrVrArexml_dictrh member_namer[Zxml_nameZ member_nodeattribsZ location_namersr-Znew_keyr r r_handle_structures8             z'BaseXMLResponseParser._handle_structurecCs2||dkr.x|D]}||dkr|SqW|S)NZ ErrorResponserL)ru)r original_rootchildr r rr~s  z%BaseXMLResponseParser._get_error_rootcCsL|jdkr0|jdr0|jjd}|dk r0|S|jd}|dk rH|S|S)Nrartr_)rTr;r<rY)r rrZlist_member_serialized_nameZserialized_namer r rrs z&BaseXMLResponseParser._member_key_namecCsxt|tr||dSi}xV|D]N}||}||krht||trV|||qp|||g||<q"|||<q"W|S)Nr)r=rarrurZ)r Z parent_noderr\rsr r rrs    z-BaseXMLResponseParser._build_name_to_xml_nodec Csby*tjt|jd}|||}Wn2tk r\}ztd||fWdd}~XYnX|S)N)targetencodingzTUnable to parse response (%s), invalid XML received. Further retries may succeed: %s)rZ XMLParserZ TreeBuilderrmfeedcloserr!)r xml_stringr^rooter r r_parse_xml_string_to_doms  z.BaseXMLResponseParser._parse_xml_string_to_domcCsFx@|D]4\}}t|r4||}||||<q |j||<q W|S)N)rrar_replace_nodesr)r rArsr-Zsub_dictr r rrs  z$BaseXMLResponseParser._replace_nodescCs|dkr dSdSdS)NtrueTFr )r rrr r r_handle_boolean sz%BaseXMLResponseParser._handle_booleancCst|S)N)float)r rrr r r _handle_floatsz#BaseXMLResponseParser._handle_floatcCs ||S)N)r$)r rrr r r_handle_timestampsz'BaseXMLResponseParser._handle_timestampcCst|S)N)int)r rrr r r_handle_integersz%BaseXMLResponseParser._handle_integercCs|S)Nr )r rrr r r_handle_stringsz$BaseXMLResponseParser._handle_stringcCs ||S)N)r&)r rrr r r _handle_blob!sz"BaseXMLResponseParser._handle_blob)NN)rrrrryrur]rr~rrrrr rrrrrrZ_handle_characterZ_handle_double _handle_long __classcell__r r )rRrrnys& $      rnc@s>eZdZddZddZddZddd Zd d Zd d ZdS) QueryParsercCs\|d}||}||}||d|kr>||dd|krXd|di|d<|S)Nr/Errors RequestIdr2)rrrrpop)r r@r xml_contentsrrAr r rr9+s   zQueryParser._do_error_parsecCs|j||ddS)NF)inject_metadata)_parse_body_as_xml)r r@rr r rr8;sz#QueryParser._do_modeled_error_parsecCs|j||ddS)NT)r)r)r r@rr r rr:>szQueryParser._do_parseTcCs^|d}||}i}|dk rJ|}d|jkr>||jd|}|||}|rZ||||S)Nr/Z resultWrapper)rr;_find_result_wrapped_shaperX_inject_response_metadata)r r@rrrrrAstartr r rrAs    zQueryParser._parse_body_as_xmlcCs||}||S)N)r)r Z element_nameZ xml_root_nodemappingr r rrPs z&QueryParser._find_result_wrapped_shapecCsR||}|d}|dk rN||}x|D]\}}|j||<q0W||d<dS)Nr2)rr<rr)r rV inject_intor child_nodeZ sub_mappingrsr-r r rrTs   z%QueryParser._inject_response_metadataN)T) rrrr9r8r:rrrr r r rr*s  rcs,eZdZddZfddZddZZS)EC2QueryParsercCs.||}|d}|dk r*d|ji|d<dS)NZ requestIdrr2)rr<r)r rVrrrr r rr_s  z(EC2QueryParser._inject_response_metadatacs,t||}d|kr(d|di|d<|S)NZ RequestIDrr2)ror9r)r r@roriginal)rRr rr9es zEC2QueryParser._do_error_parsecCs@x:|D]2}||dkrx|D]}||dkr|SqWqW|S)NrrL)ru)r rrZ errors_childr r rr~ys    zEC2QueryParser._get_error_root)rrrrr9r~rr r )rRrr^s rc@sDeZdZddZddZddZddZd d Zd d Zd dZ dS)BaseJSONParserc Csi}|jr|}n|j}|dkr"dSi}|||rF||}||SxH|D]@}||}|jd|}||} | dk rL|||| ||<qLW|S)Nr_)Zis_document_typererjrbrkr;r<rX) r rr- final_parsed member_shapesrhrr[ json_nameZ raw_valuer r rrs$     z BaseJSONParser._handle_structurec CsJi}|j}|j}x4|D](\}}|||}|||}|||<qW|S)N)rsr-rrX) r rr-rArvrwrsZ actual_keyZ actual_valuer r rrys   zBaseJSONParser._handle_mapcCs ||S)N)r&)r rr-r r rrszBaseJSONParser._handle_blobcCs ||S)N)r$)r rr-r r rrsz BaseJSONParser._handle_timestampc Cs||d}dddid}|d}|d|dd|dd<|d }|d d}|d }d} t|d kr|d r|d } | dkr|d|ot|} | dk rd| kr| ddd} | |dd<|||d|S)Nr/r)rKrJ)rLr2r.messagerKrLr0zx-amzn-query-error;rZ__type#rcrJ)_parse_body_as_jsonr<rrdrMrsplitr) r r@rr/errorr.Z response_codeZ query_errorZquery_error_componentscoder r rr9s&     zBaseJSONParser._do_error_parsecCs d|kr|d|did<dS)Nzx-amzn-requestidr2r) setdefault)r rAr.r r rrsz(BaseJSONParser._inject_response_metadatacCs@|siS||j}yt|}|Stk r:d|iSXdS)Nr)decodermjsonloads ValueError)r body_contentsr/original_parsedr r rrs  z"BaseJSONParser._parse_body_as_jsonN) rrrrryrrr9rrr r r rrs %rc@s4eZdZddZddZddZddZd d Zd S) BaseEventStreamParsercCshi}|jdr@|dd}|j|}|rd|||||<n$||||j|||||j||S)Nr1r.z :event-type)r;r<rer:_parse_non_payload_attrs_parse_payload)r r@rrZ event_typeZ event_shaper r rr:s  zBaseEventStreamParser._do_parsec Cs|dd}|j|}|dk r\||d}|||}d||d|dddi}n&d|dd d|dd ddi}|S) Nr.z:exception-typer/rLrKrr)rJrKz :error-codez:error-message)r<re_initial_body_parserX)r r@rZexception_typeZexception_shaperr/rr r rr9s  z%BaseEventStreamParser._do_error_parsec Cs|jdrxr|D]j}||}|jdr|d}|jdkrB|}n.|jdkrZ||j}n||} ||| }|||<dSqW||d} ||| } || dS)NeventZ eventpayloadr/blobstring)r;r<rTrrmrrXr) r r@rrrr_r[r/Z parsed_bodyZ raw_parser body_parsedr r rr s"       z$BaseEventStreamParser._parse_payloadc Cs^|d}xP|D]H}||}|jdr||kr||}|jdkrN||d}|||<qWdS)Nr.r| timestampg@@)r;r<rTr$) r r@rrrr.r_r[r-r r rr s   z.BaseEventStreamParser._parse_non_payload_attrscCs tddS)Nr)rQ)r rr r rr/sz)BaseEventStreamParser._initial_body_parseN)rrrr:r9rrrr r r rrs rc@seZdZddZdS)EventStreamJSONParsercCs ||S)N)r)r rr r rr8sz)EventStreamJSONParser._initial_body_parseN)rrrrr r r rr7src@seZdZddZdS)EventStreamXMLParsercCs|stdS||S)Nr)rElementr)r rr r rr=s z(EventStreamXMLParser._initial_body_parseN)rrrrr r r rr<src@s0eZdZeZddZddZddZddZd S) JSONParsercCsJi}|dk r6|j}|r&||||}n||d|}|||d|S)Nr/r.)Zevent_stream_name_handle_event_stream_handle_json_bodyr)r r@rrA event_namer r rr:IszJSONParser._do_parsecCs||d|S)Nr/)r)r r@rr r rr8Tsz"JSONParser._do_modeled_error_parsec Cs^|j|}|||}y |}Wn tk rBd}t|YnX||j|}|||<|S)Nz,First event was not of type initial-response)rer`Zget_initial_responserr!rpayload) r r@rrZevent_stream_shapeZ event_streamrrgrAr r rrWs   zJSONParser._handle_event_streamcCs||}|||S)N)rrX)r Zraw_bodyrZ parsed_jsonr r rrcs zJSONParser._handle_json_bodyN) rrrrr(r:r8rrr r r rrCs   rcsdeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ fddZ Z S)BaseRestParsercCs$i}|||d<|||||S)Nr2)_populate_response_metadata_add_modeled_parse)r r@rrr r rr:ls  zBaseRestParser._do_parsecCs6|dkr |S|j}||||||||||dS)N)rerr)r r@rrrr r rrts  z!BaseRestParser._add_modeled_parsecCsi}|||||S)N)r)r r@rrr r rr8}sz&BaseRestParser._do_modeled_error_parsecCsJi}|d}d|kr"|d|d<n$d|krF|d|d<|dd|d<|S)Nr.zx-amzn-requestidrzx-amz-request-idz x-amz-id-2rHostId)r<)r r@rGr.r r rrs z*BaseRestParser._populate_response_metadatac Csd|jkr|jd}||}|jdr>|||}|||<q|jdkrp|d}t|trf||j}|||<q||d}| ||||<n$||d}| ||} | | dS)Nrr1)rrr/) r;r<r`rTr=bytesrrmrrXr) r r@rrrZpayload_member_nameZ body_shaper/rrr r rrs"          zBaseRestParser._parse_payloadc Cs|d}x|D]}||}|jd}|dkr2qq|dkrP|||d||<q|dkrj|||||<q|dkr|jd|} | |kr|||| ||<qWdS)Nr.r{Z statusCoder0headerr_)r;r<rX_parse_header_map) r r@rrrr.r_r[r{ header_namer r rrs"  z'BaseRestParser._parse_non_payload_attrscCsRi}|jdd}x6|D].}||r|t|d}||||<qW|S)Nr_r)r;r<lowerrIrd)r rr.rAprefixrr_r r rrs z BaseRestParser._parse_header_mapcCs tddS)Nr)rQ)r rr r rrsz"BaseRestParser._initial_body_parsecCs,|}t|r(t||j}t|}|S)N)rr+r,rrmrr)r rr-rAdecodedr r rrs  zBaseRestParser._handle_stringcs@|jd}|dkr2t|ts2dd|dD}t||S)Nr{rcSsg|] }|qSr )rH).0rr r r sz/BaseRestParser._handle_list..,)r;r<r=rarror])r rrVr{)rRr rr]s zBaseRestParser._handle_list)rrrr:rr8rrrrrrr]rr r )rRrrks   rcs<eZdZeZddZfddZddZddZeZ Z S) RestJSONParsercCs ||S)N)r)r rr r rrsz"RestJSONParser._initial_body_parsecst||}||||S)N)ror9_inject_error_code)r r@rr)rRr rr9s zRestJSONParser._do_error_parsecCsr||d}d|dkrB|dd}|dd}||dd<n,d|ksRd|krn|d|dd |dd<dS) Nr/zx-amzn-errortyper.r}rrLrJrr)rrr<)r rr@r/rr r rrs  z!RestJSONParser._inject_error_codecCst|S)N)r)r rr-r r rrszRestJSONParser._handle_integer) rrrrr(rr9rrrrr r )rRrrs   rcsDeZdZeZddZddZddZddZe fd d Z Z S) RestXMLParsercCs|stdS||S)Nr)rrr)r rr r rrs z!RestXMLParser._initial_body_parsecCs@|dr6y ||Stk r4tjdddYnX||S)Nr/z2Exception caught when parsing error response body:T)exc_info)_parse_error_from_bodyr!r3r4_parse_error_from_http_status)r r@rr r rr9 s zRestXMLParser._do_error_parsecCsFt|dtjj|ddd|ddd|dddddS) Nr0r)rJrKr.zx-amz-request-idz x-amz-id-2)rr)rLr2)rMrNrOrPr<)r r@r r rr&s  z+RestXMLParser._parse_error_from_http_statuscCs|d}||}||}|||jdkr\||}|dd|dd||dSd|krvd|di|d<ddddi}t|||S) Nr/rLrrr)rLr2r2)rKrJ)rrrrhrrr)r r@rrrArGdefaultr r rr4s         z$RestXMLParser._parse_error_from_bodycst||}|S)N)ror)r rr)rRr rrKszRestXMLParser._handle_string) rrrrr(rr9rrr rrr r )rRrrs r)Zec2queryrz rest-jsonzrest-xml)(rlr+ http.clientrNrloggingrpZbotocore.compatrrZbotocore.eventstreamrrZbotocore.utilsrrrr getLoggerrr3r#r rr Exceptionr!r"rnrrrrrrrrrrrr r r rtsB ?24$bS(xP