o
    j?àhD  ã                   @   s\   d Z ddlZddlmZmZ ddlZddlZddlZdZG dd„ de	ƒZ
G dd„ deƒZdS )	z* Detection tool for nVidia graphics cards é    N)ÚPopenÚPIPEz)/usr/share/ubuntu-drivers-common/obsoletec                   @   s   e Zd ZdZdS )ÚNoDatadirErrorz4Exception thrown when no modaliases dir can be foundN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r	   r	   ú?/usr/lib/python3/dist-packages/NvidiaDetector/nvidiadetector.pyr   "   s    r   c                   @   sx   e Zd ZdZddefdd„Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚNvidiaDetectiona  
    A simple class to:
      * Detect the available graphics cards
      * See what drivers support them (If they are
        NVIDIA cards). If more than one card is
        available, try to find the highest common
        driver version which supports them all.
        (READ the comments in the code for further
        details)
      * Return the recommended driver version
    Nc                 C   sb   ddi| _ || _|| _|  |¡| _|  ¡  |  ¡  |  ¡  |  ¡  |r)|  	¡  dS t
|  ¡ ƒ dS )a…  
        printonly = if set to None will make an instance
                    of this class return the selected
                    driver.
                    If set to True it won't return
                    anything. It will simply and print
                    the choice.

        verbose   = if set to True will make the methods
                    print what is happening.
        Úcurrentiè  N)Ú _NvidiaDetection__driver_aliasesÚ	printonlyÚverboseÚgetObsoletePackagesÚoldPackagesÚ	detectionÚgetDataÚgetCardsÚremoveUnsupportedÚprintSelectionÚprintÚselectDriver)Úselfr   r   Úobsoleter	   r	   r
   Ú__init__3   s   
zNvidiaDetection.__init__c                 C   s(   | j  ¡ D ]\}}||kr|  S qdS )z7Get the name of a driver from its corresponding integerN)r   Úitems)r   ÚvalueÚkÚvr	   r	   r
   Ú__get_name_from_valueQ   s
   ÿz%NvidiaDetection.__get_name_from_valuec                 C   s:   | j  |¡}|du r| d¡rt| dd¡ƒ}t|ƒ}|S )z2Get the integer associated to the name of a driverNz-serverÚ )r   ÚgetÚendswithÚintÚreplace)r   Únamer   r	   r	   r
   Ú__get_value_from_nameX   s   
z%NvidiaDetection.__get_value_from_namec                 C   sD   g }zdd„ t |ƒ ¡ D ƒ}dd„ |D ƒ}W |S  ty!   Y |S w )z.Read the list of obsolete packages from a filec                 S   s   g | ]}|  ¡ ‘qS r	   )Ústrip©Ú.0Úxr	   r	   r
   Ú
<listcomp>e   s    z7NvidiaDetection.getObsoletePackages.<locals>.<listcomp>c                 S   s   g | ]}|d kr|‘qS )r!   r	   r)   r	   r	   r
   r,   f   s    )ÚopenÚ	readlinesÚIOError)r   r   ÚtempListr	   r	   r
   r   a   s   þþz#NvidiaDetection.getObsoletePackagesc                 C   sâ   g | _ tddgtdd}| ¡ d  d¡}t d¡}t d¡}|D ]M}| |¡}| |¡}|rN| d	¡ 	¡  
¡ }| d
¡ 	¡  
¡ }	|d |	 }
| j  |
¡ q!|rn| d	¡ 	¡  
¡ }| d
¡ 	¡  
¡ }	|d |	 }
| j  |
¡ q!dS )z^
        Detect the models of the graphics cards
        and store them in self.cards
        Úlspciz-nT©ÚstdoutÚuniversal_newlinesr   Ú
z6.*03(80|0[0-2]): *(?P<vendor>.+):(?P<device>.+) \(.+\)z/.*03(80|0[0-2]): *(?P<vendor>.+):(?P<device>.+)ÚvendorÚdeviceú:N)Úcardsr   r   ÚcommunicateÚsplitÚreÚcompileÚmatchÚgroupr(   ÚlowerÚappend)r   Úp1ÚpÚindentifier1Úindentifier2ÚlineÚm1Úm2Úid1Úid2Úidr	   r	   r
   r   k   s(   




€ôzNvidiaDetection.detectionc              
   C   sœ  i | _ t d¡}t d¡}t ¡ D ]¦}|j d¡r(d|jv s(d|jv s(d|jv r)qz|jjd }W n t	t
fy<   Y qw | |j¡}|rK| d¡}n	t d	|j ¡ q|  |¡}zK|r£|| d
¡d d…  dd¡}| d¡D ]2}| | ¡ ¡}	|	s†t d|j|f ¡ qp|	 d¡ ¡ }
|	 d¡ ¡ }| j  |g ¡ |
d | ¡ qpW q ty·   t d|j|f ¡ Y qw t| j  ¡ ƒdkrÌtj ¡  tdƒ dS dS )zi
        Get the data from the modaliases for each driver
        and store them in self.drivers
        zpci:v0000(.+)d0000(.+)svz5nvidia(?:\-driver|)\-([0-9]+)(:?\-server|)(:?\:i386|)únvidia-ÚupdatesÚexperimentalr   Ú
Modaliasesé   z/%s package has unexpected name scheme. Skippingú(Nú)r!   ú,z&Package %s has unexpected modalias: %sé   r8   z*Package %s has invalid modalias header: %sr   Únone)Údriversr<   r=   ÚaptÚCacher&   Ú
startswithÚ	candidateÚrecordÚKeyErrorÚAttributeErrorr>   r?   ÚloggingÚerrorÚ%_NvidiaDetection__get_value_from_nameÚfindr%   r;   Úlstripr@   Ú
setdefaultrA   Ú
ValueErrorÚlenÚkeysÚsysr3   Úflushr   )r   Úvendor_product_reÚ
package_reÚpackageÚmÚpackage_matchÚstripped_package_nameÚdriver_versionÚaliasÚvpr6   Úproductr	   r	   r
   r   Œ   s^   




üÿ
ÿ
ÿ€ÿÿ
þzNvidiaDetection.getDatac                 C   sØ   i | _ g | _	 | jD ]}|d| d¡… dkr(| jr"td| d ƒ | j |¡ q
t| jdd| _		 | jD ]4}d}| j	D ] }|| j| v r\d}| jrRtd	||f ƒ | j  
|g ¡ |¡ q<|si| j  
|g ¡ d
¡ q5d
S )zˆ
        See if the detected graphics cards are NVIDIA cards.
        If they are NVIDIA cards, append them to self.nvidiaCards
        r   r8   Ú10dezNVIDIA card found (rR   T©ÚreverseFzCard %s supported by driver %sN)ÚdriversForCardsÚnvidiaCardsr9   ra   r   r   rA   ÚsortedrV   ÚorderedListrc   )r   ÚcardÚ	supportedÚdriverr	   r	   r
   r   È   s0   
€
	
€€÷zNvidiaDetection.getCardsc                 C   s\   g }| j D ]}d| j | v r| |¡ q|D ]}| jr!td| ƒ | j |¡ | j |= qdS )zf
        Remove unsupported cards from self.nvidiaCards and from
        self.driversForCards
        NzRemoving unsupported card )rv   rA   r   r   rw   Úremove)r   ÚunsupportedCardsrz   Úunsupportedr	   r	   r
   r   ö   s   

€
üz!NvidiaDetection.removeUnsupportedc           
      C   s„  t | jƒ}|dkr¶|dkru	 i }| jD ]}| j| D ]}| |d¡ ||  d7  < qqt|dd}	 g }|D ]}|| |krD| |¡ q7t |ƒdkrc	 |jdd |d }| jrb| jsbt	d| ƒ n-	 |d }| jrt| jstt	d| ƒ n	 | jt
| j ¡ ƒd  d }| jr| jst	d| ƒ 	 |  |¡}	|	dur¨|dkr d	p¡d
t|	ƒ }|S |dkr®d	p¯d
t|ƒ }|S 	 | jr¾t	dƒ d}|S )zZ
        If more than one card is available, try to get the highest common driver
        r   rP   Trt   zRecommended NVIDIA driver: zRecommended NVIDIA driver: %dNi†  znvidia-driver-rL   zNo NVIDIA package to install)re   rw   rv   rc   rx   rA   Úsortr   r   r   Úlistrf   Ú%_NvidiaDetection__get_name_from_valueÚstr)
r   ÚcardsNumberÚ
occurrencerz   ÚdrvÚoccurrencesÚ
candidatesr|   ÚchoiceÚdriver_namer	   r	   r
   r     sZ   
	
þ
€€€
÷	ùzNvidiaDetection.selectDriverc           	   	   C   sÚ   	 g }g }t ddgtdd}| ¡ d }| d¡}|D ]}| d¡dkr.| | d	¡d ¡ qt|tƒrPz| |¡r>	 W |S W |S  t	yO   | |¡ Y |S w |D ]}z| |¡r[	 W qR t	yj   | |¡ Y qRw |S )
zð
        USAGE:
            * pkglist is the list of packages  you want to check
            * use lists for one or more packages
            * use a string if it is only one package
            * lists will work well in both cases
        Údpkgz--get-selectionsTr2   r   r5   z	installéÿÿÿÿú	)
r   r   r:   r;   ra   rA   Ú
isinstancerƒ   Úindexrd   )	r   ÚpkglistÚlinesÚnotinstalledrB   rC   ÚcrF   Úpkgr	   r	   r
   Úcheckpkgd  s<   
€

ôö	ö
€ÿzNvidiaDetection.checkpkgc                 C   s   |   | j¡}t|ƒt| jƒkS )z°
        oldPackages = a list of the names of the obsolete drivers
        notInstalled = a list of the obsolete drivers which are not
                       installed
        )r•   r   re   )r   ÚnotInstalledr	   r	   r
   Ú
getDriversˆ  s   
zNvidiaDetection.getDriversc                 C   sV   |   ¡ }|  ¡ r |rtj ¡  t|ƒ dS tj ¡  tdƒ dS tj ¡  t|ƒ dS )z6
        Part for the kernel postinst.d/ hook
        rU   N)r   r—   rg   r3   rh   r   )r   r|   r	   r	   r
   r   ˜  s   


zNvidiaDetection.printSelection)r   r   r   r   ÚobsoletePackagesPathr   r‚   r`   r   r   r   r   r   r   r•   r—   r   r	   r	   r	   r
   r   &   s    	
!<.^$r   )r   r<   Ú
subprocessr   r   rg   r^   rW   r˜   Ú	Exceptionr   Úobjectr   r	   r	   r	   r
   Ú<module>   s   