9(Zc@sdZddlZddlZddlZddlZddlZddlmZm Z ddl m Z m Z m Z ejeZe ZdefdYZdZdZd efd YZd efd YZd efdYZdefdYZdefdYZdefdYZdefdYZdefdYZdeefdYZdeefdYZ ied6ed6ed6ed 6e d!6Z!dS("s9 Response 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. 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(tparse_timestampt merge_dictstis_json_value_headertResponseParserFactorycBs#eZdZdZdZRS(cCs i|_dS(N(t _defaults(tself((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyt__init__nscKs|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(Rtupdate(Rtkwargs((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pytset_parser_defaultsqs cCst|}||jS(N(tPROTOCOL_PARSERSR(Rt protocol_namet parser_cls((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyt create_parser}s (t__name__t __module__RR R(((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRms  cCstj|S(N(RR(tprotocol((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRscsfd}|S(NcsFt|dr0|j}|dkr6d}q6n|}|||S(Nttextt(thasattrRtNone(Rtshapetnode_or_stringR(tfunc(s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyt_get_text_contents    ((RR((Rs2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyt _text_contents tResponseParserErrorcBseZRS((RR(((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRstResponseParsercBsteZdZdZd d dZdZdZdZdZ dZ dZ d Z d Z d 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-8cCsC|dkrt}n||_|dkr6|j}n||_dS(N(RtDEFAULT_TIMESTAMP_PARSERt_timestamp_parsert_default_blob_parsert _blob_parser(Rttimestamp_parsert blob_parser((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRs      cCs tj|S(N(tbase64t b64decode(Rtvalue((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyR scCstjd|dtjd|d|ddkrn|j|rY|j|}q|j||}n|j||}t|tr|jdi}|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-tResponseMetadatatHTTPStatusCodet HTTPHeaders( tLOGtdebugt_is_generic_error_responset_do_generic_error_parset_do_error_parset _do_parset isinstancetdicttget(RtresponseRtparsedtresponse_metadata((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pytparses cCs8|ddkr4|dj}|jdp3| SdS(NR)iR(s(tstript startswith(RR6R(((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyR/s cCsPtjdiit|dd6tjjjj|ddd6d6id6S(NslReceived a non protocol specific error response from the service, unable to populate error code and message.R)tCodeRtMessagetErrorR*(R-R.tstrRtmovest http_clientt responsesR5(RR6((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyR0s  cCstd|jjdS(Ns %s._do_parse(tNotImplementedErrort __class__R(RR6R((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyR2scCstd|jjdS(Ns%s._do_error_parse(RCRDR(RR6R((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyR1scCs)t|d|j|j}|||S(Ns _handle_%s(tgetattrt type_namet_default_handle(RRtnodethandler((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyt _parse_shapes cCs=g}|j}x'|D]}|j|j||qW|S(N(tmembertappendRJ(RRRHR7t member_shapetitem((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyt _handle_lists   cCs|S(N((RRR&((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRGsN(RRt__doc__tDEFAULT_ENCODINGRRR R9R/R0R2R1RJRORG(((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRs   $     tBaseXMLResponseParsercBseZdddZdZdZdZdZdZdZ dZ dZ e d Z e d Ze d Ze d Ze d Ze dZeZeZeZRS(cCs/tt|j||tjd|_dS(Ns{.*}(tsuperRRRtretcompilet _namespace_re(RR"R#((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRsc Csi}|j}|j}|jjdp-d}|jjdpEd}|jjdrvt|t rv|g}nx|D]}xo|D]g} |j| } | |kr|j|| } q| |kr|j|| } qtd| qW| || R*tmessageR)t__typet#iR'(t_parse_body_as_jsonR5R?RtrsplitR(RR6RR(terrort response_codetcode((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyR1 s"   cCs-d|kr)|d|jdidR<RR(RRqR5(RRR6R(R((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRs(RRRR1R(((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRs  t RestXMLParsercBs;eZdZdZdZdZedZRS(cCs&|stjjjdS|j|S(NR(RRRtElementR(RR((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRscCsT|drGy|j|SWqGtk rC}tjddtqGXn|j|S(NR(s2Exception caught when parsing error response body:texc_info(t_parse_error_from_bodyRR-R.Rt_parse_error_from_http_status(RR6RR((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyR1s cCsqiit|dd6tjjjj|ddd6d6i|djddd6|djd dd 6d 6S( NR)R<RR=R>R'sx-amz-request-idRs x-amz-id-2RR*(R?RR@RARBR5(RR6((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRscCs|d}|j|}|j|}|j||jdkr|j|}|jdd|jddi|d6|d6Sd|kri|jdd6|dRRRR*R=R<(RRmRRhRRR(RR6RRR7Rtdefault((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRs    cCstt|j||}|S(N(RSRR(RRR((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRs(RRRR1RRRR(((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyRs    tec2tqueryRs rest-jsonsrest-xml("RPRTR$Rtxml.etree.cElementTreeRtloggingtbotocore.compatRRtbotocore.utilsRRRt getLoggerRR-RtobjectRRRt ExceptionRRRRRRRRRRRR (((s2/tmp/pip-build-wDUJoH/botocore/botocore/parsers.pyt\s8       v.Q`K