o `J@sdZeZgdZddlZddlZddlmZddlm Z ddl m Z ddl Z ddl Z ddlZddlZddlZddlmZddlmZmZzdd lmZWney^dd lmZejZYnwzdd lmZWneyvdd lmZYnwdd lmZdd lm Z ddl!m"Z"m#Z#ddl$m%Z%e&e'ure(Z)e*Z+ne'Z)e'Z+e ,dZ-e ,dZ.e ,dZ/ddZ0ddZ1e j23drdZ4nddlm5Z4GdddeZ6Gddde7Z8Gddde8Z9Gdd d Z:dS)!zBrowser object to make requests of lazr.restful web services. The `Browser` class does some massage of HTTP requests and responses, and handles custom caches. It is not part of the public lazr.restfulclient API. (But maybe it should be?) )Browser RestfulHttp#ssl_certificate_validation_disabledN)md5)BytesIO)dumps)sleep)Httpurlnorm)proxy_info_from_environment) ProxyInfo) urlencode) Application)URI) error_for HTTPError)DatetimeJSONEncoders^\w+://z^\w+://s[?/:|]+cCsz)t|tr |d}n|}t|r(t|tr#|d}|d}n|d}Wn ty2Ynwt|tr=|d}t| }t d|}t d|}t j}|dd}t||krd|d|}d|d|fS) zReturn a filename suitable for the cache. Strips dangerous and common characters to create a filename we can use to store the cache in. utf-8idna, N,) isinstancebytesdecodere_url_scheme_smatchencode UnicodeError unicode_typer hexdigest re_url_schemesubre_slashrmaximum_cache_filename_lengthlenjoin)filenamefilename_matchfilemd5maximum_filename_lengthmaximum_length_before_md5_sumr.=/usr/lib/python3/dist-packages/lazr/restfulclient/_browser.pysafenameUs.                r0cCsttjddS)zWhether the user has disabled SSL certificate connection. Some testing servers have broken certificates. Rather than raising an error, we allow an environment variable, ``LP_DISABLE_SSL_CERTIFICATE_VALIDATION`` to disable the check. %LP_DISABLE_SSL_CERTIFICATE_VALIDATIONF)boolosenvirongetr.r.r.r/rs rz"/etc/ssl/certs/ca-certificates.crt)CA_CERTScsBeZdZdZdZdddeffdd ZfddZdd ZZ S) rzAn Http subclass with some custom behavior. This Http client uses the TE header instead of the Accept-Encoding header to ask for compressed representations. It also knows how to react when its cache is a MultipleRepresentationCache. NcsDt}tt|j||||td||_|jdur |j|dSdS)N)"disable_ssl_certificate_validationca_certs)rsuperr__init__SYSTEM_CA_CERTS authorizerauthorizeSession)selfr=cachetimeout proxy_info cert_disabled __class__r.r/r;s  zRestfulHttp.__init__c sJd|vr|d=|jdur|j||||tt|||||||||| S)z4Use the authorizer to authorize an outgoing request. authorizationN)r=authorizeRequestr:r_request) r?connhost absolute_uri request_urimethodbodyheaders redirectionscachekeyrDr.r/rHs  zRestfulHttp._requestcCst|jtr |j||SdS)+Retrieve a cached value for an HTTP header.N)rr@MultipleRepresentationCache_getCachedHeader)r?uriheaderr.r.r/rTs zRestfulHttp._getCachedHeader) __name__ __module__ __qualname____doc__r&r r;rHrT __classcell__r.r.rDr/rs rc@s@eZdZdZdZefddZddZddZd d Z d d Z d S)AtomicFileCachezA FileCache that can be shared by multiple processes. Based on a patch found at . z.tempc Cs\tj||_||_z t|jWdSty-}z|jtjkr"WYd}~dSd}~ww)aUConstruct an ``AtomicFileCache``. :param cache: The directory to use as a cache. :param safe: A function that takes a key and returns a name that's safe to use as a filename. The key must never return a string that begins with ``TEMPFILE_PREFIX``. By default uses ``safename``. N) r3pathnormpath _cache_dir_get_safe_namemakedirsOSErrorerrnoEEXIST)r?r@safeer.r.r/r;s  zAtomicFileCache.__init__cCs4||}||jrtd|jtj|j|S)z0Return the path on disk where ``key`` is stored.z Cache key cannot start with '%s')r` startswithTEMPFILE_PREFIX ValueErrorr3r]r(r_)r?keysafe_keyr.r.r/ _get_key_paths  zAtomicFileCache._get_key_pathc Csn||}zt|d}z |W|WS|wttfy6}z|jtjkr+WYd}~dSd}~ww)aGet the value of ``key`` if set. This behaves slightly differently to ``FileCache`` in that if ``set()`` fails to store a key, this ``get()`` will behave as if that key were never set whereas ``FileCache`` returns the empty string. :param key: The key to retrieve. Must be either bytes or unicode text. :return: The value of ``key`` if set, None otherwise. rbN)rlopenreadcloseIOErrorrbrcENOENT)r?rjcache_full_pathfrfr.r.r/r5s   zAtomicFileCache.getcCsntj|j|jd\}}t|d}|||||}t j dkr/tj |r/t |t||dS)zSet ``key`` to ``value``. :param key: The key to set. Must be either bytes or unicode text. :param value: The value to set ``key`` to. Must be bytes. )prefixdirwbwin32N)tempfilemkstemprhr_r3fdopenwriterprlsysplatformr]existsunlinkrename)r?rjvaluehandle path_namertrsr.r.r/sets    zAtomicFileCache.setc CsP||}zt|WdSty'}z|jtjkrWYd}~dSd}~ww)zDelete ``key`` from the cache. If ``key`` has not already been set then has no effect. :param key: The key to delete. Must be either bytes or unicode text. N)rlr3removerbrcrr)r?rjrsrfr.r.r/deletes  zAtomicFileCache.deleteN) rWrXrYrZrhr0r;rlr5rrr.r.r.r/r\s   r\cs0eZdZdZfddZddZddZZS)rSa>A cache that can hold different representations of the same resource. If a resource has two representations with two media types, FileCache will only store the most recently fetched representation. This cache can keep track of multiple representations of the same resource. This class works on the assumption that outside calling code sets an instance's request_media_type attribute to the value of the 'Accept' header before initiating the request. This class is very much not thread-safe, but FileCache isn't thread-safe anyway. cstt|||jd|_dS)z>Tell FileCache to call append_media_type when generating keys.N)r:rSr;append_media_typerequest_media_type)r?r@rDr.r/r;.s  z$MultipleRepresentationCache.__init__cCs |jdur |d|j}t|S)zAppend the request media type to the cache key. This ensures that representations of the same resource will be cached separately, so long as they're served as different media types. N-)rr0)r?rjr.r.r/r4s z-MultipleRepresentationCache.append_media_typec Csrt|\}}}}||}|d}t|ts|d}|dur7t|D]} | |r6| t|dSq#dS)rR:rN) r r5rrrrrgr'strip) r?rUrVscheme authorityrLrQ cached_value header_startliner.r.r/rT?s     z,MultipleRepresentationCache._getCachedHeader)rWrXrYrZr;rrTr[r.r.rDr/rSs   rSc@szeZdZdZeZdZddddefddZddZ  dd d Z dd dZ ddZ ddZ dddZ ddZdddZdS)rz6A class for making calls to lazr.restful web services.NcCsR|durt}ttj|t|trt|}| |||||_ ||_ ||_ dS)zInitialize, possibly creating a cache. If no cache is provided, a temporary directory will be used as a cache. The temporary directory will be automatically removed when the Python process exits. N) rymkdtempatexitregistershutilrmtreer str_typesrS httpFactory _connection user_agent max_retries)r? service_root credentialsr@rArBrrr.r.r/r;Ss  zBrowser.__init__c Csltd|jdD])}|jj||||d\}}|jdvr-||jkr-td|d}t|q||fS||fS)NrrrMrNrO)ii)rangerrrequeststatusintr) r?urlrMrNrO retry_countresponsecontent sleep_forr.r.r/_request_and_retryes   zBrowser._request_and_retryGETapplication/jsonc Cs|dkrtdd|i}|jdur|j|d<t|jjtr"||jj_|dur+|||jt ||||d\}}|j dkrZ|dkrSd |vsId |vrN||j fSt ||d |_ ||fSt ||} | dure| ||fS) z'Create an authenticated request object.ztag:launchpad.net:2008:redactedzUYou tried to access a resource that you don't have the server-side permission to see.AcceptNz User-Agentri0rz If-None-MatchzIf-Modified-Since)rirrrr@rSrupdaterstrr NOT_MODIFIEDrr) r?rdatarM media_type extra_headersrOrrerrorr.r.r/rHts0         zBrowser._requestFcCsHt|ttfr |}n |d}|}|j||d\}}|r"||fS|S)z2GET a representation of the given resource or URI.r5r)rrr get_methodbuild_request_urlrH)r?resource_or_urirOreturn_responserrMrrr.r.r/r5s z Browser.getcCs<d}|j||d\}}t|}t|ts|d}t||S)z?GET a WADL representation of the resource at the requested url.zapplication/vnd.sun.wadl+xml)rr)rHrrrrr)r?r wadl_typerrr.r.r/get_wadl_applications    zBrowser.get_wadl_applicationcKs||d<t|}|||dS)z"POST a request to the web service.zws.opPOST)r rH)r?r method_namekwsrr.r.r/postsz Browser.postcCs,d|i}|dur |||j||d|dS)z(PUT the given representation to the URL. Content-TypeNPUTr)rrH)r?rrepresentationrrOrr.r.r/puts  z Browser.putcCs|j|dddS)z%DELETE the resource at the given URL.DELETE)rMN)rH)r?rr.r.r/rszBrowser.deletecCs^ddi}|dur |||jt|d}|dur"|jjs"||d<|j|t|tdd|dS) z8PATCH the object at url with the updated representation.rrNetagzIf-Match)clsPATCHr)rrrTr ignore_etagrHrr)r?rrrOr cached_etagr.r.r/patchs  z Browser.patch)NrrN)NF)N)rWrXrYrZobjectr MAX_RETRIESr;rrHr5rrrrrr.r.r.r/rMs"  <  r);rZtype __metaclass____all__rrchashlibriorjsonrr3rerr}rytimerhttplib2r r r ImportErrorr from_environment urllib.parser urllibwadllib.applicationrlazr.urirlazr.restfulclient.errorsrrlazr.restfulclient._jsonrrrunicoder! basestringrcompiler#rr%r0rr]rr<r6rrr\rSrr.r.r.r/s^              /  .\.