o La ftp://... z(?i)^z\+)resubescape) url_string prefix_schemer(r(r) strip_prefixsr<cCst|}|jr dSdS)zD @return Whether the given string looks like a backend URL. TF) ParsedUrlr0)r:pur(r(r)is_backend_urlsr?cCst|sdSt|}|jsJdd}tD]}||dr+t|}tt||}nq|dur>|jtvr9t|t|j}z||WStyXt t dt t dw)z Find the right backend class instance for the given URL, or return None if the given string looks like a local path rather than a URL. Raise InvalidBackendURL if the URL is not a valid URL. Nz3should be a backend url according to is_backend_url+z Could not initialize backend: %sr)r?r=r0r4 startswithr<r.r ImportErrorr r"rrr )r:r>factoryprefixr(r(r)get_backend_objects(    rEcCs&tjrd|}t|}|rt|}|S)z Instantiate a backend suitable for the given URL, or return None if the given string looks like a local path rather than a URL. Raise InvalidBackendURL if the URL is not a valid URL. zgio+)ruse_giorEBackendWrapper)r:objr(r(r) get_backends rIc@s(eZdZdZddZddZddZdS) r=aw Parse the given URL as a duplicity backend URL. Returns the data of a parsed URL with the same names as that of the standard urlparse.urlparse() except that all values have been resolved rather than deferred. There are no get_* members. This makes sure that the URL parsing errors are detected early. Raise InvalidBackendURL on invalid URL's c Cs||_ttj_ztj|}Wn tytd|wz|j|_Wn ty0td|wz|j|_Wn tyDtd|wz|j |_ |j rUtj |j |_ Wn tyctd|wz|j |_ Wn tywtd|w|j rtj |j |_ nd|_ z|j |_ Wn tytd|w|j rtj |j |_ nd|_ z|j |_ Wn tytd|wz|j|_Wn tytd|w|jrtj|j|_nd|_i|_d|_z|j|_Wn1ty|jd vrn!d |jvr td |jstd |d |jvtd |j|jfYnw|jtvrM|jr9d|j|j |_ d|_d|_ n|j dsM|j drMd|j |_ |jsSdS|jtvrc|j sctd||jtvry|j ds{td|j|fdSdS)NzSyntax error in: %szSyntax error (scheme) in: %szSyntax error (netloc) in: %szSyntax error (path) in: %szSyntax error (username) in: %szSyntax error (password) in: %szSyntax error (hostname) in: %szSyntax error (query) in: %s)rclonersyncz::[^:]*$z&Syntax error (port) in: %s A%s B%s C%sz::[^:]+$z//r6/zIMissing hostname in a backend URL which requires an explicit hostname: %sz;missing // - relative paths not supported for scheme %s: %s)r: uses_netlocurllibparseurlparserrr0netlocr unquoteusernamepasswordhostnamequeryparse_qs query_argsportr7searchrA)selfr:r>r(r(r)__init__s                           zParsedUrl.__init__cCs|jSN)r:r[r(r(r)geturl\szParsedUrl.geturlcCs tj|Sr])rbackendstrip_auth_from_urlr^r(r(r) strip_auth_s zParsedUrl.strip_authN)__name__ __module__ __qualname____doc__r\r_rbr(r(r(r)r=s  l r=cCstdd|}|S)zCReturn a URL from a urlparse object without a username or password.z^([^:/]+://)(.*@)?(.*)z\1\3)r7r8r_) parsed_url clean_urlr(r(r)racsracCst|tr|jtjjkr|jSt|dr|||ptjjSt|drA|jtj kr-tjj S|jtj kr7tjj S|jtj krAtjjStjjS)N _error_codeerrno) isinstancer coder ErrorCode backend_errorhasattrrirjEACCESbackend_permission_deniedENOENTbackend_not_foundENOSPCbackend_no_space)r` operationer(r(r)_get_code_from_exceptionjs     rxTcsfdd}|S)Ncsfdd}|S)Nc stjd\}}tdtjdD]}z |g|RWSty:}z|a|s4|WYd}~S|d}~wty}z|a|sO|WYd}~St t dt |tjk}t |j |}|tjjkrmd}|rrdddgfdd |D}tjt d ||jjt|f||d ntt d j||jjt|f|st|trtd tjnttjt|j dr|j WYd}~qd}~wwdS)N)TNrzBacktrace of previous error: %sTcSs"t|tjr t|jSt|Sr])rkr ROPathr r9uc_name)fr(r(r) make_filenames   zFretry..outer_retry..inner_retry..make_filename cs"g|] }|rt|tr|qSr()rkr.0xr|r(r) s zCretry..outer_retry..inner_retry..z#Giving up after %s attempts. %s: %s)rlextraz#Attempt of %s Nr. %s failed. %s: %s_retry_cleanup)rare_errors_fatalgetr num_retriesr_last_exceptionrr Debugr"r rxr`rmrsjoin FatalError __class__rcr uexcWarnrkrtimesleepbackend_retry_delayror) r[args errors_fatalerrors_defaultnrwat_endrlr)fatalr%rvrr) inner_retry~sV         z/retry..outer_retry..inner_retryr()r%rrrv)r%r) outer_retry}s3zretry..outer_retryr()rvrrr(rr)retryzs5rc@sDeZdZdZddZ dZddZddZd d Z iZ d d Z d S)BackendzU See README in backends directory for information on how to write a backend. cC ||_dSr])rg)r[rgr(r(r)r\ zBackend.__init__TcCsj|jjr|jjSztjd}W|Sty4|jr/td|jj|jjf}|tjd<Y|Sd}Y|Sw)a  Return a password for authentication purposes. The password will be obtained from the backend URL, the environment, by asking the user, or by some other method. When applicable, the result will be cached for future invocations. FTP_PASSWORDzPassword for '%s@%s': N) rgrTrenvironKeyError use_getpassgetpassrSrU)r[rTr(r(r) get_passwords   zBackend.get_passwordcCs|jjr tdd|S|S)aD Remove password from commandline by substituting the password found in the URL, if any, with a generic place-holder. This is intended for display purposes only, and it is not guaranteed that the results are correct (i.e., more than just the ':password@' may be substituted. z(:([^\s:/@]+)@([^\s@]+))z :*****@\3)rgrTr7r8)r[ commandliner(r(r)munge_passwords zBackend.munge_passwordcCsJddlm}m}t|d|d<||||dd}|\}}|j||fS)z For internal use. Execute the given command line, interpreted as a shell command. Returns int Exitcode, string StdOut, string StdErr r)PopenPIPET)stdoutstderruniversal_newlines) subprocessrrr which communicate returncode)r[rrrprrr(r(r)__subprocess_popens   zBackend.__subprocess_popenc Csddl}t|ttfrd|}|}n|}||}||}tt d|| |\}}}|dkr]z|j |d}| | WdSt tfy\td|||d|dfw|||fS)z Execute the given command line with error check. Returns int Exitcode, string StdOut, string StdErr Raise a BackendException on failure. rNr}zReading results of '%s')rr6r6z0Error running '%s': returned %d, with output: %s )shlexrklisttuplersplitrr Infor"_Backend__subprocess_popen popen_breaksindexr ValueErrorr ) r[rrlogstrrresultrrignoresr(r(r)subprocess_popens*     zBackend.subprocess_popenN) rcrdrerfr\rrrrrrr(r(r(r)rs rc@seZdZdZddZddZedddd.d d Zed ddd.d dZedddddZ edddddZ ddZ ddZ ddZ edddddZeddddd Zd!d"Zed#ddd$d%Zed#ddd&d'Zd(d)Zd.d*d+Zd.d,d-Zd S)/rGz^ Represents a generic duplicity backend, capable of storing and retrieving files. cCrr])r`)r[r`r(r(r)r\rzBackendWrapper.__init__cCs<t|jdrttdt||j||dSt)N_putz Writing %s) ror`r rr"r fsdecoderNotImplementedErrorr[ source_pathremote_filenamer(r(r)__do_puts zBackendWrapper.__do_putputT)rNcCs|s|}|||dS)z Transfer source_path (Path object) to remote_filename (string) If remote_filename is None, get the filename from the last path component of pathname. N) get_filename_BackendWrapper__do_putrr(r(r)r$szBackendWrapper.putmovecCsN|s|}t|jdr|j||dur|dS||||dS)z Move source_path (Path object) to remote_filename (string) Same as put(), but unlinks source_path in the process. This allows the local backend to do this more efficiently using rename. _moveFN)rror`rsetdatardeleterr(r(r)r0s   zBackendWrapper.movercCsFt|jdr |j||||sttd|jdSt)z0Retrieve remote_filename and place in local_path_getz0File %s not found locally after get from backendN) ror`rrexistsr r"rzr)r[r local_pathr(r(r)rAs zBackendWrapper.getrcs2ddt|jdrfdd|jDSt)zL Return list of filenames (byte strings) present in backend cSst|tr t|S|S)z+Convert a (maybe unicode) filename to bytes)rkrr fsencode)filenamer(r(r)tobytesRs  z$BackendWrapper.list..tobytes_listcsg|]}|qSr(r(r~rr(r)r_sz'BackendWrapper.list..)ror`rrr^r(rr)rMs zBackendWrapper.listcCt|jdr |j|SdS)s Manages remote access before downloading files (unseal data in cold storage for instance) pre_process_downloadN)ror`r)r[rr(r(r)rc  z#BackendWrapper.pre_process_downloadcCr)rpre_process_download_batchN)ror`r)r[remote_filenamesr(r(r)rkrz)BackendWrapper.pre_process_download_batchcCsRt|trJt|jdr||dSt|jdr&|D]}||qdSt)zN Delete each filename in filename_list, in order if possible. _delete_list_deleteN)rkbytesror`_do_delete_list _do_deleter)r[ filename_listrr(r(r)rss   zBackendWrapper.deleterFcCs4|r|dd}|j||dd}|sdSdS)Nd)r`r)r[rsublistr(r(r)rs     zBackendWrapper._do_delete_listcCs|j|dSr])r`r)r[rr(r(r)rszBackendWrapper._do_deletecCsi}t|jdr||}|duri}nt|jdr&|D] }||||<q|D]}||vs4||dur8i||<dD] }|||dq:q(|S)zF Return metadata about each filename in filename_list _query_listN_query)size)ror`_do_query_list _do_query setdefault)r[rinformetadatar(r(r) query_infos    zBackendWrapper.query_inforVcCs|j|}|dur i}|Sr])r`r)r[rrr(r(r)rs zBackendWrapper._do_query_listc CsZz|j|WSty,}zt|jd|}|tjjkr&ddiWYd}~S|d}~ww)NrVr)r`rrrxr rmrs)r[rrwrlr(r(r)rs zBackendWrapper._do_querycCst|jdr |jdSdS)z Close the backend, releasing any resources held and invalidating any file objects obtained from the backend. _closeN)ror`rr^r(r(r)closes zBackendWrapper.closecCsB|s t|}|s Jdt|}|||||dS)z Return fileobject opened for reading of filename on backend The file will be downloaded first into a temp file. When the returned fileobj is closed, the temp file will be deleted. zFilename not correctly parsedrb)rrOrnew_tempduppathrrfiltered_open_with_delete)r[r parseresultstdpr(r(r)get_fileobj_reads     zBackendWrapper.get_fileobj_readcCs$|||}|}|rJ|S)zL Retrieve a file from backend, process it, return contents. )rreadr)r[rrfinbufr(r(r)get_datas  zBackendWrapper.get_datar])rcrdrerfr\rrrrrrrrrrrrrrrrrr(r(r(r)rGs6              rG)T)4rffuturerinstall_aliasesbuiltinsrrrrjrrrr7rurllib.requestrN urllib.parse urllib.errorrrrrr r r duplicity.utilr duplicity.errorsr rrrrrduplicity.backendsr.r4rrMr*r2r5r<r?rErIr=rarxrrrGr(r(r(r)s^                   #~ ;_