
    iQ                    "   d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	 ddl
mZmZmZmZmZmZmZmZ ddlmZmZmZmZmZmZmZ ddlmZmZmZ dd	lm Z  dd
l!m"Z"m#Z# ddl$m%Z% ddl&m'Z' ddl(m)Z)m*Z*  ej+        d          Z, G d de          Z-dS )u   
Asynchronous JMAP client.

Mirrors JMAPClient with all public methods as coroutines.
Uses niquests.AsyncSession for HTTP — niquests is a core dependency.
    )annotationsN)AsyncSession)build_calendar_getparse_calendar_get)build_event_changesbuild_event_getbuild_event_set_createbuild_event_set_destroybuild_event_set_updateparse_event_changesparse_event_getparse_event_set)build_task_getbuild_task_list_getbuild_task_set_createbuild_task_set_destroybuild_task_set_updateparse_task_list_getparse_task_set)_DEFAULT_USING_TASK_USING_JMAPClientBase)ical_to_jscal)JMAPAuthErrorJMAPMethodError)JMAPCalendarJMAPCalendarObject)Sessionasync_fetch_sessionzcaldav.jmapc                      e Zd ZdZd4dZd5dZd6dZd7d8dZd9dZd:dZ	d;dZ
d<dZ	 	 	 	 	 d=d>d Z	 	 	 	 d?d@d!ZdAd"ZdBd%ZdCd&Z	 dDdEd(ZdFd*ZdGd-ZdHd0ZdId2ZdJd3ZdS )KAsyncJMAPClientaw  Asynchronous JMAP client for calendar operations.

    **The JMAP support is experimental, the API may change in minor-releases**

    Usage::

        from caldav.jmap import get_async_jmap_client
        async with get_async_jmap_client(url="https://jmap.example.com/.well-known/jmap",
                                          username="alice", password="secret") as client:
            calendars = await client.get_calendars()

    Args:
        url: URL of the JMAP session endpoint (``/.well-known/jmap``).
        username: Username for Basic auth.
        password: Password for Basic auth, or bearer token if no username.
        auth: A pre-built niquests-compatible auth object. Takes precedence
              over username/password if provided.
        auth_type: Force a specific auth type: ``"basic"`` or ``"bearer"``.
        timeout: HTTP request timeout in seconds.
    returnc                
   K   | S N selfs    S/root/projects/butler/venv/lib/python3.11/site-packages/caldav/jmap/async_client.py
__aenter__zAsyncJMAPClient.__aenter__C   s          Nonec                
   K   d S r%   r&   )r(   exc_typeexc_valexc_tbs       r)   	__aexit__zAsyncJMAPClient.__aexit__F   s      tr+   r   c                z   K   | j         ,t          | j        | j        | j                   d{V | _         | j         S )z5Return the cached Session, fetching it on first call.N)authtimeout)_session_cacher    url_authr4   r'   s    r)   _get_sessionzAsyncJMAPClient._get_sessionI   s\      &(;tz4<) ) ) # # # # # #D ""r+   Nmethod_callslist[tuple]usinglist[str] | Nonelistc           	       K   |                                   d{V }||nt          t          |          d}t                              d|j        t          |                     t                      4 d{V }|                    |j        || j	        ddd| j
                   d{V }ddd          d{V  n# 1 d{V swxY w Y   |j        dv rt          |j        d|j         d	
          |                                 |                                }|                    dg           }|D ]>}	|	\  }
}}|
dk    r0|                    dd          }t!          |j        d| |          ?|S )aM  POST a batch of JMAP method calls and return the methodResponses.

        Args:
            method_calls: List of 3-tuples ``(method_name, args_dict, call_id)``.
            using: Capability URN list for the ``using`` field. Defaults to
                ``_DEFAULT_USING`` (core + calendars).

        Returns:
            List of 3-tuples ``(method_name, response_args, call_id)`` from
            the server's ``methodResponses`` array.

        Raises:
            JMAPAuthError: On HTTP 401 or 403.
            JMAPMethodError: If any methodResponse is an ``error`` response.
        N)r;   methodCallsz"JMAP POST to %s: %d method call(s)zapplication/json)zContent-TypeAccept)jsonr3   headersr4   )i  i  zHTTP z from API endpointr6   reasonmethodResponseserrortypeserverErrorzMethod call failed: r6   rD   
error_type)r8   r   r=   logdebugapi_urllenr   postr7   r4   status_coder   raise_for_statusrA   getr   )r(   r9   r;   sessionpayloadhttpresponsedatamethod_responsesrespmethod_name	resp_argscall_idrJ   s                 r)   _requestzAsyncJMAPClient._requestQ   s`       ))++++++++ $/UU^--
 

 			6\IZIZ[[[>> 	 	 	 	 	 	 	T!YYZ);GYZZ '        H	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 :--OGx3GGG   
 	!!###}}88$5r::$ 	 	D.2+KGg%%&]]6=AA
%=)==)    &  s   :3B??
C	C	list[JMAPCalendar]c                  K   |                                   d{V }t          |j                  }|                     |g           d{V }|D ]2\  }}}|dk    r&t	          |          }|D ]}| |_        d|_        |c S 3g S )zFetch all calendars for the authenticated account.

        Returns:
            List of :class:`~caldav.jmap.objects.calendar.JMAPCalendar` objects.
        NzCalendar/getT)r8   r   
account_idr]   r   _client	_is_async)	r(   rS   call	responsesrZ   r[   _	calendarscals	            r)   get_calendarszAsyncJMAPClient.get_calendars   s       ))++++++++!'"455--////////	)2 	! 	!%KAn,,.y99	$ ) )C"&CK$(CMM     - 	r+   calendar_idstrical_strc                  K   |                                   d{V }t          ||          }t          |j        d|i          }|                     |g           d{V }|D ]l\  }}}	|dk    r`t          |          \  }
}	}	}}	}	d|v r|                     ||d                    d|
vrt          |j        d          |
d         d         c S mt          |j        d          )	ai  Create a calendar event from an iCalendar string.

        Args:
            calendar_id: The JMAP calendar ID to create the event in.
            ical_str: A VCALENDAR string representing the event.

        Returns:
            The server-assigned JMAP event ID.

        Raises:
            JMAPMethodError: If the server rejects the create request.
        N)ri   new-0CalendarEvent/setz:CalendarEvent/set response missing created entry for new-0rC   idNo CalendarEvent/set response)	r8   r   r	   r`   r]   r   _raise_set_errorr   rM   )r(   ri   rk   rS   jscalrc   rd   rZ   r[   re   creatednot_createds               r)   create_eventzAsyncJMAPClient.create_event   s:      ))++++++++hK@@@%g&87E:JKK--////////	)2 
	. 
	.%KA1113B93M3M0A{Aqk))))';w3GHHH')))#O[    w'---- 2 '/:YZZZZr+   event_idr   c                r  K   |                                   d{V }t          |j        |g          }|                     |g           d{V }|D ]P\  }}}|dk    rDt	          |          }|st          |j        d| d          t          |d         d          c S Qt          |j        d	
          )a  Fetch a calendar event as an iCalendar string.

        Args:
            event_id: The JMAP event ID to retrieve.

        Returns:
            A :class:`~caldav.jmap.objects.calendar_object.JMAPCalendarObject`
            wrapping the raw JSCalendar dict.  ``parent`` is ``None`` since
            no :class:`~caldav.jmap.objects.calendar.JMAPCalendar` is available
            at the client level.

        Raises:
            JMAPMethodError: If the event is not found.
        NidsCalendarEvent/getzEvent not found: notFoundrI   r   rW   parentNo CalendarEvent/get responserC   )r8   r   r`   r]   r   r   rM   r   )	r(   rv   rS   rc   rd   rZ   r[   re   itemss	            r)   	get_eventzAsyncJMAPClient.get_event   s      ))++++++++w1zBBB--////////	)2 		F 		F%KA111'	22 )#O=8==#-   
 *uQxEEEEEE 2 '/:YZZZZr+   c                  K   |                                   d{V }t          |          }|                    dd           t          |j        ||i          }|                     |g           d{V }|D ]E\  }}}	|dk    r9t          |          \  }	}	}	}	}
}	||
v r|                     ||
|                     dS Ft          |j	        d          )a  Update a calendar event from an iCalendar string.

        Args:
            event_id: The JMAP event ID to update.
            ical_str: A VCALENDAR string with the updated event data.

        Raises:
            JMAPMethodError: If the server rejects the update.
        Nuidrn   rp   rC   )
r8   r   popr   r`   r]   r   rq   r   rM   )r(   rv   rk   rS   patchrc   rd   rZ   r[   re   not_updateds              r)   update_eventzAsyncJMAPClient.update_event   s      ))++++++++h''		%%g&88U:KLL--////////	)2 	 	%KA111-<Y-G-G*1aK{**))';x3HIII	 2 '/:YZZZZr+   
str | Nonestartendtextr}   JMAPCalendar | Nonelist[JMAPCalendarObject]c                
  K   |                                   d {V }|                     |j        ||||          }|                     |           d {V }|D ])\  }	}
}|	dk    rfdt	          |
          D             c S *g S )Nrz   c                2    g | ]}t          |           S )r|   r   ).0itemr}   s     r)   
<listcomp>z+AsyncJMAPClient._search.<locals>.<listcomp>  s6        'D@@@  r+   )r8   _build_event_search_callsr`   r]   r   )r(   ri   r   r   r   r}   rS   callsrd   rZ   r[   re   s        `      r)   _searchzAsyncJMAPClient._search   s       ))++++++++..w/A;PUWZ\`aa--........	)2 	 	%KA111    /	 : :      2 	r+   c                D   K   |                      ||||           d{V S )aP  Search for calendar events.

        All parameters are optional; omitting all returns every event in the account.
        Results are fetched in a single batched JMAP request using a result reference
        from ``CalendarEvent/query`` into ``CalendarEvent/get``.

        Args:
            calendar_id: Limit results to this calendar.
            start: Only events ending after this datetime (``YYYY-MM-DDTHH:MM:SS``).
            end: Only events starting before this datetime (``YYYY-MM-DDTHH:MM:SS``).
            text: Free-text search across title, description, locations, and participants.

        Returns:
            List of :class:`~caldav.jmap.objects.calendar_object.JMAPCalendarObject`
            instances.  ``parent`` is ``None`` on these objects; use
            :meth:`JMAPCalendar.search` if you need ``parent`` set.
        )ri   r   r   r   N)r   )r(   ri   r   r   r   s        r)   search_eventszAsyncJMAPClient.search_events  s5      0 \\kCVZ\[[[[[[[[[r+   c                  K   |                                   d{V }t          |j        g           }|                     |g           d{V }|D ]$\  }}}|dk    r|                    dd          c S %t          |j        d          )uy  Return the current CalendarEvent state string for use as a sync token.

        Calls ``CalendarEvent/get`` with an empty ID list — no event data is
        transferred, only the ``state`` field from the response.

        Returns:
            Opaque state string. Pass to :meth:`get_objects_by_sync_token` to
            retrieve only what changed since this point.
        Nrx   rz   state r~   rC   )r8   r   r`   r]   rR   r   rM   r(   rS   rc   rd   rZ   r[   re   s          r)   get_sync_tokenzAsyncJMAPClient.get_sync_token&  s       ))++++++++w1r:::--////////	)2 	2 	2%KA111 }}Wb11111 2'/:YZZZZr+   
sync_tokenDtuple[list[JMAPCalendarObject], list[JMAPCalendarObject], list[str]]c                ^  K   |                                   d{V }t          |j        |          }|                     |g           d{V }g }g }g }|D ];\  }}	}
|dk    r/t	          |	          \  }
}
}}}}|rt          |j        dd          <||z   }|sg g |fS t          |j        |          }|                     |g           d{V }i |D ]8\  }}	}
|dk    r,t          |	          D ]}t          |d          |d	         <   9fd
|D             }fd|D             }|||fS )a  Fetch events changed since a previous sync token.

        Calls ``CalendarEvent/changes`` to discover which events were created,
        modified, or destroyed since ``sync_token`` was issued. Created and
        modified events are returned as
        :class:`~caldav.jmap.objects.calendar_object.JMAPCalendarObject` instances;
        destroyed events are returned as IDs (the objects no longer exist on the server).

        Args:
            sync_token: A state string previously returned by :meth:`get_sync_token`
                or by a prior call to this method.

        Returns:
            A 3-tuple ``(added, modified, deleted)``:

            - ``added``: objects for newly created events (``parent`` is ``None``).
            - ``modified``: objects for updated events (``parent`` is ``None``).
            - ``deleted``: Event IDs that were destroyed.

        Raises:
            JMAPMethodError: If the server reports ``hasMoreChanges: true``.
        NzCalendarEvent/changeszCalendarEvent/changes response was truncated by the server (hasMoreChanges=true). Call get_sync_token() to obtain a fresh baseline and re-sync.serverPartialFailrI   rx   rz   r|   ro   c                (    g | ]}|v |         S r&   r&   r   ievents_by_ids     r)   r   z=AsyncJMAPClient.get_objects_by_sync_token.<locals>.<listcomp>t  s'    KKKQl9J9Ja9J9J9Jr+   c                (    g | ]}|v |         S r&   r&   r   s     r)   r   z=AsyncJMAPClient.get_objects_by_sync_token.<locals>.<listcomp>u  s'    NNNA<M<MLO<M<M<Mr+   )
r8   r   r`   r]   r   r   rM   r   r   r   )r(   r   rS   changes_callrd   created_idsupdated_ids	destroyedrZ   r[   re   has_more	fetch_idsget_callget_responsesr   addedmodifiedr   s                     @r)   get_objects_by_sync_tokenz)AsyncJMAPClient.get_objects_by_sync_token8  s     2 ))++++++++*7+=zJJ--77777777	!#!#!	)2 	 	%KA555FYZcFdFdC1h[) 	)#O: $7     +-	 	%r9$$"7#59EEE"mmXJ7777777768)6 	Z 	Z%KA111+I66 Z ZD/AtTX/Y/Y/YLd,,KKKK+KKKNNNN[NNNh	))r+   c                Z  K   |                                   d{V }t          |j        |g          }|                     |g           d{V }|D ]E\  }}}|dk    r9t	          |          \  }}}}}}||v r|                     |||                     dS Ft          |j        d          )zDelete a calendar event.

        Args:
            event_id: The JMAP event ID to delete.

        Raises:
            JMAPMethodError: If the server rejects the delete.
        Nrn   rp   rC   )r8   r
   r`   r]   r   rq   r   rM   )	r(   rv   rS   rc   rd   rZ   r[   re   not_destroyeds	            r)   delete_eventzAsyncJMAPClient.delete_eventx  s       ))++++++++&w'9H:FF--////////	)2 	 	%KA111/>y/I/I,1aA}},,))'=3JKKK	 2 '/:YZZZZr+   r   c                   K   |                      ||           d {V D ]$}|j                            d          |k    r|c S %|                                  d {V }t	          |j        d|           )N)ri   r}   r   z#No calendar object found with UID: rC   )r   rW   rR   r8   r   rM   )r(   r   ri   r}   objrS   s         r)   _get_object_by_uidz"AsyncJMAPClient._get_object_by_uid  s       +fMMMMMMMM 	 	Cx||E""c))


 *))++++++++(Sc(S(S
 
 
 	
r+   
list[dict]c                   K   |                                   d{V }t          |j                  }|                     |gt                     d{V }|D ]\  }}}|dk    rt          |          c S g S )zFetch all task lists for the authenticated account.

        Returns:
            List of raw JMAP TaskList dicts as returned by the server.
        Nr;   zTaskList/get)r8   r   r`   r]   r   r   r   s          r)   get_task_listszAsyncJMAPClient.get_task_lists  s       ))++++++++"7#566--k-BBBBBBBB	)2 	6 	6%KAn,,*955555 - 	r+   task_list_idtitlec                  K   |                                   d{V }dt          t          j                              ||dddd}|                    |           t          |j        d|i          }|                     |gt                     d{V }|D ]R\  }}	}
|dk    rFt          |	          \  }}
}
}}
}
d|v r| 
                    ||d                    |d         d	         c S St          |j        d
          )a,  Create a task in a task list.

        Args:
            task_list_id: The JMAP task list ID to create the task in.
            title: Task title (maps to VTODO ``SUMMARY``).
            **kwargs: Optional JMAP Task fields using wire names: ``description``,
                ``due``, ``start``, ``timeZone``, ``estimatedDuration``,
                ``percentComplete``, ``progress``, ``priority``.

        Returns:
            The server-assigned JMAP task ID.

        Raises:
            JMAPMethodError: If the server rejects the create request.
        NTaskr   zneeds-action)z@typer   
taskListIdr   percentCompleteprogresspriorityrm   r   Task/setro   No Task/set responserC   )r8   rj   uuiduuid4updater   r`   r]   r   r   rq   r   rM   )r(   r   r   kwargsrS   	task_dictrc   rd   rZ   r[   re   rs   rt   s                r)   create_taskzAsyncJMAPClient.create_task  sD       ))++++++++tz||$$& &
 
	 	   $W%7'99MNN--k-BBBBBBBB	)2 	. 	.%KAj((3A)3L3L0A{Aqk))))';w3GHHHw'----	 ) '/:PQQQQr+   task_iddictc                p  K   |                                   d{V }t          |j        |g          }|                     |gt                     d{V }|D ]H\  }}}|dk    r<|                    dg           }|st          |j        d| d          |d	         c S It          |j        d
          )zFetch a task by ID.

        Args:
            task_id: The JMAP task ID to retrieve.

        Returns:
            Raw JMAP Task dict as returned by the server.

        Raises:
            JMAPMethodError: If the task is not found.
        Nrx   r   zTask/getr=   zTask not found: r{   rI   r   zNo Task/get responserC   )r8   r   r`   r]   r   rR   r   rM   )	r(   r   rS   rc   rd   rZ   r[   re   r   s	            r)   get_taskzAsyncJMAPClient.get_task  s       ))++++++++g0wi@@@--k-BBBBBBBB	)2 		  		 %KAj((!fb11 )#O;';;#-   
 Qx ) '/:PQQQQr+   r   c                j  K   |                                   d{V }t          |j        ||i          }|                     |gt                     d{V }|D ]E\  }}}|dk    r9t          |          \  }}}}}	}||	v r|                     ||	|                     dS Ft          |j        d          )a  Update a task with a partial patch.

        Args:
            task_id: The JMAP task ID to update.
            patch: Partial patch dict mapping property names to new values.

        Raises:
            JMAPMethodError: If the server rejects the update.
        Nr   r   r   rC   )	r8   r   r`   r]   r   r   rq   r   rM   )
r(   r   r   rS   rc   rd   rZ   r[   re   r   s
             r)   update_taskzAsyncJMAPClient.update_task  s       ))++++++++$W%7'59IJJ--k-BBBBBBBB	)2 	 	%KAj((-;I-F-F*1aKk))))';w3GHHH	 ) '/:PQQQQr+   c                h  K   |                                   d{V }t          |j        |g          }|                     |gt                     d{V }|D ]E\  }}}|dk    r9t          |          \  }}}}}}||v r|                     |||                     dS Ft          |j        d          )zDelete a task.

        Args:
            task_id: The JMAP task ID to delete.

        Raises:
            JMAPMethodError: If the server rejects the delete.
        Nr   r   r   rC   )	r8   r   r`   r]   r   r   rq   r   rM   )	r(   r   rS   rc   rd   rZ   r[   re   r   s	            r)   delete_taskzAsyncJMAPClient.delete_task  s       ))++++++++%g&87)DD--k-BBBBBBBB	)2 	 	%KAj((/=i/H/H,1aA}m++))'=3IJJJ	 ) '/:PQQQQr+   )r#   r"   )r#   r,   )r#   r   r%   )r9   r:   r;   r<   r#   r=   )r#   r^   )ri   rj   rk   rj   r#   rj   )rv   rj   r#   r   )rv   rj   rk   rj   r#   r,   )NNNNN)ri   r   r   r   r   r   r   r   r}   r   r#   r   )NNNN)
ri   r   r   r   r   r   r   r   r#   r   )r#   rj   )r   rj   r#   r   )rv   rj   r#   r,   )NN)r   rj   ri   r   r}   r   r#   r   )r#   r   )r   rj   r   rj   r#   rj   )r   rj   r#   r   )r   rj   r   r   r#   r,   )r   rj   r#   r,   )__name__
__module____qualname____doc__r*   r1   r8   r]   rh   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r&   r+   r)   r"   r"   -   s        *      # # # #7  7  7  7  7 r   ([ [ [ [@[ [ [ [@[ [ [ [6 #' &*    . #' \ \ \ \ \4[ [ [ [$>* >* >* >*@[ [ [ [. W[

 

 

 

 

    %R %R %R %RNR R R R:R R R R.R R R R R Rr+   r"   ).r   
__future__r   loggingr   niquestsr   caldav.jmap._methods.calendarr   r   caldav.jmap._methods.eventr   r   r	   r
   r   r   r   r   caldav.jmap._methods.taskr   r   r   r   r   r   r   caldav.jmap.clientr   r   r   caldav.jmap.convertr   caldav.jmap.errorr   r   caldav.jmap.objects.calendarr   #caldav.jmap.objects.calendar_objectr   caldav.jmap.sessionr   r    	getLoggerrK   r"   r&   r+   r)   <module>r      s    # " " " " "   ! ! ! ! ! ! P P P P P P P P	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	                  L K K K K K K K K K - - - - - - < < < < < < < < 5 5 5 5 5 5 B B B B B B < < < < < < < <g&&lR lR lR lR lRo lR lR lR lR lRr+   