!;i dZddlmZdZddlZddlmZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZ ddlZejZn#e$r eZYnwxYwddlmZddlmZddlmZddlmZdd l m!Z!dd l m"Z#dd l$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*dd l+m,Z,e j-e.Z/d Z0dZ1dZ2dZ3dZ4dZ5dZ6dZ7GddeZ8GddeZ9GddeZ:Gdde:Z;Gdde;Z<Gdd e;Z=Gd!d"eZ>Gd#d$eZ?Gd%d&eZ@Gd'd(eZAGd)d*eZBGd+d,eZCGd-d.eZDGd/d0eZEd1ZFd2ZGd3ZHdS)4zClasses to encapsulate a single HTTP request. The classes implement a command pattern, with every object supporting an execute() method that does the actual HTTP request. )absolute_importz$jcgregorio@google.com (Joe Gregorio)N) Generator) MIMEMultipart)MIMENonMultipart) FeedParser)_auth)_helpers) BatchError HttpErrorInvalidChunkSizeErrorResumableUploadErrorUnexpectedBodyErrorUnexpectedMethodError) JsonModeli@iii<z https://www.googleapis.com/batchcd}|dkrdS|tkrdS|tjkr|sdS tj|dt tritfddDd}|rJd |}t |tr't|d kr|d }d |vr|d }nd d d d }n9#tttf$rtd |YdSwxYwtd||dvrdSdS)zDetermines whether a response should be retried. Args: resp_status: The response status received. content: The response content body. Returns: True if the response should be retried, otherwise False. NiTFutf-8c30K|]}|dv |VdS)errorN).0kwdatas HC:\PYTHON\MyICR_Workspace\venv\Lib\site-packages\googleapiclient/http.py z)_should_retry_response..ws>g......)errorsstatusmessagerrreasonrz&Invalid JSON content from response: %sz*Encountered 403 Forbidden with reason "%s")userRateLimitExceededrateLimitExceeded)_TOO_MANY_REQUESTS http_client FORBIDDENjsonloadsdecode isinstancedictnextlistlenUnicodeDecodeError ValueErrorKeyErrorLOGGERwarning) resp_statuscontentr!error_detail_keywordrs @r_should_retry_responser7PsFct(((tk+++ 5 :gnnW5566D$%% >(,"A  (($(6!']+?@F!&$//6CKK!OO!'#v--%+H%5Fa)(3H="J9    NNCW M M M55  CVLLL C C C4 5sB?C//2D%$D%c d} d} d} t|dzD])} | dkrE|d| zz} td| | ||||| r| jn| ||  d} |j||g|Ri|\} } n#t $r }|} Yd}~nd}~wt j$r }|} Yd}~nud}~wt$r }|} Yd}~nad}~wt$r8}t j j |j dvr|} Yd}~n!d}~wtj$r }|} Yd}~nd}~wwxYw| r | |kr| t| j| sn+| | fS)aRetries an HTTP request multiple times while handling errors. If after all retries the request still fails, last error is either returned as return value (for HTTP 5xx errors) or thrown (for ssl.SSLError). Args: http: Http object to be used to execute request. num_retries: Maximum number of retries. req_type: Type of the request (used for logging retries). sleep, rand: Functions to sleep for random time between retries. uri: URI to be requested. method: HTTP method to be used. args, kwargs: Additional arguments passed to http.request. Returns: resp, content - Response from the http request (may be HTTP 5xx). NrzCSleeping %.2f seconds before retry %d of %d for %s: %s %s, after %s>EPIPE ETIMEDOUT ECONNRESET ECONNABORTED ECONNREFUSED WSAETIMEDOUT)ranger2r3rrequest _ssl_SSLErrorsockettimeoutConnectionErrorOSErrorerrno errorcodegethttplib2ServerNotFoundErrorr7)http num_retriesreq_typesleeprandurimethodargskwargsrespr5 exception retry_num sleep_time ssl_errorsocket_timeoutconnection_error socket_errorserver_not_found_errors r_retry_requestr_s ( DGI;?++66 q==!Y,.J NNU#2     E*    /I(DLfFtFFFvFFMD'' " " "!IIIIII~ ' ' ''IIIIII ) ) )(IIIIII % % % |%)),*<==F$IIIIII+ / / /.IIIIII /  K''%dk7;;  E  =sH(B D BD#B** D7B>> D .C>>DDDceZdZdZdZdZdS)MediaUploadProgresszStatus of a resumable upload.c"||_||_dS)zConstructor. Args: resumable_progress: int, bytes sent so far. total_size: int, total bytes in complete upload, or None if the total upload size isn't known ahead of time. Nresumable_progress total_sizeselfrdres r__init__zMediaUploadProgress.__init__s#5$rc||j4|jdkr)t|jt|jz SdS)zPercent of upload completed, as a float. Returns: the percentage complete as a float, returning 0.0 if the total size of the upload is unknown. Nrrefloatrdrgs rprogresszMediaUploadProgress.progress= ? &4?a+?+?011E$/4J4JJ J3rN__name__ __module__ __qualname____doc__rhrnrrrraras8'' % % %     rraceZdZdZdZdZdS)MediaDownloadProgresszStatus of a resumable download.c"||_||_dS)zConstructor. Args: resumable_progress: int, bytes received so far. total_size: int, total bytes in complete download. Nrcrfs rrhzMediaDownloadProgress.__init__s#5$rc||j4|jdkr)t|jt|jz SdS)zPercent of download completed, as a float. Returns: the percentage complete as a float, returning 0.0 if the total size of the download is unknown. Nrrjrkrms rrnzMediaDownloadProgress.progressrorNrprrrrvrvs8))%%%     rrvceZdZdZdZdZdZdZdZdZ dZ e j d dd Z d Zed Zd S) MediaUploadaDescribes a media object to upload. Base class that defines the interface of MediaUpload subclasses. Note that subclasses of MediaUpload may allow you to control the chunksize when uploading a media object. It is important to keep the size of the chunk as large as possible to keep the upload efficient. Other factors may influence the size of the chunk you use, particularly if you are working in an environment where individual HTTP requests may have a hardcoded time limit, such as under certain classes of requests under Google App Engine. Streams are io.Base compatible objects that support seek(). Some MediaUpload subclasses support using streams directly to upload data. Support for streaming may be indicated by a MediaUpload sub-class and if appropriate for a platform that stream will be used for uploading the media object. The support for streaming is indicated by has_stream() returning True. The stream() method should return an io.Base object that supports seek(). On platforms where the underlying httplib module supports streaming, for example Python 2.6 and later, the stream will be passed into the http library which will result in less memory being used and possibly faster uploads. If you need to upload media that can't be uploaded using any of the existing MediaUpload sub-class then you can sub-class MediaUpload for your particular needs. ctz[Chunk size for resumable uploads. Returns: Chunk size in bytes. NotImplementedErrorrms r chunksizezMediaUpload.chunksize8s "###rcdS)FMime type of the body. Returns: Mime type. application/octet-streamrrms rmimetypezMediaUpload.mimetype@s *)rcdS)fSize of upload. Returns: Size of the body, or None of the size is unknown. Nrrms rsizezMediaUpload.sizeHs trcdS)iWhether this upload is resumable. Returns: True if resumable upload or False. Frrms r resumablezMediaUpload.resumablePs urct)aGet bytes from the media. Args: begin: int, offset from beginning of file. length: int, number of bytes to read, starting at begin. Returns: A string of bytes read. May be shorter than length if EOF was reached first. r})rgbeginends rgetbyteszMediaUpload.getbytesXs"###rcdS),Does the underlying upload support a streaming interface. Streaming means it is an io.IOBase subclass that supports seek, i.e. seekable() returns True. Returns: True if the call to stream() will return an instance of a seekable io.Base subclass. Frrms r has_streamzMediaUpload.has_streames urctzA stream interface to the data being uploaded. Returns: The returned value is an io.IOBase subclass that supports seek, i.e. seekable() returns True. r}rms rstreamzMediaUpload.streamqs"###rr9Nct|}tj|j}||D]}||=|j|d<|j|d<t j|S)a'Utility function for creating a JSON representation of a MediaUpload. Args: strip: array, An array of names of members to not include in the JSON. Returns: string, a JSON representation of this instance, suitable to pass to from_json(). N_class_module)typecopy__dict__rqrrr'dumps)rgstriptdmembers r_to_jsonzMediaUpload._to_jsonzsb JJ Idm $ $    fIIj( |) z!}}rc*|S)zCreate a JSON representation of an instance of MediaUpload. Returns: string, a JSON representation of this instance, suitable to pass to from_json(). rrms rto_jsonzMediaUpload.to_jsons}}rctj|}|d}t||ddd}t ||d}t |d}||S)a+Utility class method to instantiate a MediaUpload subclass from a JSON representation produced by to_json(). Args: s: string, JSON from to_json(). Returns: An instance of the subclass of MediaUpload that was serialized with to_json(). r.N)fromlistr from_json)r'r( __import__splitgetattr)clssrmodulemklsrs r new_from_jsonzMediaUpload.new_from_jsonsqz!}}i v S(9(9#2#(> ? ? ?ah((C-- y||rN)rqrrrsrtrrrrrrrutil positionalrr classmethodrrrrrzrzs4$$$*** $ $ $   $$$T_Q&[rrzceZdZdZejdedffd ZdZdZ dZ dZ d Z d Z d Zd ZxZS) MediaIoBaseUploadaA MediaUpload for a io.Base objects. Note that the Python file object is compatible with io.Base and can be used with this class also. fh = BytesIO('...Some data to upload...') media = MediaIoBaseUpload(fh, mimetype='image/png', chunksize=1024*1024, resumable=True) farm.animals().insert( id='cow', name='cow.png', media_body=media).execute() Depending on the platform you are working on, you may pass -1 as the chunksize, which indicates that the entire file should be uploaded in a single request. If the underlying platform supports streams, such as Python 2.6 or later, then this can be very efficient as it avoids multiple connections, and also avoids loading the entire file into memory before sending it. Note that Google App Engine has a 5MB limit on request size, so you should never set your chunksize larger than 5MB, or to -1. FcHtt|||_||_|dks|dkst ||_||_|jdtj |j |_ dS)a;Constructor. Args: fd: io.Base or file object, The source of the bytes to upload. MUST be opened in blocking mode, do not use streams opened in non-blocking mode. The given stream must be seekable, that is, it must be able to call seek() on fd. mimetype: string, Mime-type of the file. chunksize: int, File will be uploaded in chunks of this many bytes. Only used if resumable=True. Pass in a value of -1 if the file is to be uploaded as a single chunk. Note that Google App Engine has a 5MB limit on request size, so you should never set your chunksize larger than 5MB, or to -1. resumable: bool, True if this is a resumable upload. False means upload in a single request. rrN) superrrh_fd _mimetyper _chunksize _resumableseekosSEEK_ENDtell_size)rgfdrrr __class__s rrhzMediaIoBaseUpload.__init__s$ &&//111!R9q==')) )##  a%%%X]]__ rc|jSr|)rrms rrzMediaIoBaseUpload.chunksize rc|jS)r)rrms rrzMediaIoBaseUpload.mimetypes ~rc|jS)r)rrms rrzMediaIoBaseUpload.sizes zrc|jS)r)rrms rrzMediaIoBaseUpload.resumablerrcj|j||j|S)aGet bytes from the media. Args: begin: int, offset from beginning of file. length: int, number of bytes to read, starting at begin. Returns: A string of bytes read. May be shorted than length if EOF was reached first. )rrread)rgrlengths rrzMediaIoBaseUpload.getbytess,  ex}}V$$$rcdS)rTrrms rrzMediaIoBaseUpload.has_streams trc|jSr)rrms rrzMediaIoBaseUpload.streams xrc td)z%This upload type is not serializable.z&MediaIoBaseUpload is not serializable.r}rms rrzMediaIoBaseUpload.to_json#s!"JKKKr)rqrrrsrtrrDEFAULT_CHUNK_SIZErhrrrrrrrr __classcell__rs@rrrs,T_Q/AU%%%%%%8 % % %   LLLLLLLrrcxeZdZdZejddedffd ZdZdZ e dZ xZ S) MediaFileUploadaA MediaUpload for a file. Construct a MediaFileUpload and pass as the media_body parameter of the method. For example, if we had a service that allowed uploading images: media = MediaFileUpload('cow.png', mimetype='image/png', chunksize=1024*1024, resumable=True) farm.animals().insert( id='cow', name='cow.png', media_body=media).execute() Depending on the platform you are working on, you may pass -1 as the chunksize, which indicates that the entire file should be uploaded in a single request. If the underlying platform supports streams, such as Python 2.6 or later, then this can be very efficient as it avoids multiple connections, and also avoids loading the entire file into memory before sending it. Note that Google App Engine has a 5MB limit on request size, so you should never set your chunksize larger than 5MB, or to -1. r:NFcd|_||_t|jd|_|tj|\}}|d}t t ||j|||dS)aConstructor. Args: filename: string, Name of the file. mimetype: string, Mime-type of the file. If None then a mime-type will be guessed from the file extension. chunksize: int, File will be uploaded in chunks of this many bytes. Only used if resumable=True. Pass in a value of -1 if the file is to be uploaded in a single chunk. Note that Google App Engine has a 5MB limit on request size, so you should never set your chunksize larger than 5MB, or to -1. resumable: bool, True if this is a resumable upload. False means upload in a single request. Nrbrrr)r _filenameopen mimetypes guess_typerrrh)rgfilenamerrr_rs rrhzMediaFileUpload.__init__>s$!--  #.x88KHa5 ot$$-- Hh)y .     rcJ|jr|jdSdSr)rcloserms r__del__zMediaFileUpload.__del__]s. 8  HNN       rc0|dgS)zCreating a JSON representation of an instance of MediaFileUpload. Returns: string, a JSON representation of this instance, suitable to pass to from_json(). r)rrrms rrzMediaFileUpload.to_jsonas}}E7}+++rctj|}t|d|d|d|dS)Nrrrr)rrr)r'r(r)rrs rrzMediaFileUpload.from_jsonjsB JqMM kN{^ o o     r) rqrrrsrtrrrrhrr staticmethodrrrs@rrr(s*T_Q!%1Cu      <,,,  \     rrcVeZdZdZejddedffd ZxZS)MediaInMemoryUploadzMediaUpload for a chunk of bytes. DEPRECATED: Use MediaIoBaseUpload with either io.TextIOBase or io.StringIO for the stream. r:rFctj|}tt|||||dS)a&Create a new MediaInMemoryUpload. DEPRECATED: Use MediaIoBaseUpload with either io.TextIOBase or io.StringIO for the stream. Args: body: string, Bytes of body content. mimetype: string, Mime-type of the file or default of 'application/octet-stream'. chunksize: int, File will be uploaded in chunks of this many bytes. Only used if resumable=True. resumable: bool, True if this is a resumable upload. False means upload in a single request. rN)ioBytesIOrrrh)rgbodyrrrrrs rrhzMediaInMemoryUpload.__init__|sO,Z   !4((11 I 2     r) rqrrrsrtrrrrhrrs@rrrusk T_Q,$           rrc|eZdZdZejdefdZejdddZdS) MediaIoBaseDownloada "Download media resources. Note that the Python file object is compatible with io.Base and can be used with this class also. Example: request = farms.animals().get_media(id='cow') fh = io.FileIO('cow.png', mode='wb') downloader = MediaIoBaseDownload(fh, request, chunksize=1024*1024) done = False while done is False: status, done = downloader.next_chunk() if status: print "Download %d%%." % int(status.progress() * 100) print "Download Complete!" rcB||_||_|j|_||_d|_d|_d|_tj |_ tj |_ i|_ |jD]%\}}|dvr ||j |<&dS)aBConstructor. Args: fd: io.Base or file object, The stream in which to write the downloaded bytes. request: googleapiclient.http.HttpRequest, the media request to perform in chunks. chunksize: int, File will be downloaded in chunks of this many bytes. rNF)acceptzaccept-encoding user-agent)r_requestrR_urir _progress _total_size_donetimerP_sleeprandom_rand_headersheadersitemslower)rgrrBrkvs rrhzMediaIoBaseDownload.__init__s K # j ]  O))++ % %DAq7799 KKK#$ a  % %rr9rc |j}d|j|j|jzdz fz|d<|jj}t ||d|j|j|j d|\}}|j dvrd|vr|d|j kr |d|_ |xjt|z c_|j |d |vr9|d }|d dd}t||_nd |vrt|d |_|j|j|jkrd |_t%|j|j|jfS|j dkrk|d }|d dd}t||_|jdkr(d |_t%|j|j|jfSt'|||j )aGet the next chunk of the download. Args: num_retries: Integer, number of times to retry with randomized exponential backoff. If all retries fail, the raised HttpError represents the last request. If zero (default), we attempt the request only once. Returns: (status, done): (MediaDownloadProgress, boolean) The value of 'done' will be True when the media has been fully downloaded or the total size of the media is unknown. Raises: googleapiclient.errors.HttpError if the response was not a 2xx. httplib2.HttpLib2Error if a transport error has occurred. z bytes=%d-%dr9rAzmedia downloadGETr)zcontent-locationz content-range/content-lengthNTirrR)rrrrrrMr_rrrrr.rwritersplitintrrrvr )rgrNrrMrVr5 content_rangers r next_chunkzMediaIoBaseDownload.next_chunks&-$$&&( N NT_ ,q 0,  }!&    K J I     g ;* $ $!T))d3E.F$).S.S !34 NNc'll *NN HNN7 # # #$&& $_ 5 &--c155a8#&v;;  !T))#&t,<'=#>#> '4>T=M+M+M! (9IJJDJV V [C  !1M"))#q11!4F"6{{D 1$$! )$.$:JKKJg495555rN)r) rqrrrsrtrrrrhr rrrrrs&T_Q.@%%%%<T_Q@6@6@6@6@6@6rrc eZdZdZdZddZdS) _StreamSliceaTruncated stream. Takes a stream and presents a stream that is a slice of the original stream. This is used when uploading media in chunks. In later versions of Python a stream can be passed to httplib in place of the string of data to send. The problem is that httplib just blindly reads to the end of the stream. This wrapper presents a virtual stream that only reads to the end of the chunk. cd||_||_||_|j|dS)zConstructor. Args: stream: (io.Base, file object), the stream to wrap. begin: int, the seek position the chunk begins at. chunksize: int, the size of the chunk. N)_stream_beginrr)rgrrrs rrhz_StreamSlice.__init__s5  # %     rrc|j}|j|jz}|dks ||z|kr||z }|j|S)zRead n bytes. Args: n, int, the number of bytes to read. Returns: A string of length 'n', or less if EOF is reached. r)rrrrr)rgncurrs rrz_StreamSlice.read&sYl!!kDO+ 77cAgmmc A|  ###rN)r)rqrrrsrtrhrrrrr r sA ! ! !$$$$$$rr c"eZdZdZejd ddZejdddZejd d Zejddd Z d Z d Z e dZ e dZdS) HttpRequestz#Encapsulates a single HTTP request.rNc ,||_||_||_|pi|_||_||_||_||_g|_d|_ t|jpd|_ d|_ d|_ tj|_t j|_dS)aConstructor for an HttpRequest. Args: http: httplib2.Http, the transport object to use to make a request postproc: callable, called on the HTTP response and content to transform it into a data object before returning, or raising an exception on an error. uri: string, the absolute URI to send the request to method: string, the HTTP method to use body: string, the request body of the HTTP request, headers: dict, the HTTP request headers methodId: string, a unique identifier for the API method being called. resumable: MediaUpload, None if this is not a resumbale request. Fr Nr)rRrSrrmethodIdrMpostprocrresponse_callbacks_in_error_stater. body_size resumable_urirdrrrrPr) rgrMrrRrSrrrrs rrhzHttpRequest.__init__:s4  }"      ""$$TY_"--"#$] j rr9rc ||j}|jr"d}||||\}}||Sd|jvrt |j|jd<t |jtkr|j dkrd|_ d|jd<d|jd<tj |j}tj |j|j|j|jddf|_|j|_t t |j|jd<t)||d |j|jt |jt |j |j|j \}}|jD] }|||jd krt3|||j |||S) aExecute the request. Args: http: httplib2.Http, an http object to be used in place of the one the HttpRequest request object was constructed with. num_retries: Integer, number of times to retry with randomized exponential backoff. If all retries fail, the raised HttpError represents the last request. If zero (default), we attempt the request only once. Returns: A deserialized object model of the response body as determined by the postproc. Raises: googleapiclient.errors.HttpError if the response was not a 2xx. httplib2.HttpLib2Error if a transport error has occurred. N)rMrNrrPOSTx-http-method-overridez!application/x-www-form-urlencoded content-typerBrSrr,r)rMrr rstrrr.rRMAX_URI_LENGTHrSurllibparseurlparse urlunparseschemenetlocpathparamsqueryrr_rrrrr r) rgrMrNrrparsedrVr5callbacks rexecutezHttpRequest.executels( <9D > D,//t/MM4,K 4< / /-0-@-@DL) * tx==> ) )dkU.B.B DK5:DL1 2+NDL (\**4844F|.. v{FM4QUVDH DI-0TY-@-@DL) *'    K J MMt{##L    g/  H HTNNNN ;#  D'tx888 8}}T7+++rr:c:|j|dS)zadd_response_headers_callback Args: cb: Callback to be called on receiving the response headers, of signature: def cb(resp): # Where resp is an instance of httplib2.Response N)rappend)rgcbs radd_response_callbackz!HttpRequest.add_response_callbacks! &&r*****rc ||j}|jd}n&t|j}|jt j|j}|j|d<|dkr||d<t|j|d<t||d|j |j |j |j |j| \}}|jdkrd |vr|d |_n^t!|||jrGd |zd d }||jd |\}}|||\}} | r|| fS|jr|j} |jdkr@| |j|j|jz dz } nt3| |j|j} t5|j|jzdz |jdz } n|j|j|j} t9| |jkr$t|jt9| z}|jt9| zdz } dt| |jz dzi}| dkrd|j| |fz|d<t;|dzD]} | dkr]| | d| zzt<d| |j |j |jfz ||jd | |\}}n #d|_xYwtA|j|sn|||S)aExecute the next step of a resumable upload. Can only be used if the method being executed supports media uploads and the MediaUpload object passed in was flagged as using resumable upload. Example: media = MediaFileUpload('cow.png', mimetype='image/png', chunksize=1000, resumable=True) request = farm.animals().insert( id='cow', name='cow.png', media_body=media) response = None while response is None: status, response = request.next_chunk() if status: print "Upload %d%% complete." % int(status.progress() * 100) Args: http: httplib2.Http, an http object to be used in place of the one the HttpRequest request object was constructed with. num_retries: Integer, number of times to retry with randomized exponential backoff. If all retries fail, the raised HttpError represents the last request. If zero (default), we attempt the request only once. Returns: (status, body): (ResumableMediaStatus, object) The body will be None until the resumable media is fully uploaded. Raises: googleapiclient.errors.HttpError if the response was not a 2xx. httplib2.HttpLib2Error if a transport error has occurred. N*zX-Upload-Content-TypezX-Upload-Content-Lengthrzresumable URI requestr!rlocationz bytes */%s0) Content-RangerPUTrrr9zContent-Lengthzbytes %d-%d/%sr9rr:z7Retry #%d for media upload: %s %s, following status: %dT)!rMrrr#rrrrrr_rrrRrSrrr rrB_process_responserrrrrdr minrr.rAr2r3r7) rgrMrNr start_headersrVr5rrrr chunk_endrXs rr zHttpRequest.next_chunks/N <9D >   (DDt~**,,--D   % Idl33M59^5L5L5N5NM1 2s{{;? 78.1$..A.AM* +*'  {Y%   MD'{c!!jD&8&8%)*%5""*4999  ! &)5t(;sSSG LL);UGLTTMD'11$@@LFD &~% > $ $ & & @>((**D~''))R// $1222 N//11D4KKaO $$14>3K3K3M3M +dn.F.F.H.HH1LN''))A- >**')A)A)C)CD 4yy4>33555542SYY>??/#d));a?I c)d.E"E"IJJ  ??'7';(GO $ {Q//  I1}} DJJLL1i<7888M $+txEF   $ &u4!-!! gg '+$)$+w??  %%dG444s +!O  Oc|jdvrd|_d|||fS|jdkrhd|_ t|ddddz|_n#t $r d|_YnwxYwd |vr |d |_nd |_t|||j t|j|j dfS) aProcess the response from a single chunk upload. Args: resp: httplib2.Response, the response object. content: string, the content of the response. Returns: (status, body): (ResumableMediaStatus, object) The body will be None until the resumable media is fully uploaded. Raises: googleapiclient.errors.HttpError if the response was not a 2xx or a 308. )rFN4rA-r9rr7Tr) rrrrrrdr1rr rRrarr)rgrVr5s rr;zHttpRequest._process_responseGs  ;* $ $#(D tW555 5 [C  #(D  ,*-d7m.A.A#.F.Fq.I*J*JQ*N'' , , ,*+''' ,T!!%)*%5"#'D D'tx888 8  79L9L9N9N O O   s6A33BBctj|j}|d|j|d<|d=|d=|d=|d=t j|S)z1Returns a JSON representation of the HttpRequest.rNrMrrr)rrrrr'r)rgrs rrzHttpRequest.to_jsonks^ Idm $ $ [> %!^3355AkN fI jM hK gJz!}}rc tj|}|d#t|d|d<t |||d|d|d|d|d|dS) z>Returns an HttpRequest populated with info from a JSON object.rNrRrSrrr)rRrSrrrr)r'r(rzrr)rrMrrs rrzHttpRequest.from_jsonws} JqMM [> %(66q~FFAkN  %X;6iLz] n    rc ||fSrr)rVcontentss r null_postproczHttpRequest.null_postprocs X~rrNNNN)Nr)rqrrrsrtrrrhr0r4r r;rrrrGrrrrr7s4--T_Q  /!/!/!/!bT_Q>,>,>,>,@T_Q + + +T_QK5K5K5K5Z" " " H     \ \rrceZdZdZejdddZdZdZdZ dZ d Z d Z ejd dd Z d ZejdddZdS)BatchHttpRequestaBatches multiple HttpRequest objects into a single HTTP request. Example: from googleapiclient.http import BatchHttpRequest def list_animals(request_id, response, exception): """Do something with the animals list response.""" if exception is not None: # Do something with the exception. pass else: # Do something with the response. pass def list_farmers(request_id, response, exception): """Do something with the farmers list response.""" if exception is not None: # Do something with the exception. pass else: # Do something with the response. pass service = build('farm', 'v2') batch = BatchHttpRequest() batch.add(service.animals().list(), list_animals) batch.add(service.farmers().list(), list_farmers) batch.execute(http=http) r9Nc|t}|tkr tdt||_||_i|_i|_g|_d|_d|_ i|_ i|_ dS)aConstructor for a BatchHttpRequest. Args: callback: callable, A callback to be called for each response, of the form callback(id, response, exception). The first parameter is the request id, and the second is the deserialized response object. The third is an googleapiclient.errors.HttpError exception object if an HTTP error occurred while processing the request, or None if no error occurred. batch_uri: string, URI to send batch requests to. NaYou have constructed a BatchHttpRequest using the legacy batch endpoint %s. This endpoint will be turned down on August 12, 2020. Please provide the API-specific endpoint or use service.new_batch_http_request(). For more details see https://developers.googleblog.com/2018/03/discontinuing-support-for-json-rpc-and.htmland https://developers.google.com/api-client-library/python/guide/batch.r) _LEGACY_BATCH_URIr2r3 _batch_uri _callback _requests _callbacks_order _last_auto_id_base_id _responses_refreshed_credentials)rgr/ batch_uris rrhzBatchHttpRequest.__init__s  )I ) ) ) NN[ "   $"  ')###rcRd}d}|jtj|j}d}||tj|}|At||jvr+tj|d|jt|<|j|stj||jdSdS)zRefresh the credentials and apply to the request. Args: request: HttpRequest, the request. http: httplib2.Http, the global http object for the batch. NFTr9)rMrget_credentials_from_httpidrUrefresh_credentialsapply_credentialsr)rgrBrMcredsrequest_credentialss r_refresh_and_apply_credentialsz/BatchHttpRequest._refresh_and_apply_credentialss# < #3GLAAE"&  =T-3D99E  %yy ;;;)%0009:+BuII6 < ':   #E7? ; ; ; ; ; rc|jtj|_d|jdtj|dS)aAConvert an id to a Content-ID header value. Args: id_: string, identifier of individual request. Returns: A Content-ID header with the id_ encoded into it. A UUID is prepended to the value because Content-ID headers are supposed to be universally unique. N< + >)rSuuiduuid4r%r&quote)rgid_s r _id_to_headerzBatchHttpRequest._id_to_headersC =  JLLDM #mmmV\-?-?-D-D-D-DEErc|ddks |ddkrtd|zd|vrtd|z|dddd\}}tj|S) abConvert a Content-ID header value to an id. Presumes the Content-ID header conforms to the format that _id_to_header() returns. Args: header: string, Content-ID header value. Returns: The extracted id value. Raises: BatchError if the header is not in the expected format. rr`rrbz Invalid value for Content-ID: %s+r9ra)r rr%r&unquote)rgheaderbaserfs r _header_to_idzBatchHttpRequest._header_to_ids !9  vbzS00?&HII I f  ?&HII I1R4L&&ua00 c|##C(((rctj|j}tjdd|j|j|jdf}|jdz|zdz}|j dd d\}}t||}|j }|j0tj|j} | tj| |d|vr|d=|D] \} } | || < |j|d<|d|j>||jt/t1|j|d <t3j} t7| d } | |d | }||zS)zConvert an HttpRequest object into a string. Args: request: HttpRequest, the request to serialize. Returns: The request as a string in application/http format. r  z HTTP/1.1 r zapplication/jsonrNHostrr) maxheaderlenFunixfrom)r%r&r'rRr(r+r,r-rSrrJrrrrMrrXr[rr* set_unixfromr set_payloadr#r.rStringIOrflattengetvalue)rgrBr. request_line status_linemajorminormsgr credentialskeyvaluefpgrs r_serialize_requestz#BatchHttpRequest._serialize_request)s&&w{33|.. V[&-r B  ns*\9MI **>;MNNTT   uue,,/&&(( < #9',GGK&' W=== W $ $'!--//  JCCHHmF   < # OOGL ) ) )$'GL(9(9$:$:C ![]] bq ) ) ) # &&&{{}}T!!rc|dd\}}|dd\}}}t}|||}||d<t j|}||_t|ddddd|_ |d dd} || fS) zConvert string into httplib2 response and content. Args: payload: string, headers and body as a string. Returns: A pair (resp, content), such as would be returned from httplib2.request.  r9ror:rrrr z ) rrfeedrrKResponser!rreplaceversion) rgpayloadrzprotocolrr!parserr}rVr5s r_deserialize_responsez&BatchHttpRequest._deserialize_responseYs '}}T155 W#.#4#4S!#<#< && GllnnH  %% 8>>#q11!4<z+BatchHttpRequest._execute..sr applicationrMbinaryzContent-Transfer-Encodingz Content-IDF) mangle_from_rrzmultipart/mixed; boundary="%s"r rr!r"rzcontent-type: %s rz'Response not in multipart/mixed format.)rVr5N)rsetattrrrgrruattachrrvrrwrx get_boundaryrBrMrr r)rrr is_multipartr get_payloadrmrr*r#encoderT)rgrMorderrequestsrrrBr}rrrrrVr5rk for_parserr mime_responsepartresponses r_executezBatchHttpRequest._executes (()+<+<=== Jz*G"=&99C/7C+ , $ 2 2: > >C **733D OOD ! ! ! NN3    []] bu - - - 'E ***{{}} /  " "## OFw%  g ;#  D't??? ?,d>.BB..))g%  J  ))++ 9g "--// > >D++D,>??J $ : :4;K;K;M;M N N Hg'3'' 2!..11+3W*=DOJ ' '  > >rct|jdkrdS|"|jD]}|j|}| |j}n|t dt j|}|Bt j|s.t dt j || ||j|ji}g}|jD][}|j |\}}|ddkr=| ||j|}||||||<\|r| ||||jD]}|j |\}}|j|}|j|} d} d} |jdkrt#|||j|||} n#t"$r } | } Yd} ~ nd} ~ wwxYw| | || | |j||| | dS) aExecute all the requests as a single batched HTTP request. Args: http: httplib2.Http, an http object to be used in place of the one the HttpRequest request object was constructed with. If one isn't supplied then use a http object from the requests in this batch. Returns: None Raises: httplib2.HttpLib2Error if a transport error has occurred. googleapiclient.errors.BatchError if the response is the wrong format. rNzMissing a valid http object.z1Attempting refresh to obtain initial access_tokenr401r"r)r.rQrOrMr0rrXis_validr2inforZrrTr2r^rPrr rRrrN) rgrMrrBr\ redo_requests redo_orderrVr5r/rrWes rr0zBatchHttpRequest.executesn" t{  q 4 <"k   .4&"%(( 1 OPPP)%000 dDK888  + 4 4J OJ7MD'H~&&!!*---.433GTBBB,3 j)  ; MM$ M : : : + @ @J OJ7MD'nZ0Gz2HHI ;#%%#D'w{CCCC"++D'::     #Xy999~)z8Y???% @ @s8F:: GG  GNNr)rqrrrsrtrrrhr^rgrmrrrrrr0rrrrJrJs%@T_Q0)0)0)0)d<<<<FFF&))).."."."`8 ' ' 'T_Q*'*'*'*'XF>F>F>PT_QN@N@N@N@N@N@rrJc eZdZdZdZddZdS)HttpRequestMockzYMock of HttpRequest. Do not construct directly, instead use RequestMockBuilder. c||_||_||_|tjddd|_d|jvr|jd|j_dSdS)aYConstructor for HttpRequestMock Args: resp: httplib2.Response, the response to emulate coming from the request content: string, the response body postproc: callable, the post processing function usually supplied by the model class. See model.JsonModel.response() as an example. NrOK)rr!r!)rVr5rrKrr!)rgrVr5rs rrhzHttpRequestMock.__init__Osd    < )SD*I*IJJDI ty #y2DI    ! rNcB||j|jS)zExecute the request. Same behavior as HttpRequest.execute(), but the response is mocked and not really from an HTTP request/response. )rrVr5)rgrMs rr0zHttpRequestMock.execute`s }}TY 555rr)rqrrrsrtrhr0rrrrrIsA 333"666666rrc,eZdZdZddZ ddZdS) RequestMockBuilderaA simple mock of HttpRequest Pass in a dictionary to the constructor that maps request methodIds to tuples of (httplib2.Response, content, opt_expected_body) that should be returned when that method is called. None may also be passed in for the httplib2.Response, in which case a 200 OK response will be generated. If an opt_expected_body (str or dict) is provided, it will be compared to the body and UnexpectedBodyError will be raised on inequality. Example: response = '{"data": {"id": "tag:google.c...' requestBuilder = RequestMockBuilder( { 'plus.activities.get': (None, response), } ) googleapiclient.discovery.build("plus", "v1", requestBuilder=requestBuilder) Methods that you do not supply a response for will return a 200 OK with an empty string as the response content or raise an excpetion if check_unexpected is set to True. The methodId is taken from the rpcName in the discovery document. For more details see the project wiki. Fc"||_||_dS)aConstructor for RequestMockBuilder The constructed object should be a callable object that can replace the class HttpResponse. responses - A dictionary that maps methodIds into tuples of (httplib2.Response, content). The methodId comes from the 'rpcName' field in the discovery document. check_unexpected - A boolean setting whether or not UnexpectedMethodError should be raised on unsupplied method. N) responsescheck_unexpected)rgrrs rrhzRequestMockBuilder.__init__s# 0rrNc ||jvr|j|} | dd\} } t| dkr| d} t| t|krt| |t | t rt j| } t j|}|| krt| |t| | |S|j rt|td} tdd| j S)aImplements the callable interface that discovery.build() expects of requestBuilder, which is to build an object compatible with HttpRequest.execute(). See that method for the description of the parameters and the expected response. Nr:)rFz{}) rr.boolrr*r#r'r(rrrrr)rgrMrrRrSrrrrrrVr5 expected_bodymodels r__call__zRequestMockBuilder.__call__s  t~ % %~h/H$RaRLMD'8}}q  (  &&$t**44.mTBBBmS11>$(J}$=$=Mz$''=((-mTBBB"4(;; ;  " ?'::: :e$$E"4u~>> >r)FrH)rqrrrsrtrhrrrrrrisW41111* $?$?$?$?$?$?rrc2eZdZdZddZ d dZdZdS) HttpMockzMock of httplib2.HttpNc|ddi}|rBt|d5}||_dddn #1swxYwYnd|_||_d|_d|_d|_d|_d|_dS)z Args: filename: string, absolute filename to read response from headers: dict, header to return with response Nr200r)rrrresponse_headersrrRrSr)rgrrfs rrhzHttpMock.__init__s ?'G  h%% %FFHH  % % % % % % % % % % % % % % %DI '    s?AArr9cz||_||_||_||_t j|j|jfSr)rRrSrrrKrrr)rgrRrSrr redirectionsconnection_types rrBzHttpMock.requests;    !677BBrcdSrrrms rrzHttpMock.closestrrrNNr9N)rqrrrsrtrhrBrrrrrrsf.  C C C Crrc*eZdZdZdZ ddZdS)HttpMockSequenceaMock of httplib2.Http Mocks a sequence of calls to request returning different responses for each call. Create an instance initialized with the desired response headers and content and then use as if an httplib2.Http instance. http = HttpMockSequence([ ({'status': '401'}, ''), ({'status': '200'}, '{"access_token":"1/3w","expires_in":3600}'), ({'status': '200'}, 'echo_request_headers'), ]) resp, content = http.request("http://examples.com") There are special values you can pass in for content to trigger behavours that are helpful in testing. 'echo_request_headers' means return the request headers in the response body 'echo_request_headers_as_json' means return the request headers in the response body 'echo_request_body' means return the request body in the response body 'echo_request_uri' means return the request uri in the response body cH||_d|_t|_dS)z\ Args: iterable: iterable, a sequence of pairs of (headers, body) TN) _iterablefollow_redirectsr-request_sequence)rgiterables rrhzHttpMockSequence.__init__s% " $ $rrNr9c|j||||f|jd\}}t |t r|d}|dkr|}nQ|dkrtj|}n6|dkr(t|dr| }n |}n|dkr|}t |t r|d}tj ||fS)Nrrsecho_request_headerssecho_request_headers_as_jsonsecho_request_bodyrsecho_request_uri) rr2rpopr*r#rr'rhasattrrrKr) rgrRrSrrrrrVr5s rrBzHttpMockSequence.requests $$c64%ABBB**1-- g gs # # .nnW--G - - -GG 7 7 7j))GG , , ,tV$$ ))++ + + +G gs # # .nnW--G &&//rr)rqrrrsrtrhrBrrrrrsR.''' 000000rrcR|jdddtjdffd }||_|S)aSet the user-agent on every request. Args: http - An instance of httplib2.Http or something that acts like it. user_agent: string, the value for the user-agent header. Returns: A modified instance of http that was passed in. Example: h = httplib2.Http() h = set_user_agent(h, "my-app-name/6.0") Most of the time the user-agent will be set doing auth, this is for the rare cases where you are accessing an unauthenticated endpoint. rNcr|i}d|vr dz|dz|d<n |d<||||||\}}||fS)1Modify the request headers to add the user-agent.NrrorSrrrrr) rRrSrrrrrVr5 request_orig user_agents r new_requestz#set_user_agent..new_request;sx ?G 7 " "$.$4w|7L$LGL ! !$.GL !$ %+    gW}rrBrKDEFAULT_MAX_REDIRECTS)rMrrrs ` @rset_user_agentr%sR&.new_requestms ?G W   OR @ @@@Q18G, -F$ %+    gW}rr)rMrrs @r tunnel_patchrXsL$rs '&&&&& 3 !!!!!!  !JJJLMMFHHMMM &%%%%%......444444######!!!!!!,,,,,,,+++++  8 $ $&6CCCLOOOd&6F4LLLLL&LLL^yLyLyLyLyL yLyLyLxJ J J J J 'J J J Z      +    Ft6t6t6t6t6&t6t6t6n%$%$%$%$%$6%$%$%$PSSSSS&SSSl y@y@y@y@y@vy@y@y@x 66666f666@O?O?O?O?O?O?O?O?d'''''v'''T=0=0=0=0=0v=0=0=0@000f222jsAA A