a
    ]f_F                     @   s  d Z ddlZddlmZ ddlZddlZddlm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 e
eZdZejereejd< eejed	kZd
ZdZdZdZddddddddZG dd deZdd Z d:ddZ!dd Z"dd Z#d d! Z$d"d# Z%ed$ed%d&Z&e	j'j(dkr^e	j'd'k r^zdd(l)m*Z* W n e+yT   Y n
0 e*e&d)< d*d+ Z,d,d- Z-d.d/ Z.d0d1 Z/d2d3 Z0d4d5 Z1d6d7 Z2d8d9 Z3dS );z
Query Debian's Bug Tracking System (BTS).

This module provides a layer between Python and Debian's BTS. It
provides methods to query the BTS using the BTS' SOAP interface, and the
Bugreport class which represents a bugreport from the BTS.
    N)LooseVersion)datetime)
SoapClient)SimpleXMLElementz/etc/ssl/ca-debianZSSL_CERT_DIRz1.16.2z(https://bugs.debian.org/cgi-bin/soap.cgizDebbugs/SOAP/V1zhttps://bugs.debian.org/i                       )ZcriticalZgraveZseriousZ	importantZnormalminorZwishlistc                   @   sX   e Zd Z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 )	Bugreporta  Represents a bugreport from Debian's Bug Tracking System.

    A bugreport object provides all attributes provided by the SOAP
    interface. Most of the attributes are strings, the others are
    marked.

    Attributes
    ----------

    bug_num : int
        The bugnumber
    severity : str
        Severity of the bugreport
    tags : list of strings
        Tags of the bugreport
    subject : str
        The subject/title of the bugreport
    originator : str
        Submitter of the bugreport
    mergedwith : list of ints
        List of bugnumbers this bug was merged with
    package : str
        Package of the bugreport
    source : str
        Source package of the bugreport
    date : datetime
        Date of bug creation
    log_modified : datetime
        Date of update of the bugreport
    done : boolean
        Is the bug fixed or not
    done_by : str or None
        Name and Email or None
    archived : bool
        Is the bug archived or not
    unarchived : bool
        Was the bug unarchived or not
    fixed_versions : list of strings
        List of versions, can be empty even if bug is fixed
    found_versions : list of strings
        List of version numbers where bug was found
    forwarded : str
        A URL or email address
    blocks: list of ints
        List of bugnumbers this bug blocks
    blockedby : list of int
        List of bugnumbers which block this bug
    pending : str
        Either 'pending' or 'done'
    msgid : str
        Message ID of the bugreport
    owner : str
        Who took responsibility for fixing this bug
    location : str
        Either 'db-h' or 'archive'
    affects : list of str
        List of Packagenames
    summary : str
        Arbitrary text
    c                 C   s   d | _ d | _d | _d | _d | _d | _d | _d | _d | _d | _	d | _
d | _d | _d | _d | _d | _d | _d | _d | _d | _d | _d | _d | _d | _d S N)
originatordatesubjectmsgidpackagetagsdone	forwarded
mergedwithseverityownerfound_versionsfixed_versionsblocks	blockedby
unarchivedsummaryaffectslog_modifiedlocationarchivedbug_numsourcepending)self r)   5/usr/lib/python3/dist-packages/debianbts/debianbts.py__init__w   s0    zBugreport.__init__c                 C   s"   d dd | j D }|d S )N
c                 s   s   | ]\}}d  ||V  qdS )z{}: {}N)format).0keyvaluer)   r)   r*   	<genexpr>   s   z$Bugreport.__str__.<locals>.<genexpr>)join__dict__items)r(   sr)   r)   r*   __str__   s    
zBugreport.__str__c                 C   s   |   |  k S )a  Compare a bugreport with another.

        The more open and urgent a bug is, the greater the bug is:

            outstanding > resolved > archived

            critical > grave > serious > important > normal > minor > wishlist.

        Openness always beats urgency, eg an archived bug is *always*
        smaller than an outstanding bug.

        This sorting is useful for displaying bugreports in a list and
        sorting them in a useful way.

        
_get_valuer(   otherr)   r)   r*   __lt__   s    zBugreport.__lt__c                 C   s   |  | S r   )__gt__r9   r)   r)   r*   __le__   s    zBugreport.__le__c                 C   s   |   |  kS r   r7   r9   r)   r)   r*   r<      s    zBugreport.__gt__c                 C   s   |  | S r   )r;   r9   r)   r)   r*   __ge__   s    zBugreport.__ge__c                 C   s   |   |  kS r   r7   r9   r)   r)   r*   __eq__   s    zBugreport.__eq__c                 C   s   |  | S r   )r?   r9   r)   r)   r*   __ne__   s    zBugreport.__ne__c                 C   s.   | j rd}n| jrd}nd}|t| j 7 }|S )Nr   
      )r$   r   
SEVERITIESr   )r(   valr)   r)   r*   r8      s    zBugreport._get_valueN)__name__
__module____qualname____doc__r+   r6   r;   r=   r<   r>   r?   r@   r8   r)   r)   r)   r*   r   9   s   =!r   c           
      G   s   t | ttfs| g} |r,td | | t }g }tdt| t	D ]d}| ||t	  }t
d}td|| |d|}|d pg D ]}| d }	|t|	 qqF|S )a  Returns a list of Bugreport objects.

    Given a list of bugnumbers this method returns a list of Bugreport
    objects.

    Parameters
    ----------
    nrs : int or list of ints
        The bugnumbers
    additional : int
        Deprecated! The remaining positional arguments are treated as
        bugnumbers. This is deprecated since 2.10.0, please use the
        `nrs` parameter instead.

    Returns
    -------
    bugs : list of Bugreport objects

    zdCalling get_status with bugnumbers as positional arguments is deprecated, please use a list instead.r   z<get_status></get_status>Zarg0
get_status	s-gensym3r   )
isinstancelisttupleloggerwarningextend_build_soap_clientrangelen
BATCH_SIZEr   _build_int_array_elcallchildrenappend_parse_status)
ZnrsZ
additionalsoap_clientZbugsiZslice_	method_elreplyZbug_item_elbug_elr)   r)   r*   rI      s     

rI   c           
      G   s   |du rg }t |ttfs |g}|r8td || td| g|R  }|d}i }| d}|r|j	dkr|
 p|g D ]2}t|d}|d}	d	d
 |	
 pg D ||< q~n4|
 pg D ]&}| }dd
 |
 pg D ||< q|S )a  Get buglists by usertags.

    Parameters
    ----------
    email : str
    tags : list of strings
        If tags are given the dictionary is limited to the matching
        tags, if no tags are given all available tags are returned.
    moretags : str
        Deprecated! The remaining positional arguments are treated as
        tags. This is deprecated since 2.10.0, please use the `tags`
        parameter instead.

    Returns
    -------
    mapping : dict
        a mapping of usertag -> buglist

    NzbCalling get_getusertag with tags as positional arguments is deprecated, please use a list instead.get_usertagrJ   xsi:typezapachens:Mapr/   r0   c                 S   s   g | ]}t |qS r)   intr.   bugr)   r)   r*   
<listcomp>#      zget_usertag.<locals>.<listcomp>c                 S   s   g | ]}t |qS r)   ra   rc   r)   r)   r*   re   '  rf   )rK   rL   rM   rN   rO   rP   _soap_client_call
attributesgetr0   rW   strZget_name)
emailr   Zmoretagsr]   Zmap_elmappingZ	type_attrZ
usertag_eltagZ
buglist_elr)   r)   r*   r_      s(    

r_   c                 C   s   t d| }|d}g }| D ]}i }t|d|d< t|d|d< t|d|d< g |d< tjjtjjd}|	|d 
  |	d
  |	|d 
  | |d	< || q|S )
ad  Get Buglogs.

    A buglog is a dictionary with the following mappings:
        * "header" => string
        * "body" => string
        * "attachments" => list
        * "msg_num" => int
        * "message" => email.message.Message

    Parameters
    ----------
    nr : int
        the bugnumber

    Returns
    -------
    buglogs : list of dicts

    get_bug_logsoapenc:ArrayheaderbodyZmsg_numZattachments)policyz

message)rg   rW   _parse_string_elrb   rk   Z
feedparserZBytesFeedParserrr   ZSMTPZfeedencodecloserX   )Znrr]   items_elZbuglogsZ	buglog_elZbuglogZmail_parserr)   r)   r*   rn   +  s$    
rn   c                 C   s(   t d| }|d}dd | p"g D S )aH  Returns the newest bugs.

    This method can be used to query the BTS for the n newest bugs.

    Parameters
    ----------
    amount : int
        the number of desired bugs. E.g. if `amount` is 10 the method
        will return the 10 latest bugs.

    Returns
    -------
    bugs : list of int
        the bugnumbers

    newest_bugsro   c                 S   s   g | ]}t |qS r)   ra   r.   item_elr)   r)   r*   re   i  rf   znewest_bugs.<locals>.<listcomp>)rg   rW   )Zamountr]   rw   r)   r)   r*   rx   V  s    
rx   c                  O   s   g }|  D ]\}}|||g qt| dkrJt| d trJt| d } | rbtd ||  td}t	|D ]<\}}dt
| }t|ttfrt||| qr||| qrt }	|	d|}
|
d}dd	 | pg D S )
a  Get list of bugs matching certain criteria.

    The conditions are defined by the keyword arguments.

    Arguments
    ---------
    key_value : str
        Deprecated! The positional arguments are treated as key-values.
        This is deprecated since 2.10.0, please use the `kwargs`
        parameters instead.
    kwargs :
        Possible keywords are:
            * "package": bugs for the given package
            * "submitter": bugs from the submitter
            * "maint": bugs belonging to a maintainer
            * "src": bugs belonging to a source package
            * "severity": bugs with a certain severity
            * "status": can be either "done", "forwarded", or "open"
            * "tag": see http://www.debian.org/Bugs/Developer#tags for
               available tags
            * "owner": bugs which are assigned to `owner`
            * "bugs": takes single int or list of bugnumbers, filters the list
               according to given criteria
            * "correspondent": bugs where `correspondent` has sent a mail to
            * "archive": takes a string: "0" (unarchived), "1"
              (archived) or "both" (un- and archived). if omitted, only
              returns un-archived bugs.

    Returns
    -------
    bugs : list of ints
        the bugnumbers

    Examples
    --------
    >>> get_bugs(package='gtk-qt-engine', severity='normal')
    [12345, 23456]

    r   r   z_Calling get_bugs with positional arguments is deprecated, please use keyword arguments instead.z<get_bugs></get_bugs>argget_bugsro   c                 S   s   g | ]}t |qS r)   ra   ry   r)   r)   r*   re     rf   zget_bugs.<locals>.<listcomp>)r4   rP   rS   rK   rL   rM   rN   rO   r   	enumeraterj   rU   ZmarshallrQ   rV   rW   )	key_valuekwargsargskvr\   arg_nZkvZarg_namerZ   r]   rw   r)   r)   r*   r|   l  s$    *

r|   c                 C   sx  t  }dD ]}t||t| | q
tt| d|_tt| d|_dd t| d	 D |_
t| d|_|jrt| dnd|_t| d	|_t| d
|_t| d|_dd t| d	 D |_dd t| d	 D |_dd t| d	 D |_dd | d p"g D |_dd | d p@g D |_dd t| d	dD }dd |D |_|S )z9Return a bugreport object from a given status xml element)r   r   r   r   r   r   r    r#   r&   r'   r   r   r"   c                 S   s   g | ]}|qS r)   r)   )r.   rm   r)   r)   r*   re     rf   z!_parse_status.<locals>.<listcomp>r   r   Nr$   r   r%   c                 S   s   g | ]}t |qS r)   ra   r.   r[   r)   r)   r*   re     rf   r   c                 S   s   g | ]}t |qS r)   ra   r   r)   r)   r*   re     rf   r   c                 S   s   g | ]}t |qS r)   ra   r   r)   r)   r*   re     rf   r   c                 S   s   g | ]}t |qS r)   rj   r.   elr)   r)   r*   re     rf   r   c                 S   s   g | ]}t |qS r)   r   r   r)   r)   r*   re     rf   r   c                 S   s   g | ]}|r|qS r)   r)   )r.   Z_fr)   r)   r*   re     rf   r!   ,c                 S   s   g | ]}|  qS r)   )strip)r.   ar)   r)   r*   re     rf   )r   setattrrt   r   Zutcfromtimestampfloatr   r"   rj   splitr   _parse_boolr   Zdone_byr$   r   rb   r%   r   r   r   rW   r   r   r!   )r^   rd   Zfieldr!   r)   r)   r*   rY     s.    
rY    Zsoap)r#   action	namespaceZsoap_ns)r
   r	   r
   )CA_CERTSZcacertc                 C   s   | t d< dS )zSet proxy for SOAP client.

    You must use this method after import to set the proxy.

    Parameters
    ----------
    proxy_arg : str

    proxyN_soap_client_kwargs)Z	proxy_argr)   r)   r*   set_soap_proxy  s    
r   c                   C   s   t S r   r   r)   r)   r)   r*   get_soap_client_kwargs  s    r   c                   C   s   t f i tS )zFactory method that creates a SoapClient.

    For thread-safety we create SoapClients on demand instead of using a
    module-level one.

    Returns
    -------
    sc : SoapClient instance

    )r   r   r)   r)   r)   r*   rQ     s    rQ   c                  G   s0   g }t | D ]\}}|dt| |f q|S )zConvert arguments to be consumed by a SoapClient method

    Soap client required a list of named arguments:
    >>> _convert_soap_method_args('a', 1)
    [('arg0', 'a'), ('arg1', 1)]

    r{   )r}   rX   rj   )r   	soap_argsr   r{   r)   r)   r*   _convert_soap_method_args  s    r   c                 G   s:   t  }t| }tr t|| | S t|| |g|R  S dS )z!Wrapper to call SoapClient methodN)rQ   r   PYSIMPLESOAP_1_16_2getattr)Zmethod_namer   rZ   r   r)   r)   r*   rg   !  s
    rg   c                 C   sb   | | }|dd |dd |ddt| |D ] }| dt|}|dd q<|S )	zNbuild a soapenc:Array made of ints called `el_name` as a child
    of `parent`zxmlns:soapencz)http://schemas.xmlsoap.org/soap/encoding/r`   ro   zsoapenc:arrayTypezxsd:int[{:d}]itemzxsd:int)Z	add_childZadd_attributer-   rS   rj   )Zel_nameparentZlist_r   r   rz   r)   r)   r*   rU   .  s    
rU   c                 C   s   t | }| dvS )z(parse a boolean value from a xml element)r   0)rj   r   )r   r0   r)   r)   r*   r   <  s    r   c                 C   s@   t | }|  d}|r<|jdkr<t|}|jddd}|S )z.read a string element, maybe encoded in base64r`   zxsd:base64Binaryzutf-8replace)errors)rj   rh   ri   r0   base64Z	b64decodedecode)r   r0   Zel_typer)   r)   r*   rt   B  s    
rt   )N)4rH   r   Zdistutils.versionr   Zemail.feedparserrk   Zemail.policyr   ossysZloggingZpysimplesoapZpysimplesoap.clientr   Zpysimplesoap.simplexmlr   Z	getLoggerrE   rN   Zca_pathpathisdirenviron__version__r   ZURLZNSZBTS_URLrT   rC   objectr   rI   r_   rn   rx   r|   rY   r   version_infomajorZhttplib2r   ImportErrorr   r   rQ   r   rg   rU   r   rt   r)   r)   r)   r*   <module>   sr   	

 -
2+K/