
    i3                    J   d 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m	Z	m
Z
mZ ddlmZmZmZmZ ddlZ	 ddlm
Z
 e
eez           Zn#  Y nxY werddlmZ d	d
lm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m Z m!Z!m"Z"m#Z# d	dl$m%Z% d	dl&m'Z'm(Z( d	dl)m*Z*m+Z+ d	dl,m-Z- d	dl.m/Z/  edd          Z0 ej1        d          Z2 G d de%          Z3 G d de%          Z4 G d de%          Z5 G d de5          Z6 G d  d!e6          Z7 G d" d#e6          Z8 G d$ d%          Z9dS )&az  
I'm trying to be consistent with the terminology in the RFCs:

CalendarSet is a collection of Calendars
Calendar is a collection of CalendarObjectResources
Principal is not a collection, but holds a CalendarSet.

There are also some Mailbox classes to deal with RFC6638.

A SynchronizableCalendarObjectCollection contains a local copy of objects from a calendar on the server.
    N)datetime)sleep)TYPE_CHECKINGAnyOptionalTypeVar)ParseResultSplitResultquoteunquote)r   )vCalAddress   )	DAVClientCalDAVSearcher)IterableIteratorSequence)Literal)CalendarObjectResourceEventFreeBusyJournalTodo)	DAVObject)cdavdav)errorvcal)to_wire)URL_CCr   )boundcaldavc                      e Zd ZdZded         fdZded         fdZded         fdZded         fdZ	 	 	 	 dd	e	dz  d
e	dz  de
dz  de	dz  ddf
dZ	 	 	 	 dd	e	dz  d
e	dz  de
dz  de	dz  ddf
dZdd	e	dz  d
e	dz  ddfdZdS )CalendarSetz.
    A CalendarSet is a set of calendars.
    returnCalendarc                 B     ddl m}  ||          } fd|D             S )z2Convert PropfindResult list into Calendar objects.r   )(_extract_calendars_from_propfind_resultsc           	      `    g | ]*}t          j        |j        |j        |j                   +S ))clienturlnameidparent)r(   r,   r-   r.   cal_id).0infoselfs     L/root/projects/butler/venv/lib/python3.11/site-packages/caldav/collection.py
<listcomp>z7CalendarSet._calendars_from_results.<locals>.<listcomp>D   sE     
 
 
 DKTXDI$+^bccc
 
 
    )!caldav.operations.calendarset_opsr*   )r4   resultsr*   calendar_infoss   `   r5   _calendars_from_resultsz#CalendarSet._calendars_from_results=   s_    	
 	
 	
 	
 	
 	
 BA'JJ
 
 
 
&
 
 
 	
r7   c                     | j         r|                                 S | j                            t	          | j                  | j        j        d          }|                     |j                  S )a  
        List all calendar collections in this set.

        For sync clients, returns a list of Calendar objects directly.
        For async clients, returns a coroutine that must be awaited.

        Returns:
         * [Calendar(), ...]

        Example (sync):
            calendars = calendar_set.get_calendars()

        Example (async):
            calendars = await calendar_set.get_calendars()
        r   propsdepth)	is_async_client_async_calendarsr,   propfindstrr-   CALENDAR_LIST_PROPSr;   r9   r4   responses     r5   get_calendarszCalendarSet.get_calendarsI   sj       	+((***;''MM!@ ( 
 
 ++H,<===r7   c                    K   | j                             t          | j                  | j         j        d           d{V }|                     |j                  S )z(Async implementation of get_calendars().r   r=   N)r,   rB   rC   r-   rD   r;   r9   rE   s     r5   rA   zCalendarSet._async_calendarsa   sm      --MM!@ . 
 
 
 
 
 
 
 
 ++H,<===r7   c                 *    |                                  S z
        Deprecated: Use :meth:`get_calendars` instead.

        This method is an alias kept for backwards compatibility.
        rG   r4   s    r5   	calendarszCalendarSet.calendarsh        !!###r7   Nr.   r1    supported_calendar_component_setmethodc                     | j         r|                     ||||          S t          | j        || ||                              |          S )ax  
        Utility method for creating a new calendar.

        Args:
          name: the display name of the new calendar
          cal_id: the uuid of the new calendar
          supported_calendar_component_set: what kind of objects
           (EVENT, VTODO, VFREEBUSY, VJOURNAL) the calendar should handle.
           Should be set to ['VTODO'] when creating a task list in Zimbra -
           in most other cases the default will be OK.
          method: 'mkcalendar' or 'mkcol' - usually auto-detected

        For async clients, returns a coroutine that must be awaited.

        Returns:
          Calendar(...)-object
        r.   r0   r/   rO   rP   )r@   _async_make_calendarr(   r,   saver4   r.   r1   rO   rP   s        r5   make_calendarzCalendarSet.make_calendarp   se    0  	e,,T6;[]cdddK-M
 
 
 $f$

	r7   c                 p   K   t          | j        || ||          }|                    |           d{V S )&Async implementation of make_calendar.rR   rS   N)r(   r,   _async_save)r4   r.   r1   rO   rP   calendars         r5   rT   z CalendarSet._async_make_calendar   sX       K-M
 
 
 )))888888888r7   c                 p   |r7|s5|                                  D ] }|                                }||k    r|c S !|r!|st          j        d| d| j                   |s4|s2|                                  }|st          j        d          |d         S | j        t          d          |t          d          t          t          j	        |          
                                                              t          | j        j        
                                                    r | j        j                            |          }nt          |t                    s?t          |t                    r[|                    d          s|                    d	          r1| j        t          d
          | j                            |          }nQ| j        t          d
          |t          d          | j                            t          |          dz             }t          | j        || ||          S )ac  
        The calendar method will return a calendar object.  If it gets a cal_id
        but no name, it will not initiate any communication with the server

        Args:
          name: return the calendar with this display name
          cal_id: return the calendar with this calendar id or URL

        Returns:
          Calendar(...)-object
        zNo calendar with name z found under zno calendars foundr   N%Unexpected value None for self.clientz Unexpected value None for cal_idzhttps://zhttp://"Unexpected value None for self.url/)r.   r0   r-   r/   )rG   get_display_namer   NotFoundErrorr-   r,   
ValueErrorrC   r!   	objectify	canonical
startswithjoin
isinstancer   r(   )r4   r.   r1   r[   display_namecalsr-   s          r5   r[   zCalendarSet.calendar   sE     	$ 	$ ..00 $ $'88::4''#OOO ( 	^ 	^%&\t&\&\RVRZ&\&\]]] 	d 	%%''D @)*>???7N;DEEE>?@@@s}V$$..0011<<SAZAZA\A\=]=]^^ 	5+/&&v..CC$$ 	5vs##	5"":..	5282C2CI2N2N	5 x !EFFF(--''CCx !EFFF~ !CDDD(--f 344C$tPPPPr7   NNNNNN)__name__
__module____qualname____doc__listr;   rG   rA   rM   rC   r   rW   rT   r[    r7   r5   r&   r&   8   s        

$z2B 

 

 

 

>tJ/ > > > >0>Z(8 > > > >$4
+ $ $ $ $  !7;!! !Dj! d
! +.*	!
 d
! 
! ! ! !J  !7;!9 9Dj9 d
9 +.*	9
 d
9 
9 9 9 9"3Q 3QS4Z 3Qd
 3Qj 3Q 3Q 3Q 3Q 3Q 3Qr7   r&   c                       e Zd ZdZ	 	 	 d!ded         deez  ez  ez  dz  dedz  de	ddf
 fd	Z
e	 	 d"dddeez  ez  ez  dz  dedz  dd fd
            Z	 	 	 	 d#dedz  dedz  de	dz  ddfdZ	 	 	 	 d#dedz  dedz  de	dz  ddfdZd$dZ	 	 	 d!dedz  dedz  dedz  ddfdZd%dZed             Zej        d&d            Zded         fdZded         fdZd Zdeedz           fdZd'dZd(d Z xZS ))	Principala!  
    This class represents a DAV Principal. It doesn't do much, except
    keep track of the URLs for the calendar-home-set, etc.

    A principal MUST have a non-empty DAV:displayname property
    (defined in Section 13.2 of [RFC2518]),
    and a DAV:resourcetype property (defined in Section 13.9 of [RFC2518]).
    Additionally, a principal MUST report the DAV:principal XML element
    in the value of the DAV:resourcetype property.

    (TODO: the resourcetype is actually never checked, and the DisplayName
    is not stored anywhere)
    Nr,   r   r-   calendar_home_setkwargsr'   c                 $   || _          t          t          |           j        d||d| || j        t          d          | j        j        | _        |                     t          j	                              }|[t                              d           t                              d           t                              d| j        j        z             | j        j                            t          j        |                    | _        dS dS )a  
        Returns a Principal.

        End-users usually shouldn't need to construct Principal-objects directly.  Use davclient.principal() to get the principal object of the logged-in user  and davclient.principals() to get other principals.

        Args:
          client: a DAVClient() object
          url: The URL, if known.
          calendar_home_set: the calendar home set, if known

        If url is not given, deduct principal path as well as calendar home set
        path from doing propfinds.
        r,   r-   Nr]   "calendar server lacking a feature:)current-user-principal property not foundz assuming %s is the principal URLrq   )_calendar_home_setsuperrs   __init__r,   rb   r-   get_propertyr   CurrentUserPrincipallogwarningrf   r!   rc   )r4   r,   r-   rt   ru   cup	__class__s         r5   r|   zPrincipal.__init__   s    ( #4'i'Iv3II&III;{" !HIII{DH##C$<$>$>??C{@AAAGHHH>PQQQ{++CM#,>,>??DHHH ;r7   c                   K    | ||p|j         |          }||                    t          j                               d{V }|Xt                              d           t                              d           t                              d|j          d           n1|j                             t          j        |                    |_         |S )ap  
        Create a Principal, discovering URL if not provided.

        This is the recommended way to create a Principal with async clients
        as it handles async URL discovery.

        For sync clients, you can use the regular constructor: Principal(client)

        Args:
            client: A DAVClient or AsyncDAVClient instance
            url: The principal URL (if known)
            calendar_home_set: The calendar home set URL (if known)

        Returns:
            Principal with URL discovered if not provided

        Example (async):
            principal = await Principal.create(async_client)
        )r,   r-   rt   Nrx   ry   z	assuming z is the principal URL)	r-   _async_get_propertyr   r~   r   r   rf   r!   rc   )clsr,   r-   rt   	principalr   s         r5   createzPrincipal.create  s      6 C!vz/
 
 
	 ;!55c6N6P6PQQQQQQQQC{@AAAGHHHI
IIIJJJJ &
c0B0B C C	r7   r.   r1   rO   r(   c                 |    | j         r|                     ||||          S | j                            ||||          S )z
        Convenience method, bypasses the self.calendar_home_set object.
        See CalendarSet.make_calendar for details.

        For async clients, returns a coroutine that must be awaited.
        rO   rP   )r@   rT   rt   rW   rV   s        r5   rW   zPrincipal.make_calendar;  sX      	e,,T6;[]cddd%33-M	 4 
 
 	
r7   c                 x   K   |                                   d{V }|                    ||||           d{V S )rY   Nr   )_async_get_calendar_home_setrT   )r4   r.   r1   rO   rP   rt   s         r5   rT   zPrincipal._async_make_calendarR  ss       #'"C"C"E"EEEEEEE&;;-M	 < 
 
 
 
 
 
 
 
 	
r7   r&   c                    K   | j         r| j         S |                     t          j                               d{V }|d|v rd|vrt	          |          }|| _        | j         S )z*Async helper to get the calendar home set.N@://)rz   r   r   CalendarHomeSetr   rt   r4   calendar_home_set_urls     r5   r   z&Principal._async_get_calendar_home_setb  s      " 	+**&*&>&>t?S?U?U&V&V V V V V V V!-,,,222$)*?$@$@!!6&&r7   cal_urlc                     |s| j                             ||          S | j        t          d          t	          | j        | j        j                            |                    S )z
        The calendar method will return a calendar object.
        It will not initiate any communication with the server.
        Nr]   )r-   )rt   r[   r,   rb   r(   r-   rf   )r4   r.   r1   r   s       r5   r[   zPrincipal.calendaru  sd      	L)224@@@{" !HIIIDKT[_-A-A'-J-JKKKKr7   r   c                     ddl m}m} |                                 }|                                 }|                     t          j                              } ||d                   } ||          |j        d<    ||          |j        d<   |S )zL
        Returns the principal, as an icalendar.vCalAddress object.
        r   )r   vTextcncutype)		icalendarr   r   r`   calendar_user_address_setr}   r   CalendarUserTypeparams)r4   r   r   r   idsr   rets          r5   get_vcal_addresszPrincipal.get_vcal_address  s     	10000000""$$,,..""4#8#:#:;;k#a&!! 599
4$uV}}
8
r7   c                     | j         sF|                     t          j                              }|d|v rd|vrt	          |          }|| _        | j         S )Nr   r   )rz   r}   r   r   r   rt   r   s     r5   rt   zPrincipal.calendar_home_set  sj    & 	;$($5$5d6J6L6L$M$M!
 &1000!666(-.C(D(D%%:D"&&r7   c                 6   t          |t                    r	|| _        d S t          j        |          }|-|j        r&|j        | j        j        j        k    r|| j        _        t          | j        | j        j                            |                    | _        d S N)	rg   r&   rz   r!   rc   hostnamer,   r-   rf   )r4   r-   sanitized_urls      r5   rt   zPrincipal.calendar_home_set  s    c;'' 	&)D#Fc** $% 	0-*@DKOD\*\*\ #0"-dk4;?;O;OP];^;^"_"_r7   c                 6    | j                             |           S )a]  
        Return the principal's calendars.

        For sync clients, returns a list of Calendar objects directly.
        For async clients, returns a coroutine that must be awaited.

        Example (sync):
            calendars = principal.get_calendars()

        Example (async):
            calendars = await principal.get_calendars()
        )r,   rG   rL   s    r5   rG   zPrincipal.get_calendars  s     {((...r7   c                 *    |                                  S rJ   rK   rL   s    r5   rM   zPrincipal.calendars  rN   r7   c                    t          j                    }|                    dd           |                    dd           |                    dd           t          j                    }t          j                    }|                    d|           |                    dt          j                               |                    d	|           |                    d
|           |                    |           | 	                                }t          ||          }|
                                 |D ]}	|                    |	d           | j                            |j        |j        ddi          }
|
                                S )zYSends a freebusy-request for some attendee to the server
        as per RFC6638.
        prodidz-//tobixen/python-caldav//ENversionz2.0rP   REQUESTuiddtstampdtstartdtenddatar0   T)no_default_parameterszContent-Typeztext/calendar; charset=utf-8)headers)r   r(   adduuiduuid1r   r   nowadd_componentschedule_outboxadd_organizeradd_attendeer,   postr-   r   _find_objects_and_props)r4   r   r   	attendeesfreebusy_icalr   freebusy_compoutbox	caldavobjattendeerF   s              r5   freebusy_requestzPrincipal.freebusy_request  s   
 "*,,($BCCC)U+++(I...jll!*,,%%%%)X\^^444)W---'5)))##M222%%''-???	!!!! 	I 	IH""84"HHHH;##JN#%CD $ 
 

 //111r7   c                     |                      t          j                    d          }|t          j        d          d |D             rJ t          |          }|                    d            d |D             S )	z$
        defined in RFC6638
        F)parse_propsNz,No calendar user addresses given from serverc                 T    g | ]%}|j         t          j                    j         k    #|&S rq   )tagr   Hrefr2   xs     r5   r6   z7Principal.calendar_user_address_set.<locals>.<listcomp>  s,    EEE!QUchjjn-D-DA-D-D-Dr7   c                 J    t          |                     dd                     S )N	preferredr   )intget)r   s    r5   <lambda>z5Principal.calendar_user_address_set.<locals>.<lambda>  s    c!%%Q*?*?&@&@%@ r7   )keyc                     g | ]	}|j         
S rq   )textr   s     r5   r6   z7Principal.calendar_user_address_set.<locals>.<listcomp>   s    ***1***r7   )r}   r   CalendarUserAddressSetr   ra   rp   sort)r4   
_addresses	addressess      r5   r   z#Principal.calendar_user_address_set  s     '+&7&7'))u '8 '
 '

 %&TUUUEEzEEEEEE$$	 	@@AAA**	****r7   ScheduleInboxc                 "    t          |           S )zC
        Returns the schedule inbox, as defined in RFC6638
        r   )r   rL   s    r5   schedule_inboxzPrincipal.schedule_inbox  s     t,,,,r7   ScheduleOutboxc                 "    t          |           S )zD
        Returns the schedule outbox, as defined in RFC6638
        r   )r   rL   s    r5   r   zPrincipal.schedule_outbox  s     ----r7   NNNrk   rj   )r'   r&   )r'   r   r'   N)r'   r   )r'   r   )rl   rm   rn   ro   r   rC   r	   r
   r!   r   r|   classmethodr   rW   rT   r   r[   r   propertyrt   setterrp   rG   rM   r   r   r   r   __classcell__r   s   @r5   rs   rs      s5          )-<@(,	#@ #@%#@ ;,s2T9#@ :	#@
 #@ 
#@ #@ #@ #@ #@ #@J  =A(,	* ** ;,s2T9* :	*
 
* * * [*\  !7;
 
Dj
 d

 +.*	
 

 
 
 
2  !7;
 
Dj
 d

 +.*	
 

 
 
 
 ' ' ' '*  !"	L LDjL d
L t	L
 
L L L L$    ' ' X' ` ` ` `*/tJ/ / / / / $4
+ $ $ $ $2 2 2:+4d
+; + + + +$- - - -. . . . . . . .r7   rs   c                       e Zd ZdZ	 	 	 	 	 	 dcded         deez  ez  ez  dz  ded         dedz  d	edz  d
df fdZ		 dd	 dedZ
	 dd	 dedZ fdZd Zd
ee         fdZded
dfdZd Z	 	 	 dfdee         dedz  deded
df
dZdgdZdhdZdidZdjd Zdkd!Zdhd"Zdid#Zdjd$Zdld%Zdld&Z dmd'e!e         d(ed
e!e         fd)Z"dmd'e!e         d(ed
e!e#         fd*Z$	 dmd'e!e         d(ed
ee%eef                  fd+Z&d, Z'	 	 	 	 dnd/e(d0e(dz  d1dd2ee)d.         z  d3ed
e*d4         fd5Z+	 dod6Z,	 dod7Z-dpd9Z.	 	 	 	 	 	 	 	 dqd;ed<ed=ed>ed?ee/j0                 dz  d
ee#         fd@Z1d/e(d0e(d
dAfdBZ2	 	 	 drdDe*e         dEedFedz  d
ed         fdGZ3d
ed         fdHZ4dI Z5dldJedz  d
dfdKZ6	 	 dsdLedMe/j7        dz  dNed4         d
dfdOZ8dLed
d4fdPZ9dLed
d4fdQZ:dLed
d4fdRZ;dtdSZ<dLed
d4fdTZ=dLed
d4fdUZ>dLed
d4fdVZ?e=Z@d
ed         fdWZAd
ed         fdXZBdYed4         d
efdZZC	 	 	 dfd[edz  d\ed]ed
d^fd_ZDdud`ZEeEZFeDZGd
ed         fdaZHd
ed         fdbZI xZJS )vr(   z
    The `Calendar` object is used to represent a calendar collection.
    Refer to the RFC for details:
    https://tools.ietf.org/html/rfc4791#section-5.3.1
    Nr,   r   r-   r0   r   r.   r/   r'   c           
      H     t                      j        d||||||d| dS )a  
        Initialize a Calendar object.

        Args:
            client: A DAVClient instance
            url: The url for this calendar. May be a full URL or a relative URL.
            parent: The parent object (typically a CalendarSet or Principal)
            name: The display name for the calendar (stored in props cache)
            id: The calendar id (used when creating new calendars)
            props: A dict with known properties for this calendar
        )r,   r-   r0   r/   r>   r.   Nrq   )r{   r|   )	r4   r,   r-   r0   r.   r/   r>   extrar   s	           r5   r|   zCalendar.__init__  sI    * 	 	
s6bD	
 	
TY	
 	
 	
 	
 	
r7   c                    | j         r|                     ||||          S | t          t          j                              }|| _        |k| j        rb| j        j                            dt                    }|d         dvrt          j        d          |d         dk    r|d         d	k    rd
}nd}nd}| j        j                            |dz             }|| _        t          j                    }|rt          j        |          }||gz  }|r4t%          j                    }	|D ]}
|	t%          j        |
          z  }	||	z  }|d
k    r=|t          j                    t          j                    t%          j                    gz   z  }t          j                    |z   }|d
k    rt          j                    nt%          j                    |z   }|                     |||d          }|r|	 |                     |g           dS # t:          $ rV 	 |                                 }t          j        ||k               Y dS #  t@          !                    dd           Y Y dS xY ww xY wdS )z
        Create a new calendar with display name `name` in `parent`.

        For async clients, returns a coroutine that must be awaited.
        Ncreate-calendarreturn_typesupportfullfragilequirk>Creation of calendars (allegedly) not supported on this serverr   	behaviourmkcol-requiredmkcol
mkcalendarr_      rootquery_methodr-   expected_return_valueDcalendar server does not support display name on calendar?  IgnoringTexc_info)"r@   _async_createrC   r   r   r/   r,   featuresis_supporteddictr   MkcalendarErrorr0   r-   rf   r   PropDisplayNamer   SupportedCalendarComponentSetCompResourceType
Collectionr(   SetMkcol
Mkcalendar_queryset_properties	Exceptionr`   assert_r   r   )r4   r.   r/   rO   rP   	supportedpathproprh   sccssccsetr   rcurrent_display_names                  r5   _createzCalendar._create/  s     	Z%%dB0PRXYYY:TZ\\""B>{ & K0==>O]a=bb	Y'/KKK/X   Y'722y7MQa7a7a$FF)FF%{##BH-- xzz 	?400L D , 	577D7 ' '	#&DLDWC$&&#.*:*:DMOO)LLLDgii$ &' 1 1t7H7HCOKKUTY\K]]  	##\N33333 	 	 	+/+@+@+B+B(M"6$">??????KK^!%         		 	s$   (H   
I ,H::II I c                   K   | t          t          j                              }|| _        |k| j        rb| j        j                            dt                    }|d         dvrt          j	        d          |d         dk    r|d         d	k    rd
}nd}nd}| j
        j                            |dz             }|| _        t          j                    }|rt          j        |          }||gz  }|r4t!          j                    }	|D ]}
|	t!          j        |
          z  }	||	z  }|d
k    r=|t          j                    t          j                    t!          j                    gz   z  }t          j                    |z   }|d
k    rt          j                    nt!          j                    |z   }|                     |||d           d{V  |r	 |                     |g           d{V  dS # t6          $ rn 	 |                     t          j                               d{V }t          j        ||k               Y dS #  t<                              dd           Y Y dS xY ww xY wdS )z Async implementation of _create.Nr   r   r   r   r   r   r   r   r   r   r_   r   r   r   Tr   ) rC   r   r   r/   r,   r   r   r   r   r   r0   r-   rf   r   r  r  r   r  r  r  r  r(   r  r  r	  _async_query_async_set_propertiesr  r   r  r   r   )r4   r.   r/   rO   rP   r  r  r  rh   r  r  r  r   r  s                 r5   r   zCalendar._async_createz  s      :TZ\\""B>{ & K0==>O]a=bb	Y'/KKK/X   Y'722y7MQa7a7a$FF)FF%{##BH--xzz 	?400L D , 	577D7 ' '	#&DLDWC$&&#.*:*:DMOO)LLLDgii$ &' 1 1t7H7HCOVS   
 
 	
 	
 	
 	
 	
 	
 	

  	
00,@@@@@@@@@@@   151I1I#/J[J[1\1\+\+\+\+\+\+\(M"6$">??????KK^!%         	 	s%   G/ /
I':AII#I'#I'c                    | j         r|                                 S | j        j                            dt
                    }| j        j                            d           }|d         dk    rt          dd          D ]u}	 t                                                       n# t          j
        $ r Y nw xY w	 |                                 }t          d           ^# t          j        $ r d}Y  nw xY w|r-|                                 D ]}|                                 dS t                                                       dS )	zcDelete the calendar.

        For async clients, returns a coroutine that must be awaited.
        delete-calendarr   r   r      333333?FN)r@   _async_calendar_deleter,   r   r   r   ranger{   deleter   DeleteError
get_eventsr   ra   search)r4   
quirk_infowiper   r   s       r5   r   zCalendar.delete  sb   
  	1..000 [)667H$OO
;'445FGGGi I--1b\\ 
 
GGNN$$$$(   D))A#JJJJ*    DEE  	[[]]  



  GGNNs$    B""B43B48#CC10C1c                   K   ddl }| j        j                            dt                    }| j        j                            d           }|d         dk    rt          dd          D ]}	 |                                  d{V  n# t          j        $ r Y nw xY w	 | 	                    d           d{V  |
                    d	           d{V  l# t          j        $ r d
}Y  nw xY w|r9| 	                                 d{V D ]}|                                 d{V  dS |                                  d{V  dS )z*Async implementation of Calendar.delete().r   Nr  r   r   r  T)eventr  F)asyncior,   r   r   r   r  _async_deleter   r!  r#  r   ra   )r4   r(  r$  r%  _objs         r5   r  zCalendar._async_calendar_delete  s     [)667H$OO
;'445FGGGi I--1b\\ 
 
,,..........(   D++D+111111111!--,,,,,,,,,,*    DEE  	'![[]]****** * *''))))))))))* * $$&&&&&&&&&&&s$   +BBB7CC)(C)c                    | j         t          d          t          j                    g}|                     |d          }|j        rB|j        D ]8}|j                            t          j                    j                  }|r|c S 9g S |	                                }|t          | j         j                           t          j                    j                 }d |D             S )z
        returns a list of component types supported by the calendar, in
        string format (typically ['VJOURNAL', 'VTODO', 'VEVENT'])
        Nr^   F)parse_response_xmlc                 8    g | ]}|                     d           S )r.   )r   )r2   r  s     r5   r6   z5Calendar.get_supported_components.<locals>.<listcomp>  s$    <<<)	f%%<<<r7   )r-   rb   r   r  get_propertiesr9   
propertiesr   r   r   r   r  )r4   r>   rF   result
componentsresponse_listr  s          r5   get_supported_componentsz!Calendar.get_supported_components  s    
 8ABBB3556&&u&GG  	"* & &#.2243U3W3W3[\\
 &%%%%&I !88::WTX]334T5W5Y5Y5]^<<t<<<<r7   icalc                 *    |                      |          || j                  }| |_        |                                 |D ]} |j        |fi | |j                            d          d         d         |_        |                                 |S )z
        sends a schedule request to the server.  Equivalent with add_event, add_todo, etc,
        but the attendees will be added to the ical object before sending it to the server.
        )r   r,   veventr   r   )	_calendar_comp_class_by_datar,   r0   r   r   icalendar_instancewalkr/   rU   )r4   r5  r   attendeeoptionsr+  r   s         r5   save_with_inviteszCalendar.save_with_invites
  s     6d//554TTT
! 	: 	:HCX999999',,X66q9%@



r7   c                     |s;t          |t                    st          |t                    r/dt          |          vr|r	d|vr||d<   t	          j        dd|i|S |S )Ns   BEGIN:VCALENDARical_fragmentobjtyperq   )rg   rC   bytesr    r   create_ical)r4   r5  r?  	ical_datas       r5   _use_or_create_icszCalendar._use_or_create_ics  s     	Bc""	B&0u&=&=	B"'$--77  2y88-1	/*#AAGAyAAAr7   Fobjclassno_overwrite	no_createCalendarResourceObjectc           
      "    || j          | j        |fdd|j                                         i||           }| j        r|                     |||          S |                    ||          }|j        |                    d           |S )aG  Add a new calendar object (event, todo, journal) to the calendar.

        This method is for adding new content to the calendar.  To update
        an existing object, fetch it first and use ``object.save()``.

        Args:
          objclass: Event, Journal or Todo
          ical: ical object (text, icalendar or vobject instance)
          no_overwrite: existing calendar objects should not be overwritten
          no_create: don't create a new object, existing calendar objects should be updated
          dtstart: properties to be inserted into the icalendar object
          dtend: properties to be inserted into the icalendar object
          summary: properties to be inserted into the icalendar object
          alarm_trigger: when given, one alarm will be added
          alarm_action: when given, one alarm will be added
          alarm_attach: when given, one alarm will be added

        Note that the list of parameters going into the icalendar
        object and alarms is not complete.  Refer to the RFC or the
        icalendar library for a full list of properties.
        r?  Vr   rE  rF  NTfix)	r,   rC  rl   upperr@   _async_add_object_finishrU   r-   _handle_reverse_relations)r4   rD  r5  rE  rF  rB  os          r5   
add_objectzCalendar.add_object$  s    @ HK(( =("3"9"9";";==AJ  
 
 
  	d00Yb0cccFF	FBB 5''D'111r7   c                 ~   K   |                     ||           d{V }|j        |                    d           |S )zLAsync helper for add_object(): awaits save() then handles reverse relations.rJ  NTrK  )rU   r-   rO  )r4   rP  rE  rF  s       r5   rN  z!Calendar._async_add_object_finishU  sQ      &&li&HHHHHHHH5''D'111r7   r   c                 .     | j         t          g|R i |S )zy
        Add an event to the calendar.

        Returns ``self.add_object(Event, ...)`` - see :meth:`add_object`
        )rQ  r   r4   largsru   s      r5   	add_eventzCalendar.add_event\  s&     tu7u777777r7   r   c                 .     | j         t          g|R i |S )z{
        Add a todo/task to the calendar.

        Returns ``self.add_object(Todo, ...)`` - see :meth:`add_object`
        )rQ  r   rT  s      r5   add_todozCalendar.add_todod  s&     tt6e666v666r7   r   c                 .     | j         t          g|R i |S )z
        Add a journal entry to the calendar.

        Returns ``self.add_object(Journal, ...)`` - see :meth:`add_object`
        )rQ  r   rT  s      r5   add_journalzCalendar.add_journall  s&     tw9999&999r7   c                      | j         |i |S )z
        Deprecated: Use :meth:`add_object` instead.

        This method is an alias kept for backwards compatibility.
        See https://github.com/python-caldav/caldav/issues/71
        )rQ  rT  s      r5   save_objectzCalendar.save_objectw  s     t0000r7   c                      | j         |i |S )z
        Deprecated: Use :meth:`add_event` instead.

        This method is an alias kept for backwards compatibility.
        See https://github.com/python-caldav/caldav/issues/71
        )rV  rT  s      r5   
save_eventzCalendar.save_event  s     t~u////r7   c                      | j         |i |S )z
        Deprecated: Use :meth:`add_todo` instead.

        This method is an alias kept for backwards compatibility.
        See https://github.com/python-caldav/caldav/issues/71
        )rX  rT  s      r5   	save_todozCalendar.save_todo  s     t}e.v...r7   c                      | j         |i |S )z
        Deprecated: Use :meth:`add_journal` instead.

        This method is an alias kept for backwards compatibility.
        See https://github.com/python-caldav/caldav/issues/71
        )rZ  rT  s      r5   save_journalzCalendar.save_journal  s      t1&111r7   c                     | j         r|                     |          S | j        5| j                            d          } | j        d| j        ||d| j         | S )z
        The save method for a calendar is only used to create it, for now.
        We know we have to create it when we don't have a url.

        For async clients, returns a coroutine that must be awaited.

        Returns:
         * self
        N{DAV:}displayname)r/   r.   rP   rq   )r@   rZ   r-   r>   r   r  r/   extra_init_optionsr4   rP   rh   s      r5   rU   zCalendar.save  sj      	,##F+++8:>>*=>>LDLaDG,vaaI`aaar7   c                    K   | j         ;| j                            d          } | j        d|| j        |d| j         d{V  | S )zAsync implementation of save.Nrd  )r.   r/   rP   rq   )r-   r>   r   r   r/   re  rf  s      r5   rZ   zCalendar._async_save  s|      8:>>*=>>L$$$ !dgf @D@W         r7   
event_urlsraise_notfoundc              #     K   | j         t          d          g }t          j                    t	          j                    z   }t	          j                    |z   d |D             z   }|                     |dd          }|                    t	          j                    g          }|r7|j	        D ]/}|j	        |         }	|	rd|	v rt          j        d|	 d|           0|D ]#}
|
||
         t          j        j                 fV  $dS )zv
        get multiple events' data.
        TODO: Does it overlap the _request_report_build_resultlist method
        Nr^   c                 B    g | ]}t          j        |j                   S valuer   r   r  r2   us     r5   r6   z&Calendar._multiget.<locals>.<listcomp>  '    0\0\0\A1G1G1G0\0\0\r7   report404Status  in )r-   rb   r   r  r   CalendarDataCalendarMultiGetr
  expand_simple_propsstatusesr   ra   r   )r4   rh  ri  rvr  r   rF   r9   hrefstatusr  s              r5   	_multigetzCalendar._multiget  s5     
 8ABBBxzzD-///$&&-0\0\Q[0\0\0\\ ;;tT844..0A0C0C/DEE 	L ) L L!*40 Levoo-.J.J.JD.J.JKKK 	9 	9Agaj!2!6788888	9 	9r7   c              #      K   |                      ||          }|D ]q\  }}t          t          t          |                    d          } |                     |          | j        | j                            |          ||           V  rdS )z
        get multiple events' data
        TODO: Does it overlap the _request_report_build_resultlist method?
        @author mtorange@gmail.com (refactored by Tobias)
        )ri  z/:@)safer-   r   r0   N)r~  r   r   rC   r8  r,   r-   rf   )r4   rh  ri  r9   r-   r   
quoted_urls          r5   multigetzCalendar.multiget  s       ..N.KK  	 	ICws3xx00u===J9$33D99HMM*--	      	 	r7   c                   K   | j         t          d          t          j                    t	          j                    z   }t	          j                    |z   d |D             z   }|                     |dd           d{V }|                    t	          j                    g          |r7|j	        D ]/}|j	        |         }|rd|v rt          j        d| d|           0fdD             S )	uD   Async version of _multiget — returns a list of (url, data) tuples.Nr^   c                 B    g | ]}t          j        |j                   S rl  ro  rp  s     r5   r6   z,Calendar._async_multiget.<locals>.<listcomp>  rr  r7   rs  rt  ru  rv  c                 N    g | ]!}||         t           j        j                 f"S rq   )r   rw  r   )r2   r  r9   s     r5   r6   z,Calendar._async_multiget.<locals>.<listcomp>  s-    HHH1GAJt0456HHHr7   )r-   rb   r   r  r   rw  rx  r  ry  rz  r   ra   )	r4   rh  ri  r  r   rF   r|  r}  r9   s	           @r5   _async_multigetzCalendar._async_multiget  s!      8ABBBxzzD-///$&&-0\0\Q[0\0\0\\**4x@@@@@@@@..0A0C0C/DEE 	L ) L L!*40 Levoo-.J.J.JD.J.JKKKHHHHHHHHr7   c                 6    t           | j        |i |          S )z
        get multiple events' data
        @author mtorange@gmail.com
        (refactored by Tobias)
        This is for backward compatibility.  It may be removed in 3.0 or later release.
        )rp   r  rT  s      r5   calendar_multigetzCalendar.calendar_multiget  s#     MDM53F33444r7   VEVENTmaybestartend
compfilterexpandverify_expandr   c                     t          j        dt          d           |rt          j        d           |dk    r|duo|du}|dk    rt
          }n|dk    rt          }nd}|                     ||||d	
          }|S )a  
        .. deprecated:: 3.0
            Use :meth:`search` instead. This method will be removed in 4.0.

        Search events by date in the calendar.

        Args:
            start: Start of the date range to search.
            end: End of the date range (optional for open-ended search).
            compfilter: Component type to search for. Defaults to "VEVENT".
                Set to None to fetch all calendar components.
            expand: Should recurrent events be expanded? Default "maybe"
                becomes True unless the search is open-ended.
            verify_expand: Not in use anymore, kept for backward compatibility.

        Returns:
            List of CalendarObjectResource objects matching the search.

        Example (migrate to search)::

            # Legacy (deprecated):
            events = calendar.date_search(start, end, expand=True)

            # Recommended:
            events = calendar.search(start=start, end=end, event=True, expand=True)
        z7use `calendar.search rather than `calendar.date_search`   )
stacklevelz`verify_expand in date_search does not work anymore, as we're doing client side expansion insteadr  Nr  VTODOF)r  r  
comp_classr  split_expanded)warningswarnDeprecationWarningloggingr   r   r   r#  )r4   r  r  r  r  r  r  objectss           r5   date_searchzCalendar.date_search  s    H 	E	
 	
 	
 	
  	Or   W$&:3d?F!!JJ7""JJJ++!   
 
 r7   c           
         | j         r|                     ||||          S g }|t          j                    g}nt          j                    g|z   }|                     |dd          }|                    |          }|D ]}	||	         }
t          j        j        |
v r>|
                    t          j        j                  }||                     |          n|}nd}|t          }t          |	          }|j        t          |	          }| j                            |          | j        k    r|                     || j        | j                            |          || |
                     ||fS )z
        Takes some input XML, does a report query on a calendar object
        and returns the resource objects found.

        For async clients, returns a coroutine that must be awaited.
        Nr   rs  r-   r   r0   r>   )r@   &_async_request_report_build_resultlistr   rw  r
  ry  r   popr8  r   r!   r   r   r-   rf   appendr,   r4   xmlr  r>   no_calendardatamatchesprops_rF   r9   r  pdatacdatacomp_class_r-   s                 r5    _request_report_build_resultlistz)Calendar._request_report_build_resultlistF  s     	>>Z   ='))*FF'))*U2F;;sAx00..v66 	 	AAJE $--		$"3"788@J@RD55e<<<Xb  "4a&&C|#Ahhx}}S!!TX--NNKc**      '""r7   c           
        K   g }|t          j                    g}nt          j                    g|z   }|                     |dd           d{V }|                    |          }|D ]}	||	         }
t           j        j        |
v r>|
                    t           j        j                  }||                     |          n|}nd}|t          }t          |	          }|j	        t          |	          }| j                            |          | j        k    r|                     || j        | j                            |          || |
                     ||fS )z9Async implementation of _request_report_build_resultlist.Nr   rs  r  )r   rw  r  ry  r   r  r8  r   r!   r   r   r-   rf   r  r,   r  s                 r5   r  z/Calendar._async_request_report_build_resultlisty  s      ='))*FF'))*U2F**38<<<<<<<<..v66 	 	AAJE $--		$"3"788@J@RD55e<<<Xb  "4a&&C|#Ahhx}}S!!TX--NNKc**      '""r7   r   c                 h   ddl m}  |            }| |_        |D ]}|d         dk    sJ |}|dk    rd}|dk    rd}|d	k    rd
}|dk    r_|                    dd          }t	          |d         t
                    r|d         g|d<   |d         D ]}|                    ||           |dk    r|dk    s	||j        v rt          ||||                    |	                    d          r'|
                    |dd         ||         d           |
                    |||                    |S )a  Create a searcher object for building complex search queries.

        This is the recommended way to perform advanced searches. The
        returned searcher can have filters added, and then be executed:

        .. code-block:: python

            searcher = calendar.searcher(event=True, start=..., end=...)
            searcher.add_property_filter("SUMMARY", "meeting")
            results = searcher.search()

        For simple searches, use :meth:`search` directly instead.

        :param searchargs: Search parameters (same as for :meth:`search`)
        :return: A CalDAVSearcher bound to this calendar

        See :class:`caldav.search.CalDAVSearcher` for available filter methods.
        r   r   r   r*  class_classno_categoryno_categories	no_class_no_class	sort_keyssort_reverseFr  no_   Nundefoperator)r#  r   	_calendarr   rg   rC   add_sort_key__dataclass_fields__setattrre   add_property_filter)r4   
searchargsr   my_searcherr   aliasr  sortkeys           r5   searcherzCalendar.searcher  s   & 	+*****$n&& $ 	H 	HCq6S====Ehm##'k!!"k!!)~~neDDj5s;; H/9+/F.GJ{+)+6 D DG,,WlCCCCD&&$${/O(O(OS*S/::::!!%(( H//abb	:c?U\/]]]]//z#GGGGr7   Tr  server_expandr  r  r>   c	           	         ddl m}
 t          |	                    dd          t                    sJ  |
            }|	D ]}|d         dk    sJ |}|dk    rd}|d	k    rd
}|dk    rd}|dk    rIt          |	d         t
                    r|	d         g|	d<   |	d         D ]}|                    ||           y|dk    s	||j        v rt          |||	|                    |	                    d          r'|
                    |dd         |	|         d           |
                    ||	|                    |s|r|}| j        r|                    | ||||||          S |                     | ||||||          S )aB  Sends a search request towards the server, processes the
        results if needed and returns the objects found.

        Refactoring 2025-11: a new class
        class:`caldav.search.CalDAVSearcher` has been made, and
        this method is sort of a wrapper for
        CalDAVSearcher.search, ensuring backward
        compatibility.  The documentation may be slightly overlapping.

        I believe that for simple tasks, this method will be easier to
        use than the new interface, hence there are no plans for the
        foreseeable future to deprecate it.  This search method will
        continue working as it has been doing before for all
        foreseeable future.  I believe that for simple tasks, this
        method will be easier to use than to construct a
        CalDAVSearcher object and do searches from there.  The
        refactoring was made necessary because the parameter list to
        `search` was becoming unmanagable.  Advanced searches should
        be done via the new interface.

        Caveat: The searching is done on the server side, the RFC is
        not very crystal clear on many of the corner cases, and
        servers often behave differently when presented with a search
        request.  There is planned work to work around server
        incompatibilities on the client side, but as for now
        complicated searches will give different results on different
        servers.

        ``todo`` - searches explicitly for todo.  Unless
        ``include_completed`` is specified, there is some special
        logic ensuring only pending tasks is returned.

        There is corresponding ``event`` and ``journal`` bools to
        specify that the search should be only for events or journals.
        When neither are set, one should expect to get all objects
        returned - but quite some calendar servers will return
        nothing.  This will be solved client-side in the future, as
        for 2.0 it's recommended to search separately for tasks,
        events and journals to ensure consistent behaviour across
        different calendar servers and providers.

        ``sort_keys`` refers to (case-insensitive) properties in the
        icalendar object, ``sort_reverse`` can also be given.  The
        sorting will be done client-side.

        Use ``start`` and ``end`` for time-range searches.  Open-ended
        searches are supported (i.e. "everything in the future"), but
        it's recommended to use closed ranges (i.e. have an "event
        horizon" of a year and ask for "everything from now and one
        year ahead") and get the data expanded.

        With the boolean ``expand`` set, you don't have to think too
        much about recurrences - they will be expanded, and with the
        (default) ``split_expanded`` set, each recurrence will be
        returned as a separate list object (otherwise all recurrences
        will be put into one ``VCALENDAR`` and returned as one
        ``Event``).  This makes it safe to use the ``event.component``
        property.  The non-expanded resultset may include events where
        the timespan doesn't match the date interval you searched for,
        as well as items with multiple components ("special"
        recurrences), meaning you may need logic on the client side to
        handle the recurrences.  *Only time range searches over closed
        time intervals may be expanded*.

        As for 2.0, the expand-logic is by default done on the
        client-side, for consistent results across various server
        incompabilities.  However, you may force server-side expansion
        by setting ``server_expand=True``

        Text attribute search parameters can be given to query the
        "properties" in the calendar data: category, uid, summary,
        comment, description, location, status.  According to the RFC,
        a substring search should be done.

        You may use no_category, no_summary, etc to search for objects
        that are missing those attributes.

        Negated text matches are not supported yet.

        For power-users, those parameters are also supported:

         * ``xml`` - use this search query, and ignore other filter parameters
         * ``comp_class`` - alternative to the ``event``, ``todo`` or ``journal`` booleans described above.
         * ``filters`` - other kind of filters (in lxml tree format)

        r   r   r  Tr   r*  r  r  r  r  r  r  r  r  r  r  Nr  r  )r#  r   rg   r   boolrC   r  r  r  re   r  r@   async_search)r4   r  r  r  r  r>   filterspost_filter_hacksr  r   r  r   r  r  s                  r5   r#  zCalendar.search  s   F 	+***** *..488$????? %n&& 	H 	HCq6S====Ehm##'k!!"k!!j5s;; H/9+/F.GJ{+)+6  G,,WlCCC $${/O(O(OS*S/:::!!%(( H//abb	:c?U\/]]]]//z#GGGG 	w 	C  	++m^UCf   !!-[&
 
 	
r7   r   c                     t          j                    t          j        ||          gz   }|                     |dd          }t	          | |j                  S )z
        Search the calendar, but return only the free/busy information.

        Args:
          start : defaults to datetime.today().
          end : same as above.

        Returns:
          [FreeBusy(), ...]
        r   rs  )r   FreeBusyQuery	TimeRanger
  r   raw)r4   r  r  r   rF   s        r5   r   zCalendar.freebusy_requestg  sM     !##t~eS'A'A&BB;;tQ11hl+++r7   duepriorityr  include_completedsort_keyc                 <    |r|f}|                      d||          S )a  
        Fetches a list of todo items (this is a wrapper around search).

        For sync clients, returns a list of Todo objects directly.
        For async clients, returns a coroutine that must be awaited.

        Args:
          sort_keys: use this field in the VTODO for sorting (iterable of lower case string, i.e. ('priority','due')).
          include_completed: boolean - by default, only pending tasks are listed
          sort_key: DEPRECATED, for backwards compatibility with version 0.4.

        Example (sync):
            todos = calendar.get_todos()

        Example (async):
            todos = await calendar.get_todos()
        T)todor  r  )r#  )r4   r  r  r  s       r5   	get_todoszCalendar.get_todosw  s/    .  	$!I {{8IU^{___r7   c                      | j         |i |S )z
        Deprecated: Use :meth:`get_todos` instead.

        This method is an alias kept for backwards compatibility.
        )r  rT  s      r5   todoszCalendar.todos  s     t~u////r7   c                 :   |t           S t          |d          ri|                    d          D ]R}|                                }|dk    r	t          c S |dk    r	t
          c S |dk    r	t          c S |dk    r	t          c S Snt          |d          rt          |j	                  st           S t          j        t          t          j        t
          t          j        t          t          j        t          i}|j	        D ]}|j        |v r||j                 c S t           S )	z
        takes some data, either as icalendar text or icalender object (TODO:
        consider vobject) and returns the appropriate
        CalendarResourceObject child class.
        Nsplit
zBEGIN:VEVENTzBEGIN:VTODOzBEGIN:VJOURNALzBEGIN:VFREEBUSYsubcomponents)r   hasattrr  stripr   r   r   r   lenr  r   r   )r4   r   lineical2caldavscs        r5   r8  z%Calendar._calendar_comp_class_by_data  s:    < *)4!! 	5

4(( 	$ 	$zz||>)) LLL=((KKK+++"NNN,,,#OOO -	$ T?++ 	5t)** .-- !7"H	K ( 5 5<;..&r|4444 /%%r7   r   c                 J    t          |||                                           S )z7
        Returns the event with the given URL.
        r  )r   load)r4   r|  r   s      r5   event_by_urlzCalendar.event_by_url  s%     D666;;===r7   r   comp_filterr  c                     |                      ||dd          }fd|D             }|st          j        dz            t          j        t	          |          dk               |d         S )a>  
        Get one calendar object from the calendar by UID.

        Args:
         uid: the object uid
         comp_class: filter by component type (Event, Todo, Journal)
         comp_filter: for backward compatibility.  Don't use!

        Returns:
         CalendarObjectResource (Event, Todo, or Journal)
        Tinsist)r   r  r  r  r  c                 *    g | ]}|j         k    |S rq   )r/   )r2   rP  r   s     r5   r6   z.Calendar.get_object_by_uid.<locals>.<listcomp>  s     ===Qqr7   z%s not found on serverr   r   )r#  r   ra   r  r  )r4   r   r  r  items_founds    `   r5   get_object_by_uidzCalendar.get_object_by_uid  s    2 kk
V^ " 
 
 >===+=== 	F%&>&DEEEc+&&!+,,,1~r7   c                 T    |                      |t          j        d                    S )z
        Get a task/todo from the calendar by UID.

        Returns the task with the given uid.
        See :meth:`get_object_by_uid` for more details.
        r  r  r  r   
CompFilterr4   r   s     r5   get_todo_by_uidzCalendar.get_todo_by_uid  s'     %%ctw7O7O%PPPr7   c                 T    |                      |t          j        d                    S )z
        Get an event from the calendar by UID.

        Returns the event with the given uid.
        See :meth:`get_object_by_uid` for more details.
        r  r  r  r  s     r5   get_event_by_uidzCalendar.get_event_by_uid  s'     %%ctx7P7P%QQQr7   c                 T    |                      |t          j        d                    S )z
        Get a journal entry from the calendar by UID.

        Returns the journal with the given uid.
        See :meth:`get_object_by_uid` for more details.
        VJOURNALr  r  r  s     r5   get_journal_by_uidzCalendar.get_journal_by_uid  s'     %%ctz7R7R%SSSr7   c                      | j         |i |S )z
        Deprecated: Use :meth:`get_object_by_uid` instead.

        This method is an alias kept for backwards compatibility.
        )r  rT  s      r5   object_by_uidzCalendar.object_by_uid  s     &t%u7777r7   c                 ,    |                      |          S )z
        Deprecated: Use :meth:`get_event_by_uid` instead.

        This method is an alias kept for backwards compatibility.
        )r  r  s     r5   event_by_uidzCalendar.event_by_uid  s     $$S)))r7   c                 ,    |                      |          S )z
        Deprecated: Use :meth:`get_todo_by_uid` instead.

        This method is an alias kept for backwards compatibility.
        )r  r  s     r5   todo_by_uidzCalendar.todo_by_uid  s     ##C(((r7   c                 ,    |                      |          S )z
        Deprecated: Use :meth:`get_journal_by_uid` instead.

        This method is an alias kept for backwards compatibility.
        )r  r  s     r5   journal_by_uidzCalendar.journal_by_uid  s     &&s+++r7   c                 8    |                      t                    S )ay  
        List all events from the calendar.

        For sync clients, returns a list of Event objects directly.
        For async clients, returns a coroutine that must be awaited.

        Returns:
         * [Event(), ...]

        Example (sync):
            events = calendar.get_events()

        Example (async):
            events = await calendar.get_events()
        r  )r#  r   rL   s    r5   r"  zCalendar.get_events*  s    $ {{e{,,,r7   c                 *    |                                  S )z
        Deprecated: Use :meth:`get_events` instead.

        This method is an alias kept for backwards compatibility.
        )r"  rL   s    r5   eventszCalendar.events>  s        r7   r  c                 F   ddl }g }|D ]}t          |d          rUt          j        j        |j        v r=|                    t          |j        t          j        j                                      gt          |d          r9|                    t          |j        	                                                     |
                                 d                    |          }|                    |                                d                                          }d| S )	a  
        Generate a fake sync token for servers without sync support.
        Uses a hash of all ETags to detect changes.

        Args:
            objects: List of calendar objects to generate token from

        Returns:
            A fake sync token string
        r   Nr>   r-   |F)usedforsecurityfake-)hashlibr  r   GetEtagr   r>   r  rC   r-   rd   r   rf   md5encode	hexdigest)r4   r  r  etagsr+  combined
hash_values          r5   _generate_fake_sync_tokenz"Calendar._generate_fake_sync_tokenF  s     	 	7 	7CsG$$ 7CI)E)ES3;?!;<<====e$$ 7S!2!2!4!455666

88E??[[!2!2E[JJTTVV
#z###r7   
sync_tokenload_objectsdisable_fallback&SynchronizableCalendarObjectCollectionc                 &	   d}| j         j                            dt                    }|                    d          dk    r|rt          j        d          d}|r,t          |t                    r|	                    d          rd}|rm	 t          j                    }t          j        |	          }t          j        d
	          }t          j                    t          j                    z   }	||||	gz   }
|                     |
t          j                    gd          \  }}	 |j        }n>#  |j                            dt          j        j        z             d         j        }Y nxY w|r/|D ],}	 |                                 # t
          j        $ r Y )w xY wt1          | ||          S # t
          j        t
          j        f$ r+}|r t4                              d| d           Y d}~nd}~ww xY wt4                              d           t;          |                                           }|rG|D ]D}t?          |d          r|j         +	 |                                 /# t
          j        $ r Y @w xY wE|rt?          |d         d          rt          j        j        |d         j!        vrt	 | "                    t          j                    gd          }|#                    t          j                    g          }d |D             }t4                              dtI          |           d           |%                                D ]\  }}	t          | j&        '                    |          (                                          }||v r`t?          ||         d          si ||         _!        ||         j!        )                    |	           t4                              d|            n4# tT          $ r'}t4                              d|            Y d}~nd}~ww xY w| +                    |          }|rBt          |t                    r-|	                    d          r||k    rt1          | g |          S t1          | ||          S )a  get_objects_by_sync_token aka get_objects

        Do a sync-collection report, ref RFC 6578 and
        https://github.com/python-caldav/caldav/issues/87

        This method will return all objects in the calendar if no
        sync_token is passed (the method should then be referred to as
        "objects"), or if the sync_token is unknown to the server.  If
        a sync-token known by the server is passed, it will return
        objects that are added, deleted or modified since last time
        the sync-token was set.

        If load_objects is set to True, the objects will be loaded -
        otherwise empty CalendarObjectResource objects will be returned.

        This method will return a SynchronizableCalendarObjectCollection object, which is
        an iterable.

        This method transparently falls back to retrieving all objects if the server
        doesn't support sync tokens. The fallback behavior is identical from the user's
        perspective, but less efficient as it transfers the entire calendar on each sync.

        If disable_fallback is set to True, the method will raise an exception instead
        of falling back to retrieving all objects. This is useful for testing whether
        the server truly supports sync tokens.
        Tz
sync-tokenr   r   unsupportedz+Sync tokens are not supported by the serverFr  rm  1)r>   r  z.//r   )r[   r  r  zSync-collection REPORT failed (z!), falling back to full retrievalNz6Using fallback sync mechanism (retrieving all objects)_datar>   r   )r?   c                 \    i | ])}t          |j                                                  |*S rq   )rC   r-   rd   r2   r+  s     r5   
<dictcomp>z6Calendar.get_objects_by_sync_token.<locals>.<dictcomp>  s0    SSSc#'"3"3"5"566SSSr7   zFallback: Fetching ETags for z objectszFallback: Added ETag to z)Failed to fetch ETags for fallback sync: ),r,   r   r   r   r   r   ReportErrorrg   rC   re   r   SyncCollection	SyncToken	SyncLevelr  r  r  r  treefindallr   r   r  ra   r  DAVErrorr   r3   debugrp   r#  r  r  r>   _query_propertiesry  r  itemsr-   rf   rd   updater  r  )r4   r  r  r  use_sync_tokensync_supportcmdtokenlevelr>   r   rF   r  r+  eall_objects
etag_props
url_to_objurl_strcanonical_url_strfake_sync_tokens                        r5   get_objects_by_sync_tokenz"Calendar.get_objects_by_sync_token_  s(   D {+88SW8XXI&&-77 W'(UVVV"N 	#*Z55 	#*:O:OPW:X:X 	#"N 	aa(**J777C000

S[]]2eUE22&*&K&K 'L ' '#7Z!)!4JJZ!)!6!6us}?P7P!Q!QRS!T!YJJJ   !& ! !!HHJJJJ$2 ! ! ! D! >!7z    %u~6 a a a# _1___````````	a 			JKKK 4;;==))  	"  sG,, 	0A



 .    1B  	A00	47KO;WX>K_4_4_113;==/1KK%993;==/JJ
 TS{SSS
		S#j//SSSTTT&0&6&6&8&8 R RNGU(+DHMM',B,B,L,L,N,N(O(O%(J66&z2C'DgNN EBDJ'89?"#45;BB5III		"P=N"P"PQQQR     		IaIIJJJ	 88EE  	*Z55 	*:O:OPW:X:X 	_,,=!2/    6;?
 
 
 	
s   BF/ &D. -F/ .9E)'F/ 3FF/ FF/ FF/ /G5
!G00G5I&&I87I85D>O4 4
P%>P  P%c                      | j         |i |S )z
        Deprecated: Use :meth:`get_objects_by_sync_token` instead.

        This method is an alias kept for backwards compatibility.
        )r2  rT  s      r5   objects_by_sync_tokenzCalendar.objects_by_sync_token  s     .t-u????r7   c                 8    |                      t                    S )zd
        List all journals from the calendar.

        Returns:
         * [Journal(), ...]
        r   )r#  r   rL   s    r5   get_journalszCalendar.get_journals  s     {{g{...r7   c                 *    |                                  S )z
        Deprecated: Use :meth:`get_journals` instead.

        This method is an alias kept for backwards compatibility.
        )r6  rL   s    r5   journalszCalendar.journals  s       """r7   )NNNNNNrj   r   )NFF)FF)r'   r   )r'   r   )r'   r   )r'   rG  r   )F)Nr  r  F)NNF)r'   r   )NFTFNNNN)r  FNrk   )r'   r   )r'   r  )Krl   rm   rn   ro   r   rC   r	   r
   r!   r|   r  r   r   r  rp   r   r4  r<  rC  typer   r  rQ  rN  rV  rX  rZ  r\  r^  r`  rb  rU   rZ   r   r~  r"   r  tupler  r  r   r   r   r  r  r  r  r   rw  r#  r   r  r  r8  r  r  r  r  r  r  r  r  r  r  r'  r"  r  r  r2  r4  r  get_objectsr6  r8  r   r   s   @r5   r(   r(     s.         )-<@(,
 
%
 ;,s2T9
 %	

 Dj
 $J
 

 
 
 
 
 
4 QUI	I I I IX QU;	; ; ; ;z    @' ' '6=$s) = = = =0c D    	 	 	"  "/ / y/	/ Dj/ / / 
"/ / / /b   8 8 8 87 7 7 7: : : :1 1 1 10 0 0 0/ / / /2 2 2 2   &   9 9HSM 94 9T\]`Ta 9 9 9 90 8C= $ S[\_S`    $ AFI I"3-I9=I	eCHo	I I I I$5 5 5  $#*1#C CC _C 	C
 ww''C C 
*	+C C C CR AF1# 1# 1# 1#h AF$# $# $# $#L0 0 0 0h ##"04T
 T
T
 T
 	T

 T
 D%&-T
 
cT
 T
 T
 T
l,h ,X ,* , , , ,$ $7"'#	` `C=`  ` *	`
 
f` ` ` `<0f 0 0 0 0"& "& "&H> >sTz >W > > > > /39=	! !! _t+! 56	!
 
! ! ! !FQ3 Q+C Q Q Q QRC R,D R R R RTc T.F T T T T8 8 8 8* *(@ * * * *)s )'? ) ) ) ),# ,*B , , , , E-DM - - - -(!W ! ! ! !$6N1O $TW $ $ $ $6 "&"!&	L
 L
$JL
 L
 	L

 
2L
 L
 L
 L
\@ @ @ @ $G+K/d9o / / / /#$y/ # # # # # # # #r7   r(   c            	       l     e Zd ZdZ	 	 	 d
ded         dedz  deez  ez  e	z  dz  ddf fdZ
d	 Z xZS )ScheduleMailboxaw  
    RFC6638 defines an inbox and an outbox for handling event scheduling.

    TODO: As ScheduleMailboxes works a bit like calendars, I've chosen
    to inheritate the Calendar class, but this is a bit incorrect, a
    ScheduleMailbox is a collection, but not really a calendar.  We
    should create a common base class for ScheduleMailbox and Calendar
    eventually.
    Nr,   r   r   r-   r'   c                    t          t          |                               ||           d| _        |s|r|j        | _        |s$|r"| j        t          d          | j        j        }|D|t          d          |j                            t          j
        |                    | _        dS |t          d          | j        t          d          |j        | _        	 | j        j                            t          |                     |                                                               | _        dS #  t          j        dd           t          j        | j                                                   d| _        t          j        d	t%          |                                           d
t          j                  xY w)z9
        Will locate the mbox if no url is given
        rw   Nr]   z Unexpected value None for clientz#Unexpected value None for principalzsomething bad happenedTr   zprincipal has no z.  )r{   r=  r|   _itemsr,   rb   r   r-   rf   r!   rc   r}   findpropr  r   r  check_scheduling_supportra   rC   ERR_FRAGMENT)r4   r,   r   r-   r   s       r5   r|   zScheduleMailbox.__init__  s    	ot$$--V-EEE 	+) 	+#*DK 	.V 	.{" !HIII-I?~ !CDDDzs}S'9'9::DHHH  !FGGG{" !HIII }DH  ;?//D4E4Edmmoo4V4V0W0WXX6FFFFdkBBDDEEE ))25dmmoo2F2F2F2FHZHZ[  s   #AD; ;BGc                 0     j         s	                      d           _         n#  t          j        d           t	          j        dt           j                  v             fd                                 D              _          j         D ]}|	                                 Y nhxY w	  j         
                                 nJ#   fd                                 D              _          j         D ]}|	                                 Y nxY w j         S )z_
        TODO: work in progress
        TODO: perhaps this belongs to the super class?
        Tr  zXcaldav server does not seem to support a sync-token REPORT query on a scheduling mailboxgooglec                 H    g | ]}t          |d          j                  S r   )r-   r,   r   r,   r2   r   r4   s     r5   r6   z-ScheduleMailbox.get_items.<locals>.<listcomp>O  :       MN*qtDKHHH  r7   c                 H    g | ]}t          |d          j                  S rG  rH  rI  s     r5   r6   z-ScheduleMailbox.get_items.<locals>.<listcomp>X  rJ  r7   )r?  r  r  r"  r   r  rC   r-   childrenr  sync)r4   r   s   ` r5   	get_itemszScheduleMailbox.get_itemsB  s[   
 { 	"lll==	n   h#dh--7888   RVR_R_RaRa     AFFHHHH   """"   RVR_R_RaRa     AFFHHHH {s   & BB)-C ADr   )rl   rm   rn   ro   r   rs   rC   r	   r
   r!   r|   rN  r   r   s   @r5   r=  r=  
  s          )-&*<@	+ +%+ t#+ ;,s2T9	+
 
+ + + + + +Z      r7   r=  c                       e Zd Zej        ZdS )r   N)rl   rm   rn   r   ScheduleInboxURLr@  rq   r7   r5   r   r   g  s        $HHHr7   r   c                       e Zd Zej        ZdS )r   N)rl   rm   rn   r   ScheduleOutboxURLr@  rq   r7   r5   r   r   k  s        %HHHr7   r   c                   `    e Zd ZdZd	dZdee         fdZdefdZ	d Z
deeef         fdZdS )
r  z
    This class may hold a cached snapshot of a calendar, and changes
    in the calendar can easily be copied over through the sync method.

    To create a SynchronizableCalendarObjectCollection object, use
    calendar.objects(load_objects=True)
    r'   Nc                 >    || _         || _        || _        d | _        d S r   )r[   r  r  _objects_by_url)r4   r[   r  r  s       r5   r|   z/SynchronizableCalendarObjectCollection.__init__x  s%     $#r7   c                 4    | j                                         S r   )r  __iter__rL   s    r5   rW  z/SynchronizableCalendarObjectCollection.__iter__~  s    |$$&&&r7   c                 *    t          | j                  S r   )r  r  rL   s    r5   __len__z.SynchronizableCalendarObjectCollection.__len__  s    4<   r7   c                 x    | j         -i | _         | D ]#}|| j         |j                                        <   $| j         S )zp
        returns a dict of the contents of the SynchronizableCalendarObjectCollection, URLs -> objects.
        )rU  r-   rd   )r4   r+  s     r5   objects_by_urlz5SynchronizableCalendarObjectCollection.objects_by_url  sM     '#%D  @ @<?$SW%6%6%8%899##r7   c                    g }g }t          | j        t                    o| j                            d          }|s	 | j                            | j        d          }t          |j        t                    r|j                            d          rd}nx|                                 }|D ]#}|j                                        |_        |j        |v rt          j
        j        ||j                 j        v r^t          j
        j        |j        v rF||j                 j        t          j
        j                 |j        t          j
        j                 k    r|||j        <   	 |                                 |                    |           # t          j        $ r3 |                    |           |                    |j                   Y !w xY wt%          |                                          | _        d| _        |j        | _        ||fS n## t          j        t          j        f$ r d}Y nw xY w|rt0                              d           t%          | j                                                  }|D ],}	 |                                 # t          j        $ r Y )w xY wd |D             }|                                 }	|                                D ]z\  }
}|
|	v r\t9          |	|
         d          r|	|
         j        nd}t9          |d          r|j        nd}||k    r||                    |           e|                    |           {|	D ]!}
|
|vr|                    |	|
                    "t%          |                                          | _        d| _        | j                            | j                  | _        ||fS )	a   
        This method will contact the caldav server,
        request all changes from it, and sync up the collection.

        This method transparently falls back to comparing full calendar state
        if the server doesn't support sync tokens.
        r  FrD  TNz5Using fallback sync mechanism (comparing all objects)c                 B    i | ]}|j                                         |S rq   )r-   rd   r  s     r5   r  z?SynchronizableCalendarObjectCollection.sync.<locals>.<dictcomp>  s(    RRR3cg//113RRRr7   r   )rg   r  rC   re   r[   r2  r[  r-   rd   r   r  r   r>   r  r  r   ra   r  rp   valuesr  rU  r  r!  r   r"  r#  r$  r  r   r  )r4   updated_objsdeleted_objsis_fake_tokenupdatesobur+  current_objectscurrent_by_url
old_by_urlr-   old_datanew_datas                r5   rM  z+SynchronizableCalendarObjectCollection.sync  s     #4?C88`T_=W=WX_=`=` $	%"%-AAO% B  
 g0#66 87;M;X;XY`;a;a 8$(MM --//C& - -"%'"3"3"5"5GsNN #3sw<3E E E #39 < <"37|1#+/BciPSP[P_F``` ('*CG-HHJJJ(//4444$2 - - -(//444GGCG,,,,,- $(

#5#5DL+/D(&-&8DO(,771 "2 %u~6 % % % $%  '	TIIMNNN #4=#7#7#9#9::O '  HHJJJJ*   D SR/RRRN,,..J +0022 
- 
-S*$$ 8?z#PV7W7Waz#33]aH+23+?+?IsxxTH8++0D$++C000 !'',,,, " 9 9n,, ''
3888   5 5 7 788DL#'D "mEEdlSSDOl++sH   D$H ")FH >G
H G?H H/.H/:JJ! J!r   )rl   rm   rn   ro   r|   r   r   rW  r   rY  r[  r:  rM  rq   r7   r5   r  r  o  s         $ $ $ $'(3- ' ' ' '! ! ! ! !$ $ $],eCHo ], ], ], ], ], ],r7   r  ):ro   r  r   r  r   timer   typingr   r   r   r   urllib.parser	   r
   r   r   r   date	TimeStampr   	davclientr   r#  r   collections.abcr   r   r   r   calendarobjectresourcer   r   r   r   r   	davobjectr   elementsr   r   libr   r   lib.python_utilitiesr    lib.urlr!   r"   	getLoggerr   r&   rs   r(   r=  r   r   r  rq   r7   r5   <module>rw     s  
 
                8 8 8 8 8 8 8 8 8 8 8 8 A A A A A A A A A A A A    	)II	D '%%%%%%$$$$$$&&&&&& 8 8 8 8 8 8 8 8 8 8                    !                           ) ) ) ) ) )      ge3444g!!_Q _Q _Q _Q _Q) _Q _Q _QDr. r. r. r. r.	 r. r. r.j	x# x# x# x# x#y x# x# x#v'S S S S Sh S S Sz% % % % %O % % %& & & & &_ & & &|, |, |, |, |, |, |, |, |, |,s   A
 
A