
    i =                         d Z ddlZddlZddlmZ ddlmZmZ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 dd
lmZ ddlmZmZ ddlmZ ereZ ej        e          Z G d d          ZdS )z
Base class for DAV response parsing.

This module contains the shared logic between DAVResponse (sync) and
AsyncDAVResponse (async) to eliminate code duplication.
    N)Iterable)TYPE_CHECKINGAnycast)etree)_Element)dav)BaseElement)error)to_normal_str)_normalize_href_validate_status)_strip_to_multistatusc                   N   e Zd ZU dZdZedz  ed<   dZeed<   dZ	e
ed<   dZeed<   d	Zeed
<   dZeed<   dZeed<   d dddeddfdZedefd            Zdeee         z  fdZdeddfdZdedeeee         edz  f         fdZdeeeeef         f         fdZdeeeeef         f         fdZ	 	 d!dedeeef         dededz  deee         z  dz  f
dZdeeeeef         f         fdZ	 	 	 d"dee         dz  dee         dz  dedz  deeeeef         f         fdZ dS )#BaseDAVResponsez
    Base class containing shared response parsing logic.

    This class provides the XML parsing and response extraction methods
    that are common to both sync and async DAV responses.
    Ntreeheadersr   status _rawF	huge_treereason	davclientresponseResponsereturnc                   	 |j         | _         |j        | _        t                              dt          | j                   z              t                              dt          | j                  z              |j        | _        || _        |r|j	        | _	        | j         
                    dd          	ddg}g d}t          	fd|D                       }t          	fd	|D                       }	r-|s+|s)|j        d
k     r|j        rt          j        d	            	 t          | j         d                   }n# t           t"          t$          f$ r d}Y nw xY w|dk    s| j        s)d| _        d| _        t                              d           n	 t)          j        | j        t)          j        d| j	                            | _        t          j        t0          j        k    r3t                              t)          j        | j        d                     nl# t6          $ r_ |rt          j        t0          j        k    r=|st0          j        }nt0          j        } |dt          | j                  z   d           |r Y nw xY wt;          | d          rt                              | j                   t=          | j        t>                    r!| j                             dd          | _        n:t=          | j        t
                    r | j                             dd          | _        |j        | _        	 tC          |dd          p|j"        | _"        dS # tF          $ r d| _"        Y dS w xY w)a  
        Initialize response from an HTTP response object.

        This shared method extracts headers, status, and parses XML content.
        Both DAVResponse and AsyncDAVResponse should call this from their __init__.

        Args:
            response: The HTTP response object from niquests
            davclient: Optional reference to the DAVClient for huge_tree setting
        zresponse headers: zresponse status: zContent-Typer   ztext/xmlzapplication/xml)z
text/plaintext/calendarzapplication/octet-streamc              3   B   K   | ]}                     |          V  d S N
startswith.0xcontent_types     J/root/projects/butler/venv/lib/python3.11/site-packages/caldav/response.py	<genexpr>z6BaseDAVResponse._init_from_response.<locals>.<genexpr>M   s1      GG0033GGGGGG    c              3   B   K   | ]}                     |          V  d S r    r!   r#   s     r'   r(   z6BaseDAVResponse._init_from_response.<locals>.<genexpr>N   s1      MM1L33A66MMMMMMr)   i  zUnexpected content type: zContent-Lengthr   NzNo content deliveredT)remove_blank_textr   )parserpretty_printz8Expected some valid XML from the server, but got this: 
)exc_infor   s   
   
z

reason_phrase)$r   status_coder   logdebugstrcontentr   r   r   getanytextr   	weirdnessintKeyError
ValueError	TypeErrorr   r   XML	XMLParserlevelloggingDEBUGtostring	Exceptioninfohasattr
isinstancebytesreplacegetattrr   AttributeError)
selfr   r   	xml_typesno_xml_types
expect_xmlexpect_no_xmlcontent_length_logr&   s
            @r'   _init_from_responsez#BaseDAVResponse._init_from_response5   s     '*		&T\):)::;;;		%DK(8(88999$	" 	1&0DN|'';;!23	RRRGGGGYGGGGG
MMMMMMMMM	H	H "	H $s** + OFFFGGG	  .>!?@@NN*i0 	  	  	 NNN	 QdiDIDIII,----L "II ?TT^\\\  	, 9--IIenTYTJJJKKK'    
 % 		W](B(B( -&|&}DSdi..)!%   
   , 4   	<IIdi   $)U++ < I--gu==		DIs++ < I--fd;;	*	!(OTBBUhoDKKK 	 	 	DKKKK	s7   "D= =EE9H A&JJ7M M+*M+c                     t          | d          s3t          j        t          t          | j                  d          | _        t          | j                  S )z,Return the raw response content as a string.r   Tr.   )rI   r   rF   r   r   r   r   r   rO   s    r'   rawzBaseDAVResponse.raw   sI     tV$$ 	UtHdi'@'@tTTTDITY'''r)   c                 *    t          | j                  S )a  
        The general format of inbound data is something like this:

        <xml><multistatus>
            <response>(...)</response>
            <response>(...)</response>
            (...)
        </multistatus></xml>

        but sometimes the multistatus and/or xml element is missing in
        self.tree.  We don't want to bother with the multistatus and
        xml tags, we just want the response list.

        An "Element" in the lxml library is a list-like object, so we
        should typically return the element right above the responses.
        If there is nothing but a response, return it as a list with
        one element.

        (The equivalent of this method could probably be found with a
        simple XPath query, but I'm not much into XPath)
        )_proto_stripr   rX   s    r'   r   z%BaseDAVResponse._strip_to_multistatus   s    , DI&&&r)   c                 $    t          |           dS )a  
        status is a string like "HTTP/1.1 404 Not Found".  200, 207 and
        404 are considered good statuses.  The SOGo caldav server even
        returns "201 created" when doing a sync-report, to indicate
        that a resource was created after the last sync-token.  This
        makes sense to me, but I've only seen it from SOGo, and it's
        not in accordance with the examples in rfc6578.
        N)r   )rO   r   s     r'   validate_statuszBaseDAVResponse.validate_status   s     	     r)   c                    d}d}g }d}t          j        |j        t          j        j        k               |D ]H}|j        t          j        j        k    rFt          j        |            |j        }t          j        |           |                     |           c|j        t          j        j        k    r|rJ t          |j        pd          }|j        t          j
        j        k    r|                    |           |j        dk    r`|                                }t          j        t          |          dk               t          j        |d         j        dk               d}3t          j        d	|           Jt          j        |           |rt          j        d
|v            t          t           |          ||fS )z
        One response should contain one or zero status children, one
        href tag and zero or more propstats.  Find them, assert there
        isn't more in the response and return those three fields
        NFr   z{DAV:}error   r   z&{https://purelymail.com}does-not-existTz$unexpected element found in response404)r   assert_tagr	   r   Statusr;   r]   Hrefr   PropStatappendgetchildrenlenr<   r   r7   )rO   r   r   href	propstats	check_404elemchildrens           r'   _parse_responsezBaseDAVResponse._parse_response   s    $&		hlcl&66777 	N 	NDx3:>))&j)))f%%%$$V,,,,SX\))&tyB77S\---  &&&&]**  ++--c(mmq0111hqko1YYZZZ 		  FMMMMd 	+M%6/***S$F33r)   c                    i | _         i | _        d| j        v r| j        d         | _        |                                 }|D ]}|j        t          j        j        k    r|j        | _	        *t          j        |j        t          j        j        k               |                     |          \  }}}|| j         vri | j         |<   || j        |<   |D ]}d}|                    t          j        j                  }t          j        |du           |U|j        Nt          j        t!          |          dk               |dz  }|                     |j                   d|j        v r|                    t          j        j                  D ]!}|dz  }|D ]}	|	| j         |         |	j        <   "t          j        |t!          |          k               | j         S )zNInternal implementation of find_objects_and_props without deprecation warning.zSchedule-Tagr   Nr_   z 404 )objectsstatusesr   schedule_tagr   rb   r	   	SyncTokenr;   
sync_tokenr   ra   r   rn   findrc   rh   r]   iterfindProp)
rO   	responsesrri   rj   r   propstatcntproptheprops
             r'   _find_objects_and_propsz'BaseDAVResponse._find_objects_and_props   s   79(*T\)) $^ <D..00	 "	4 "	4Au)))"#&M!%3<#33444(,(<(<Q(?(?%T9f 4<''%'T"&,d#
 & 4 4!sz~66fD0111%&+*AM#f++"23331HC((555&+-- $--chl;; B BD1HC#' B B:AT*7;77B cS]]23333#4& |r)   c                 b    t          j        dt          d           |                                 S )aN  Check the response from the server, check that it is on an expected format,
        find hrefs and props from it and check statuses delivered.

        The parsed data will be put into self.objects, a dict {href:
        {proptag: prop_element}}.  Further parsing of the prop_element
        has to be done by the caller.

        self.sync_token will be populated if found, self.objects will be populated.

        .. deprecated::
            Use ``response.results`` instead, which provides pre-parsed property values.
            This method will be removed in a future version.
        zfind_objects_and_props() is deprecated. Use response.results instead, which provides pre-parsed property values from the protocol layer.   )
stacklevel)warningswarnDeprecationWarningr~   rX   s    r'   find_objects_and_propsz&BaseDAVResponse.find_objects_and_props  s=     	Q		
 	
 	
 	
 ++---r)   proptagprops_foundmulti_value_allowedxpathc           	         g }||v r||         }|                                 D ]}|dk    r|d                                                             d          r|d                                         dk    rT|d                                                             d          r|d         dv rt                              d| d	d
                    |           d           |s5t          |          dk    r"|j        r|                    |j                   n|r|nd}|	                    |          }	g }|	D ]e}
t	          j
        |
                                             |
j        r|                    |
j                   K|                    |
j                   f|r|S |sd S t	          j
        t          |          dk               |d         S )Nz,{urn:ietf:params:xml:ns:caldav}calendar-datar   zcontent-typer_   r   version)2z2.0zIf you see this, please add a report at https://github.com/python-caldav/caldav/issues/209 - in _expand_simple_prop, dealing with z, extra item found: =.z.//*)itemslowerendswithr5   r   joinrh   r;   rf   findallra   rb   )rO   r   r   r   r   valuesprop_xmlitem_xpathleafsleafs              r'   _expand_simple_propz#BaseDAVResponse._expand_simple_prop*  s"    k!!"7+H ((  LLLQ00@@! GMMOO>> Aw}}//	:: !tAw,?V?V 		 H  Za  H  H  wz  w  w  @D  wE  wE  H  H  H     0S]]a//= 1MM(-000"'3V ((00! 0 0DMdjjll"2333y 0di0000dh//// 	M tM#f++*+++!9r)   c                      | j         |i |S r    )_expand_simple_props)rO   largskwargss      r'   expand_simple_propsz#BaseDAVResponse.expand_simple_propsW  s    (t(%:6:::r)   propsmulti_value_propsc                    |pg }|pg }t          | d          s|                                  | j        D ]t}| j        |         }|D ]/}|j        
|                     |j        ||          ||j        <   0|D ]0}|j        
|                     |j        ||d          ||j        <   1ut          t          t          t          t          t          f         f         | j                  S )a  
        The find_objects_and_props() will stop at the xml element
        below the prop tag.  This method will expand those props into
        text.

        Executes find_objects_and_props if not run already, then
        modifies and returns self.objects.
        rp   N)r   T)r   r   )rI   r~   rp   rb   r   r   dictr7   )rO   r   r   r   ri   r   r|   s          r'   r   z$BaseDAVResponse._expand_simple_propsZ  s    -3tY'' 	+((***L 	 	D,t,K e e8#(,(@(@;^c(@(d(dDH%%)  8#(,(@(@HkD )A ) )DH%%	 Dd38n,-t|<<<r)   r    )FN)NNN)!__name__
__module____qualname____doc__r   r   __annotations__r   r   r   r=   r   r   boolr   r7   r   rV   propertyrY   listr   r]   tuplern   r   r~   r   r   r   r   r
   r    r)   r'   r   r   $   s          !D(T/   GSFCOOOD#NNNItFCIsY YJ Y3 YRV Y Y Y Yv (S ( ( ( X('x$x.'@ ' ' ' '0	!c 	!d 	! 	! 	! 	!'4 '4U3XPSVZPZ;Z5[ '4 '4 '4 '4V-c4X3F.F)G - - - -^.S$sH}2E-E(F . . . .4 %* ) )) #x-() "	)
 Tz) 
tCy4	) ) ) )Z;tCc3h<O7P ; ; ; ;
 /326 	"= "=$t+"= $C=4/"= Tz	"=
 
c4S>!	""= "= "= "= "= "=r)   r   )r   rD   r   collections.abcr   typingr   r   r   lxmlr   
lxml.etreer   caldav.elementsr	   caldav.elements.baser
   
caldav.libr   caldav.lib.python_utilitiesr   caldav.protocol.xml_parsersr   r   r   r[   r   	getLoggerr   r5   r   r   r)   r'   <module>r      sd      $ $ $ $ $ $ + + + + + + + + + +                   , , , , , ,       5 5 5 5 5 5               Hg!!X= X= X= X= X= X= X= X= X= X=r)   