B ݁[@szdZddlZddlZddlZddlZddlZddlmZm Z ddl m Z ddl m Z mZmZmZeeZe ZGdddeZdd Zd d ZGd d d eZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZ GdddeZ!Gddde!eZ"Gddde!eZ#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)six XMLParseError) EventStream)parse_timestamp merge_dictsis_json_value_headerlowercase_dictc@s$eZdZddZddZddZdS)ResponseParserFactorycCs i|_dS)N) _defaults)selfr Q/Users/kashii/Desktop/Projects/Workshops/worker-safety/lambda/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 timetsamp string * blob_parser - A callable that can parse a blob type N)r update)r kwargsr r r set_parser_defaultss z)ResponseParserFactory.set_parser_defaultscCst|}|f|jS)N)PROTOCOL_PARSERSr )r protocol_nameZ parser_clsr r r create_parsersz#ResponseParserFactory.create_parserN)__name__ __module__ __qualname__rrrr r r r r s r cCs t|S)N)r r)protocolr r r rsrcsfdd}|S)Ncs.t|dr|j}|dkr"d}n|}|||S)Ntext)hasattrr)r shapeZnode_or_stringr)funcr r _get_text_contents  z(_text_content.._get_text_contentr )rrr )rr _text_contents rc@s eZdZdS)ResponseParserErrorN)rrrr r r r r sr c@sjeZdZdZdZdZdddZddZdd Zd d Z d d Z ddZ ddZ ddZ ddZddZdS)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 r rs zResponseParser.__init__cCs t|S)N)base64 b64decode)r valuer r r r$sz#ResponseParser._default_blob_parsercCstd|dtd|d|ddkrP||rB||}q\|||}n |||}|rp|jdrp|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- eventstreamResponseMetadataHTTPStatusCode HTTPHeaders) LOGdebug_is_generic_error_response_do_generic_error_parse_do_error_parse _do_parse serializationget isinstancedictr)r responserparsedresponse_metadatar-r r r parses         zResponseParser.parsecCsD|ddkr@d|ks |ddkr$dS|d}|dp>| SdS)Nr/ir.Ts)strip startswith)r r>r.r r r r6s  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.r/r)CodeMessage)Errorr1)r4r5strrmoves http_client responsesr;)r r>r r r r7s    z&ResponseParser._do_generic_error_parsecCstd|jjdS)Nz %s._do_parse)NotImplementedError __class__r)r r>rr r r r9$szResponseParser._do_parsecCstd|jjdS)Nz%s._do_error_parse)rKrLr)r r>rr r r r8'szResponseParser._do_error_parsecCst|d|j|j}|||S)Nz _handle_%s)getattr type_name_default_handle)r rnodehandlerr r r _parse_shape+s zResponseParser._parse_shapecCs.g}|j}x|D]}||||qW|S)N)memberappendrR)r rrPr? member_shapeitemr r r _handle_list0s  zResponseParser._handle_listcCs|S)Nr )r rr,r r r rO9szResponseParser._default_handle)NN)rrr__doc__DEFAULT_ENCODINGr'rr$rAr6r7r9r8rRrWrOr r r r r!s  ,  r!cseZdZd fdd ZddZddZfdd Zd d Zd d ZddZ ddZ ddZ e ddZ e ddZe ddZe ddZe ddZe ddZeZeZeZZS)!BaseXMLResponseParserNcs"tt|||td|_dS)Nz{.*})superrZrrecompile _namespace_re)r r(r))rLr r r>s zBaseXMLResponseParser.__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)Nnamekeyr, flattenedzUnknown tag: %s) r`r,r:r;r<list _node_tagrRr ) r rrPr? key_shape value_shapeZkey_location_nameZvalue_location_nameZ keyval_nodeZ single_pairZtag_namekey_nameval_namer r r _handle_mapCs"    z!BaseXMLResponseParser._handle_mapcCs|jd|jS)Nr)r^subtag)r rPr r r rcXszBaseXMLResponseParser._node_tagcs.|jdrt|ts|g}tt|||S)Nra)r:r;r<rbr[rZrW)r rrP)rLr r rW[sz"BaseXMLResponseParser._handle_listcCsi}|j}||}x|D]}||}d|jks|jdr>q|||}||} | dk rn||| ||<q|jdri} |jd} x:|jD],\} } |j | ddd| }| | |<qW| | kr| | ||<qW|S)Nlocation eventheader xmlAttributer_:r) members_build_name_to_xml_noder:r;_member_key_namerRattribitemsr^risplit)r rrPr?roxml_dict member_namerUZxml_nameZ member_nodeZattribsZ location_namer`r,Znew_keyr r r _handle_structurees.         z'BaseXMLResponseParser._handle_structurecCsL|jdkr0|jdr0|jjd}|dk r0|S|jd}|dk rH|S|S)Nrbrar_)rNr:r;rS)r rrvZlist_member_serialized_nameZserialized_namer r r rqs z&BaseXMLResponseParser._member_key_namecCsxt|tr||dSi}xV|D]N}||}||krht||trV|||qp|||g||<q"|||<q"W|S)Nr)r<rbrprcrT)r Z parent_noderurVr`r r r rps    z-BaseXMLResponseParser._build_name_to_xml_nodec Csjy2tjjjtjj|jd}|||}Wn2tk rd}zt d||fWdd}~XYnX|S)N)targetencodingz7Unable to parse response (%s), invalid XML received: %s) xmletree cElementTree XMLParser TreeBuilderrYfeedcloserr )r xml_stringparserrooter r r _parse_xml_string_to_doms    z.BaseXMLResponseParser._parse_xml_string_to_domcCsFx@|D]4\}}t|r4||}||||<q |j||<q W|S)N)rsrbrp_replace_nodesr)r r?r`r,Zsub_dictr r r rs  z$BaseXMLResponseParser._replace_nodescCs|dkr dSdSdS)NtrueTFr )r rrr r r _handle_booleansz%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_blobsz"BaseXMLResponseParser._handle_blob)NN)rrrrrhrcrWrwrqrprrrrrrrrrZ_handle_characterZ_handle_doubleZ _handle_long __classcell__r r )rLr rZ=s$        rZc@s,eZdZddZddZddZddZd S) QueryParsercCs\|d}||}||}||d|kr>||dd|krXd|di|d<|S)Nr.ZErrors RequestIdr1)rrprrpop)r r>r xml_contentsrr?r r r r8s   zQueryParser._do_error_parsecCsZ|d}||}i}|dk rJ|}d|jkr>||jd|}|||}||||S)Nr. resultWrapper)rr:_find_result_wrapped_shaperR_inject_response_metadata)r r>rrrr?startr r r r9s    zQueryParser._do_parsecCs||}||S)N)rp)r element_nameZ xml_root_nodemappingr r r rs z&QueryParser._find_result_wrapped_shapecCsR||}|d}|dk rN||}x|D]\}}|j||<q0W||d<dS)Nr1)rpr;rsr)r rP inject_intor child_nodeZ sub_mappingr`r,r r r rs   z%QueryParser._inject_response_metadataN)rrrr8r9rrr r r r rsrcs$eZdZddZfddZZS)EC2QueryParsercCs.||}|d}|dk r*d|ji|d<dS)NZ requestIdrr1)rpr;r)r rPrrrr r r r s  z(EC2QueryParser._inject_response_metadatacs(tt|||}d|di|d<|S)NrZ RequestIDr1)r[rr8r)r r>roriginal)rLr r r8s zEC2QueryParser._do_error_parse)rrrrr8rr r )rLr r src@sDeZdZddZddZddZddZd d Zd d Zd dZ dS)BaseJSONParserc Csd|j}|dkrdSi}xH|D]@}||}|jd|}||}|dk r||||||<qW|S)Nr_)ror:r;rR) r rr, member_shapes final_parsedrvrUZ json_name raw_valuer r r rw(s  z BaseJSONParser._handle_structurec CsJi}|j}|j}x4|D](\}}|||}|||}|||<qW|S)N)r`r,rsrR) r rr,r?rdrer` actual_key actual_valuer r r rh:s   zBaseJSONParser._handle_mapcCs ||S)N)r%)r rr,r r r rDszBaseJSONParser._handle_blobcCs ||S)N)r#)r rr,r r r rGsz BaseJSONParser._handle_timestampcCs||d}dddid}|d|dd|dd<|d}|d |oTt|}|dk rd |krx|d d d }||dd <|||d |S)Nr.r)rErD)rFr1messagerErFr/Z__type#rDr-)_parse_body_as_jsonr;rGrsplitr)r r>rr.errorZ response_codecoder r r r8Js   zBaseJSONParser._do_error_parsecCs d|kr|d|did<dS)Nzx-amzn-requestidr1r) setdefault)r r?r-r r r resz(BaseJSONParser._inject_response_metadatacCs@|siS||j}yt|}|Stk r:d|iSXdS)Nr)decoderYjsonloads ValueError)r body_contentsr.original_parsedr r r rjs  z"BaseJSONParser._parse_body_as_jsonN) rrrrwrhrrr8rrr r r r r&s rc@seZdZdZddZdS) JSONParserz'Response parse for the "json" protocol.cCs:i}|dk r&||d}|||}|||d|S)Nr.r-)rrRr)r r>rr?rr r r r9ys  zJSONParser._do_parseN)rrrrXr9r r r r rwsrc@s4eZdZddZddZddZddZd d Zd S) BaseEventStreamParsercCshi}|jdr@|dd}|j|}|rd|||||<n$||||j|||||j||S)Nr0r-z :event-type)r:r;ror9_parse_non_payload_attrs_parse_payload)r r>rr event_typeZ event_shaper r r r9s   zBaseEventStreamParser._do_parsecCs*d|ddd|ddddi}|S)NrFr-z :error-coderz:error-message)rDrE)r;)r r>rrr r r r8sz%BaseEventStreamParser._do_error_parsec Cs|jdrxr|D]j}||}|jdr|d}|jdkrB|}n.|jdkrZ||j}n||} ||| }|||<dSqW||d} ||| } || dS)Nevent eventpayloadr.blobstring)r:r;rNrrY_initial_body_parserRr) r r>rrrr_rUr.Z parsed_bodyZ raw_parser body_parsedr r r rs         z$BaseEventStreamParser._parse_payloadc Cs^|d}xP|D]H}||}|jdr||kr||}|jdkrN||d}|||<qWdS)Nr-rl timestampg@@)r:r;rNr#) r r>rrrr-r_rUr,r r r rs   z.BaseEventStreamParser._parse_non_payload_attrscCs tddS)Nr)rK)r rr r r rsz)BaseEventStreamParser._initial_body_parseN)rrrr9r8rrrr r r r rs   rc@seZdZddZdS)EventStreamJSONParsercCs ||S)N)r)r rr r r rsz)EventStreamJSONParser._initial_body_parseN)rrrrr r r r rsrc@seZdZddZdS)EventStreamXMLParsercCs|stjjdS||S)Nr)rzr{r|Elementr)r rr r r rsz(EventStreamXMLParser._initial_body_parseN)rrrrr r r r rsrc@sDeZdZddZddZddZddZd d Zd d Zd dZ dS)BaseRestParsercCsHi}|||d<|dkr|S|j}|||||||||||S)Nr1)_populate_response_metadatarorr)r r>rrrr r r r9s zBaseRestParser._do_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>metadatar-r r r rs z*BaseRestParser._populate_response_metadatac Csd|jkr|jd}||}|jdrX|j}|dd}t|d|||} | ||<q|jdkr|d} t| tr| |j} | ||<q| |d} | || ||<n$| |d} | || } | | dS)Npayloadr0contextoperation_namer.)rr) r:r;r&rrNr<bytesrrYrrRr) r r>rrrZpayload_member_nameZ body_shaperr_r.rrr r r rs&         zBaseRestParser._parse_payloadc Cs|d}x|D]}||}|jd}|dkr2qq|dkrP|||d||<q|dkrj|||||<q|dkr|jd|} | |kr|||| ||<qWdS)Nr-rk statusCoder/headerr_)r:r;rR_parse_header_map) r r>rrrr-r_rUrk header_namer r r r s"   z'BaseRestParser._parse_non_payload_attrscCsRi}|jdd}x6|D].}||r|t|d}||||<qW|S)Nr_r)r:r;lowerrClen)r rr-r?prefixrr_r r r rs z BaseRestParser._parse_header_mapcCs tddS)Nr)rK)r rr r r r+sz"BaseRestParser._initial_body_parsecCs,|}t|r(t||j}t|}|S)N)rr*r+rrYrr)r rr,r?decodedr r r r2s  zBaseRestParser._handle_stringN) rrrr9rrrrrrr r r r rs   rcs0eZdZeZddZfddZddZZS)RestJSONParsercCs ||S)N)r)r rr r r r>sz"RestJSONParser._initial_body_parsecs"tt|||}||||S)N)r[rr8_inject_error_code)r r>rr)rLr r r8As zRestJSONParser._do_error_parsecCsr||d}d|dkrB|dd}|dd}||dd<n,d|ksRd|krn|d|dd |dd<dS) Nr.zx-amzn-errortyper-rnrrFrDrr)rrtr;)r rr>r.rr r r rFs  z!RestJSONParser._inject_error_code) rrrrr'rr8rrr r )rLr r:s rcsDeZdZeZddZddZddZddZe fd d Z Z S) RestXMLParsercCs|stjjdS||S)Nr)rzr{r|rr)r rr r r rYsz!RestXMLParser._initial_body_parsec CsN|drDy ||Stk rB}ztjdddWdd}~XYnX||S)Nr.z2Exception caught when parsing error response body:T)exc_info)_parse_error_from_bodyr r4r5_parse_error_from_http_status)r r>rrr r r r8^s zRestXMLParser._do_error_parsecCsHt|dtjjj|ddd|ddd|dddddS) Nr/r)rDrEr-zx-amz-request-idz x-amz-id-2)rr)rFr1)rGrrHrIrJr;)r r>r r r rxs   z+RestXMLParser._parse_error_from_http_statuscCs|d}||}||}|||jdkr\||}|dd|dd||dSd|krvd|di|d<ddddi}t|||S) Nr.rFrrr)rFr1r1)rErD)rrprrjrrr)r r>rrr?rdefaultr r r rs         z$RestXMLParser._parse_error_from_bodycstt|||}|S)N)r[rr)r rr)rLr r rszRestXMLParser._handle_string) rrrrr'rr8rrrrrr r )rLr rUs  r)ec2queryrz rest-jsonzrest-xml)(rXr\r*rxml.etree.cElementTreerzloggingbotocore.compatrrZbotocore.eventstreamrbotocore.utilsrrrr getLoggerrr4r"objectr rr Exceptionr r!rZrrrrrrrrrrrr r r r tsB   .QBeN