U
    gtf                  	   @  s  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlmZ d dlmZ ddlmZ ddlmZ ddlmZ dd	lmZmZ dd
lmZmZmZmZmZmZmZmZ ddl m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& ddddZ'e'd Z(dd e') D Z*e+dZ,dZ-e+de- dZ.dZ/e/ de( dZ0ej1dd Z2dd Z3ej1dd Z4d d!d"d#d$d%d&d'd(Z5d)d e5D d*d d+d,d-d.) D d/d0d1d2d3Z6d4d5 Z7d6d7 Z8d8d9 Z9d:d; Z:dDd<d=Z;eG d>d? d?Z<G d@dA dAZ=dBdC Z>dAgZ?dS )E    )annotationsN)	dataclass)zipimporter   )	functools)compat_realpath)Request)	HTTPErrornetwork_exceptions)
NO_DEFAULTPopendeprecation_warningformat_field
remove_endshell_quotesystem_identifierversion_tuple)CHANNELORIGINRELEASE_GIT_HEADUPDATE_HINTVARIANT__version__zyt-dlp/yt-dlpzyt-dlp/yt-dlp-nightly-buildszyt-dlp/yt-dlp-master-builds)stableZnightlyZmasterr   c                 C  s   i | ]\}}||qS  r   ).0keyvaluer   r   1/tmp/pip-unpacked-wheel-q5ljy6pj/yt_dlp/update.py
<dictcomp>,   s      r   z(\d+\.)*\d+z[\da-f]{40}z7Generated from: https://(?:[^/?#]+/){3}commit/(?P<hash>)zhttps://api.github.com/repos/z	/releasesc                  C  sF  t tddrtj} ttds$d| fS tjtj| krFtj d| fS tjdkrnt	t
 d dk rhd	nd
}nTdt   }|dd dkrt d dd dkrdnd
}td }r|} ttjd | d| fS tjt} tttrdtj| dfS tjtjd dkr>tjtj| dr>d| fS d| fS )z#@returns (variant, executable_path)frozenF_MEIPASSpy2exeZ_dirdarwinr   )
      Z_legacy _r   N)x86x86_64amd64i386i686   Z32Z_x86ZSTATICX_PROG_PATHZ_exezipz..)z__main__.pyz-mz../.git/HEADsourceunknown)getattrsys
executablehasattrr#   ospathdirnameplatformr   mac_vermachinelowerarchitecturegetenvr   __file__
isinstance
__loader__r   joinbasenameargvexists)r8   r<   Zstatic_exe_pathr   r   r    _get_variant_and_executable_path8   s,    

 rG   c                   C  s   t pt d S )Nr   )r   rG   r   r   r   r   detect_variantW   s    rH   c               
   C  s   t  dkrd S tt` tjddddgdtjtj	t
tjtjd\} }}td|  rt|  W  5 Q R  S W 5 Q R X d S )	Nr1   gitz	rev-parsez--shortHEADT)textcwdstdoutstderrz	[0-9a-f]+)rH   
contextlibsuppress	Exceptionr   runr7   r8   r9   abspathr@   
subprocessPIPEre	fullmatchstrip)rM   r)   r   r   r   current_git_head[   s    

  rY   r(   z.exez_x86.exeZ_macosZ_macos_legacyZ_linuxZ_linux_aarch64Z_linux_armv7l)r0   win_exewin_x86_exeZ
darwin_exeZdarwin_legacy_exeZ	linux_exelinux_aarch64_exelinux_armv7l_exec                 C  s   i | ]
}|d qS Nr   )r   variantr   r   r   r   t   s      c                 C  s   i | ]\}}|d | dqS )z,Auto-update is not supported for unpackaged z+ executable; Re-download the latest releaser   )r   r_   namer   r   r   r   u   s    WindowsZMacOSLinux)Z	win32_dirZ
darwin_dirZ	linux_dirzJpy2exe is no longer supported by yt-dlp; This executable cannot be updatedzSYou cannot update when running from source code; Use git to pull the latest changeszVYou installed yt-dlp from a manual build or with a package manager; Use that to updatezGYou are using an unofficial build of yt-dlp; Build the executable again)r$   r1   r2   otherc                   C  s"   t rt S tt ttrdnd S )Nr2   rc   )r   _NON_UPDATEABLE_REASONSgetrH   r   r   r   r   r   is_non_updateable~   s     rf   c                   C  s   t tt dd d dS )Nzyt-dlp%s)templateignoredefault)r   _FILE_SUFFIXESrH   r   r   r   r   _get_binary_name   s    rk   c            	        s   d\} }t j|krd S t jd d \}}ddtt| d}t j| k r`d| d| d| S d}d	}t }|d
krt  t fdddD r|dd|S d S |dkrt	t
ddd }|dk r|dd|S d S d| d| d| S )N))      )rl   	   r/   zPlease update to Python .z	 or abovezPython version z is no longer supported! z]Support for {} has been deprecated. See  https://github.com/yt-dlp/yt-dlp/{}  for details.
{}z;You may stop receiving updates on this version at any time!)rZ   r[   c                 3  s   | ]}  d | V  qdS )zWindows-N
startswith)r   r`   Zplatform_namer   r   	<genexpr>   s     z*_get_system_deprecation.<locals>.<genexpr>)72008ServerR2zWindows 7/Server 2008 R2zissues/10086)r\   r]   CS_GNU_LIBC_VERSION )r/      zsystem glibc version < 2.31z	pull/8638zSupport for Python version z has been deprecated. )r4   version_inforC   mapstrrH   r:   anyformatr   r7   confstr	partition)	ZMIN_SUPPORTEDZMIN_RECOMMENDEDmajorminorZ
PYTHON_MSGZEXE_MSG_TMPLZSTOP_MSGr_   libc_verr   rr   r   _get_system_deprecation   s*    

r   c              	     sj   t  }ttdttj| ddd2 t fdddD ]}|	d |  q@W 5 Q R X |
 S )Ni   rbr   )	bufferingc                     s
     S r^   )readintor   fmvr   r   <lambda>       z_sha256_file.<locals>.<lambda>)hashlibsha256
memoryview	bytearrayopenr7   r8   realpathiterupdate	hexdigest)r8   hnr   r   r   _sha256_file   s    r   c                 C  s\   d| krt | | }n| }| d| }|rB||krB|d| 7 }|| krX|d|  7 }|S )Nr!   @z build  from )_INVERSE_UPDATE_SOURCESre   )origintagversionZchannellabelr   r   r   _make_label   s    r   c                   @  s\   e Zd ZU dZded< dZded< dZded< dZded< e Z	ded	< dZ
ded
< dZdS )
UpdateInfoa  
    Update target information

    Can be created by `query_update()` or manually.

    Attributes:
        tag                 The release tag that will be updated to. If from query_update,
                            the value is after API resolution and update spec processing.
                            The only property that is required.
        version             The actual numeric version (if available) of the binary to be updated to,
                            after API resolution and update spec processing. (default: None)
        requested_version   Numeric version of the binary being requested (if available),
                            after API resolution only. (default: None)
        commit              Commit hash (if available) of the binary to be updated to,
                            after API resolution and update spec processing. (default: None)
                            This value will only match the RELEASE_GIT_HEAD of prerelease builds.
        binary_name         Filename of the binary to be updated to. (default: current binary name)
        checksum            Expected checksum (if available) of the binary to be
                            updated to. (default: None)
    r{   r   N
str | Noner   requested_versioncommitbinary_namechecksumT)__name__
__module____qualname____doc____annotations__r   r   r   rk   r   r   _has_updater   r   r   r   r      s   
r   c                   @  s  e Zd ZeZeZeZd9ddddZ	e
dd Ze
dd	 Zd:d
dZdd ZdddddZdd ZdddddZdddddZdddddd Zefd!d"Zejd#d$ Zejd%d& Zd'd( Zd)d* Zd;d+d,Zd-d. Zd<d0d1Ze
d2d3 Zd4d5 Z dd6d7d8Z!dS )=UpdaterNr   )targetc                 C  sZ  || _ |p| jd\| _}| _|sJd| jks:| j| jkrJ| j| _d | _n| jsb| jdd | _t|or|| jk| _| jsd| _d| _d| jkr| j| _	| j	
dsB| j	| jkrB| j d| j dd	 d
| j | j	| j jj d| j dd  | d n:| j| j| _	| j	sB| d| jdd| j d t  dt  | _d S )Nr   r!   r   latestFzyt-dlp/zYou are switching to an Z
unofficialZredz executable from z. Run zat your own riskz	light redzLAutomatically restarting into custom builds is disabled for security reasonszInvalid update channel z requested. Valid channels are z, Trw   )ydl_channel
rpartitionrequested_channelrequested_tag_update_sourcesr   bool_exactrequested_reporq   _originreport_warningZ_format_errZStylesZEMPHASIS_block_restartre   _report_errorrC   rH   r   _identifier)selfr   r   sepr   r   r   __init__   s2    :zUpdater.__init__c                 C  s   t S )zCurrent version)r   r   r   r   r   current_version  s    zUpdater.current_versionc                 C  s   t S )zCurrent commit hash)r   r   r   r   r   current_commit  s    zUpdater.current_commitc                 C  s`   |s
| j }|dkrdnd| }d| j d| d| }| jd| d|  | j| S )	Nr   zlatest/downloadz	download/zhttps://github.com/
/releases/r!   zDownloading r   )r   r   r   write_debugurlopenread)r   r`   r   r8   urlr   r   r   _download_asset  s    zUpdater._download_assetc              
   C  sh   |dkrd| n|}t  d| j d| }| jd|  t| jt|dddd	d
 	 S )Nr   tags/r!   r   zFetching release info: zapplication/vnd.github+jsonzyt-dlpz
2022-11-28)Acceptz
User-AgentzX-GitHub-Api-Version)headers)
API_BASE_URLr   r   r   jsonloadsr   r   r   decode)r   r   r   r   r   r   	_call_api!  s    zUpdater._call_apir{   ztuple[str | None, str | None])r   returnc                 C  s   t |r|d fS | |}|dkr.|d }n0tdt j d|dd}|rZ|dnd }tt|ddr||d }n$t	
|d	d}|r|d
nd }|s|s| jddd ||fS )Nr   Ztag_namez\s+(?P<version>z)$r`   r(   r   target_commitishbodyhashzEOne of either version or commit hash must be available on the releaseTexpected)_VERSION_RErW   r   rV   searchpatternre   group_HASH_PATTERN
_COMMIT_REmatchr   )r   r   Zapi_infor   r   r   r   r   r   _get_version_info+  s    



zUpdater._get_version_infoc                 C  s   |D ]t}z| j d|d W   S  tk
rv } z8t|trN|jdkrNW Y q| d|  W Y  d S d }~X Y qX q| d| j d| j	 d d S )NZ_update_specr     zfetch update spec: The requested tag z does not exist for T)
r   r   r
   rA   r	   status_report_network_errorr   r   r   )r   Zsource_tagsr   errorr   r   r   _download_update_specB  s     zUpdater._download_update_spec)lockfileresolved_tagc           	      C  s   |  }tdd |D }|D ]}|rR|d| j ds<q|dd\}}}}n|ds^q|dd\}}}t|| jrt	|r| j
s|  S | ||r|  S n
||krq| d| d	d
  d S q|S )Nc                 s  s   | ]}| d V  qdS )lockV2 Nrp   )r   liner   r   r   rs   R  s     z/Updater._process_update_spec.<locals>.<genexpr>r   rw   rl   zlock r/   zyt-dlp cannot be updated to z) since you are on an older Python versionT)
splitlinesr|   rq   r   splitrV   r   r   r   rW   r   _version_comparer   )	r   r   r   linesZis_version2r   r)   r   r   r   r   r   _process_update_specP  s0    



 zUpdater._process_update_spec)abc                 C  s,   t | d| r$t|t|kS ||kS )zp
        Compare two version strings

        This function SHOULD NOT be called if self._exact == True
        ro   )r   rW   r   )r   r   r   r   r   r   r   m  s    zUpdater._version_compareF_outputzUpdateInfo | None)r   c             
   C  s  | j s| d dS z| | j\}}W n> tk
rf } z | jd| ddd W Y dS d}~X Y nX | jr| j| j krd}n<|r| jr| j|k}q| 	| j| }n|r|| j
k}nd}| jd	kr|n| j}t| j| jd
d p| j| j}t| j ||}| jd	krdnd d| }	|sF|rB| j|	 d| d dS | |rTdnd}
|
sddS | |
|}|r|| jkrdS ||kr|}nt|r|}nd}d}t srz| d|}W nb tk
r* } zBt|tr|jdkr| d|  W Y dS | jd W 5 d}~X Y nHX |  D ]&}|t r8| d } q`q8|sr| jd |rt| j ||}| jd| d|	 ||krd| nd  t|||||kr|nd|dS )z~Fetches info about the available update
        @returns   An `UpdateInfo` if there is an update available, else None
        z3No target repository could be determined from inputNzobtain version info (r    z; Please try again later or)delimTFr   r   r/   ZLatestZ	Requestedz
 version: z
yt-dlp is up to date ()r   Nr^   zSHA2-256SUMSr   zfetch checksums: z@No hash information found for the release, skipping verificationr   zGThe hash could not be found in the checksum file, skipping verificationzCurrent version: 
z
Upgradable to: r(   )r   r   r   r   r   ) r   r   r   r   r
   r   r   r   r   r   r   r   r   r   r   	to_screenr   r   r   rW   rf   r   rA   r	   r   r   r   r   endswithrk   r   r   )r   r   r   r   e
has_updater   Zcurrent_labelZrequested_labelZlatest_or_requestedZupdate_specZ
result_tagZresult_versionr   hashesr   lnupdate_labelr   r   r   query_updatew  s    
"


zUpdater.query_updatec              
   C  s  |t kr| jdd}|sdS t }|r6| |d dS | jdt| j  t| j	|j
|j}| jd| d tj| j}t| jtjs| | jS t|tjs| |S | j d| j d }}t d	kr| jd
 }}z tj|pdrt| W n  tk
r&   | d Y S X z| |j|j
}W n| tk
r } z\t|tr|jdkr| d| j	 d|j
 dd W Y  S | jd| |j
d W Y S d
}~X Y nX |js| d n&t |! |jkr| jd|j
dS z$t"|d}	|	#| W 5 Q R X W n  tk
r8   | | Y S X |rt$| jj%}
zt&| j| W n  tk
r   | d Y S X zt&|| j W n. tk
r   | d t&|| j Y S X t }|'drt(j)t*d| ddt+j,t+j,d nv|rnzt| W n  tk
r,   | d Y nX zt-| j|
 W n, tk
rl   | dt.| j  Y S X | jd|  dS )zUpdate yt-dlp executable to the latest version
        @param update_info  `UpdateInfo | None` as returned by query_update()
        Tr   FzCurrent Build Hash: zUpdating to z ...z.newz.oldr0   Nr(   z Unable to remove the old versionr   r   r   z does not existzfetch updates: r   zPAutomatically restarting into unverified builds is disabled for security reasonszverify the new executablewbzUnable to move current versionz#Unable to overwrite current versionwinz&ping 127.0.0.1 -n 5 -w 1000 & del /F "")shellrM   rN   z0Unable to set permissions. Run: sudo chmod a+rx zUpdated yt-dlp to )/r   r   rf   r   r   r   r   filenamer   r   r   r   r7   r8   r9   accessW_OK_report_permission_errorrH   rF   removeOSErrorr   r   r
   rA   r	   r   r   r   r   r   r   r   r   writestatst_moderenamerq   atexitregisterr   rT   DEVNULLchmodr   )r   Zupdate_infoerrr   	directoryZnew_filenameZold_filenameZ
newcontentr   outfmaskr_   r   r   r   r     s    

 ,
  
zUpdater.updatec                 C  s   t t d S )zFilename of the executabler   )r   rG   r   r   r   r   r    s    zUpdater.filenamec                 C  s(   t tddrtjS t tddr$tjS dS )z0The command-line to run the executable, if known	orig_argvNr"   F)r3   r4   r  rE   r   r   r   r   cmd"  s    zUpdater.cmdc                 C  s<   | j std| jdt| j   t| j \}}}|S )zRestart the executablezMust be frozen or Py >= 3.10zRestarting: )r  AssertionErrorr   r   r   r   rR   )r   r)   
returncoder   r   r   restart+  s    zUpdater.restartc                   s    fdd}|_ d S )Nc                     s   j   ddd jjS )Nz+. Restart yt-dlp to use the updated versionTr   )r   r   _download_retcoder   msgr   r   r   wrapper3  s    z'Updater._block_restart.<locals>.wrapper)r  )r   r  r  r   r  r   r   2  s    zUpdater._block_restartc                 C  s$   | j j||rdnd d d| j _d S )NF)tbd   )r   Zreport_errorr  )r   r  r   r   r   r   r   8  s    zUpdater._report_errorc                 C  s   |  d| dd d S )NzUnable to write to z; try running as administratorT)r   )r   filer   r   r   r  <  s    z Updater._report_permission_error;c              	   C  sH   |s
| j }|dkr|nd| }| d| | d| j d| d d S )Nr   ztag/z
Unable to z visit  https://github.com/r   T)r   r   r   )r   actionr   r   r8   r   r   r   r   ?  s    zUpdater._report_network_errorc                 C  s   | j dkrd| j  S | j S )zMDeprecated; requested tag with 'tags/' prepended when necessary for API callsr   r   )r   r   r   r   r   _target_tagH  s    zUpdater._target_tagc                 C  s   t | jddS )z7Deprecated; report whether there is an update availableTr   )r   r   r   r   r   r   _check_updateM  s    zUpdater._check_update)	attributec           
      C  s   dddd}ddddd	d
}||krD||krDt t| jd|t| j d| d}||kr|| }|ds|d|d7 }| }|}n0|d7 }|  }|dkrtdddd}d|_|}t| | D ]\}}t	||}	t
| ||	 qt	| |S )z0Compat getter function for deprecated attributesr"  r!  r   )Zcheck_updateZ
target_tagZtarget_channelr   r   r   r   r   )r   Znew_versionZlatest_versionZrelease_nameZrelease_hashz object has no attribute ro   z6 is deprecated and will be removed in a future versionr)   z. Please use z insteadz$. Please call query_update() insteadNr(   F)AttributeErrortyper   rq   r   r   r   r   itemsr3   setattr)
r   r#  Zdeprecated_props_mapZupdate_info_props_mapr  Zsource_namer1   mappingZtarget_namer   r   r   r   __getattr__Q  s<    

zUpdater.__getattr__)N)N)F)r  N)"r   r   r   r   r   r   r   UPDATE_SOURCESr   r   propertyr   r   r   r   r   r   r   r   r   r   r   r   cached_propertyr  r  r  r   r   r  r   r!  r"  r)  r   r   r   r   r      s:   &


	

PV



	
r   c                 C  s   t |  S )zUpdate the program file with the latest version from the repository
    @returns    Whether there was a successful update (No update = False)
    )r   r   )r   r   r   r   
run_update{  s    r-  )N)@
__future__r   r  rO   r   r   r7   r:   rV   rT   r4   Zdataclassesr   	zipimportr   compatr   r   Z
networkingr   Znetworking.exceptionsr	   r
   utilsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r*  Z
REPOSITORYr&  r   compiler   r   r   r   ZAPI_URLcacherG   rH   rY   rj   rd   rf   rk   r   r   r   r   r   r-  __all__r   r   r   r   <module>   s   (
 



"	
    