
    i^`                       d Z ddlmZ ddlZddlZ	 ddlZddlmZ n# e	$ r ddlZddl
mZ Y nw xY w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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/ ddl0m1Z1  ej2        d          Z3e"e!gZ4e"e#gZ5 G d d          Z6 G d de6          Z7dS )a   
Synchronous JMAP client.

Wraps session establishment, HTTP communication, and method dispatching
into a single object with a clean public API.

Auth note: JMAP has no 401-challenge-retry dance (unlike CalDAV).
Credentials are sent upfront on every request. A 401/403 is a hard failure.
    )annotationsN)HTTPBasicAuth)build_calendar_getparse_calendar_get)	build_event_changesbuild_event_getbuild_event_query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)CALENDAR_CAPABILITYCORE_CAPABILITYTASK_CAPABILITY)ical_to_jscal)JMAPAuthErrorJMAPMethodError)JMAPCalendarJMAPCalendarObject)Sessionfetch_session)HTTPBearerAuthzcaldav.jmapc                  J    e Zd Z	 	 	 	 	 dddZddZddZedd            ZdS ) _JMAPClientBaseN   urlstrusername
str | Nonepassword	auth_typetimeoutintreturnNonec                    || _         || _        || _        || _        d | _        |	|| _        d S |                     |          | _        d S N)r&   r(   r*   r,   _session_cache_auth_build_auth)selfr&   r(   r*   authr+   r,   s          M/root/projects/butler/venv/lib/python3.11/site-packages/caldav/jmap/client.py__init__z_JMAPClientBase.__init__;   sR       .2DJJJ)))44DJJJ    c                   |}|*| j         rd}n | j        rd}nt          | j        d          |dk    r>| j         r| j        st          | j        d          t	          | j         | j                  S |dk    r1| j        st          | j        d          t          | j                  S t          | j        d|d	          )
a  Select and construct the auth object.

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

        JMAP supports Basic and Bearer auth; Digest is not supported.
        When ``auth_type`` is ``None`` the type is inferred from the
        credentials supplied: a username triggers Basic, a password
        alone triggers Bearer, and neither raises :class:`JMAPAuthError`.
        NbasicbearerzDNo credentials provided. Supply username+password or a bearer token.r&   reasonz/Basic auth requires both username and password.z?Bearer auth requires a token supplied as the password argument.zUnsupported auth_type z. Use 'basic' or 'bearer'.)r(   r*   r   r&   r   r"   )r5   r+   effective_types      r7   r4   z_JMAPClientBase._build_authO   s    #!} !( !)#a   
 W$$=  #L    !>>>x''= #\    "$-000H\\\\   r9   sessionr    errdictc                ^    t          |j        d| |                    dd                    )Nzset failed: typeserverErrorr&   r>   
error_type)r   api_urlget)r5   r@   rA   s      r7   _raise_set_errorz _JMAPClientBase._raise_set_errory   s:    '#''wwv}55
 
 
 	
r9   
account_idcalendar_idstartendtextlist[tuple]c                    i }||g|d<   |||d<   |||d<   |||d<   t          | |pd          }d| dd	d
dddf}||gS )zPReturn a batched [CalendarEvent/query, CalendarEvent/get] call list for _search.NinCalendarsafterbeforerO   )filter_conditionCalendarEvent/getz
ev-query-0zCalendarEvent/queryz/ids)resultOfnamepath)	accountIdz#idszev-get-1)r	   )rK   rL   rM   rN   rO   filter_dict
query_callget_calls           r7   _build_event_search_callsz)_JMAPClientBase._build_event_search_calls   s     "*5K&#(K ?$'K!"&K&zKDWSWXXX
' ,1"   
 H%%r9   )NNNNr%   )r&   r'   r(   r)   r*   r)   r+   r)   r,   r-   r.   r/   )r+   r)   )r@   r    rA   rB   r.   r/   )rK   r'   rL   r)   rM   r)   rN   r)   rO   r)   r.   rP   )__name__
__module____qualname__r8   r4   rJ   staticmethodr^    r9   r7   r$   r$   :   s          $# $5 5 5 5 5(( ( ( (T
 
 
 
 & & & \& & &r9   r$   c                      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
JMAPClienta  Synchronous JMAP client for calendar operations.

    Usage::

        from caldav.jmap import get_jmap_client
        client = get_jmap_client(url="https://jmap.example.com/.well-known/jmap",
                                  username="alice", password="secret")
        calendars = 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 requests-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.
    r.   c                    | S r1   rc   r5   s    r7   	__enter__zJMAPClient.__enter__   s    r9   r/   c                    d S r1   rc   )r5   exc_typeexc_valexc_tbs       r7   __exit__zJMAPClient.__exit__   s    tr9   r    c                j    | j         &t          | j        | j        | j                  | _         | j         S )z5Return the cached Session, fetching it on first call.N)r6   r,   )r2   r!   r&   r3   r,   rg   s    r7   _get_sessionzJMAPClient._get_session   s3    &"/tzSWS_"`"`"`D""r9   Nmethod_callsrP   usinglist[str] | Nonelistc                d   |                                  }||nt          t          |          d}t                              d|j        t          |                     t          j        |j        || j	        ddd| j
                  }|j        dv rt          |j        d|j         d	
          |                                 |                                }|                    dg           }|D ]>}|\  }	}
}|	dk    r0|
                    dd          }t!          |j        d|
 |          ?|S )a  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.
            requests.HTTPError: On other non-2xx HTTP responses.
        N)rq   methodCallsz"JMAP POST to %s: %d method call(s)zapplication/json)zContent-TypeAccept)jsonr6   headersr,   )i  i  zHTTP z from API endpointr=   methodResponseserrorrD   rE   zMethod call failed: rF   )ro   _DEFAULT_USINGrs   logdebugrH   lenrequestspostr3   r,   status_coder   raise_for_statusrw   rI   r   )r5   rp   rq   r@   payloadresponsedatamethod_responsesrespmethod_name	resp_argscall_idrG   s                r7   _requestzJMAPClient._request   st   " ##%% $/UU^--
 

 			6\IZIZ[[[=O%7CUVVL
 
 
 :--OGx3GGG   
 	!!###}}88$5r::$ 	 	D.2+KGg%%&]]6=AA
%=)==)    &  r9   list[JMAPCalendar]c                    |                                  }t          |j                  }|                     |g          }|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.
        zCalendar/getF)ro   r   rK   r   r   _client	_is_async)	r5   r@   call	responsesr   r   _	calendarscals	            r7   get_calendarszJMAPClient.get_calendars   s     ##%%!'"455MM4&))	)2 	! 	!%KAn,,.y99	$ * *C"&CK$)CMM     - 	r9   rL   r'   ical_strc                   |                                  }t          ||          }t          |j        d|i          }|                     |g          }|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.
        )rL   new-0CalendarEvent/setz:CalendarEvent/set response missing created entry for new-0r=   idNo CalendarEvent/set response)	ro   r   r
   rK   r   r   rJ   r   rH   )r5   rL   r   r@   jscalr   r   r   r   r   creatednot_createds               r7   create_eventzJMAPClient.create_event  s    ##%%hK@@@%g&87E:JKKMM4&))	)2 
	. 
	.%KA1113B93M3M0A{Aqk))))';w3GHHH')))#O[    w'---- 2 '/:YZZZZr9   event_idr   c                V   |                                  }t          |j        |g          }|                     |g          }|D ]P\  }}}|dk    rDt	          |          }|st          |j        d| d          t          |d         d          c S Qt          |j        d	
          )a  Fetch a calendar event by JMAP event ID.

        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.
        idsrV   zEvent not found: notFoundrF   r   Nr   parentNo CalendarEvent/get responser=   )ro   r   rK   r   r   r   rH   r   )	r5   r   r@   r   r   r   r   r   itemss	            r7   	get_eventzJMAPClient.get_event/  s     ##%%w1zBBBMM4&))	)2 		F 		F%KA111'	22 )#O=8==#-   
 *uQxEEEEEE 2 '/:YZZZZr9   c                   |                                  }t          |          }|                    dd           t          |j        ||i          }|                     |g          }|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.
        uidNr   r   r=   )
ro   r   popr   rK   r   r   rJ   r   rH   )r5   r   r   r@   patchr   r   r   r   r   not_updateds              r7   update_eventzJMAPClient.update_eventO  s     ##%%h''		%%g&88U:KLLMM4&))	)2 	 	%KA111-<Y-G-G*1aK{**))';x3HIII	 2 '/:YZZZZr9   r)   rM   rN   rO   r   JMAPCalendar | Nonelist[JMAPCalendarObject]c                    |                                  }|                     |j        ||||          }|                     |          }|D ])\  }	}
}|	dk    rfdt	          |
          D             c S *g S )NrV   c                2    g | ]}t          |           S )r   r   ).0itemr   s     r7   
<listcomp>z&JMAPClient._search.<locals>.<listcomp>v  s6        'D@@@  r9   )ro   r^   rK   r   r   )r5   rL   rM   rN   rO   r   r@   callsr   r   r   r   s        `      r7   _searchzJMAPClient._searchh  s     ##%%..w/A;PUWZ\`aaMM%((	)2 	 	%KA111    /	 : :      2 	r9   c                4    |                      ||||          S )a  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 since no
            :class:`~caldav.jmap.objects.calendar.JMAPCalendar` is available at
            the client level; use :meth:`JMAPCalendar.search` if you need ``parent``
            set.
        )rL   rM   rN   rO   )r   )r5   rL   rM   rN   rO   s        r7   search_eventszJMAPClient.search_events}  s    4 ||5cPT|UUUr9   c                    |                                  }t          |j        g           }|                     |g          }|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.
        r   rV   state r   r=   )ro   r   rK   r   rI   r   rH   r5   r@   r   r   r   r   r   s          r7   get_sync_tokenzJMAPClient.get_sync_token  s     ##%%w1r:::MM4&))	)2 	2 	2%KA111 }}Wb11111 2'/:YZZZZr9   
sync_tokenDtuple[list[JMAPCalendarObject], list[JMAPCalendarObject], list[str]]c                6   |                                  }t          |j        |          }|                     |g          }g }g }g }|D ];\  }}	}
|dk    r/t	          |	          \  }
}
}}}}|rt          |j        dd          <||z   }|sg g |fS t          |j        |          }|                     |g          }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``.
        zCalendarEvent/changeszCalendarEvent/changes response was truncated by the server (hasMoreChanges=true). Call get_sync_token() to obtain a fresh baseline and re-sync.serverPartialFailrF   r   rV   Nr   r   c                (    g | ]}|v |         S rc   rc   r   ievents_by_ids     r7   r   z8JMAPClient.get_objects_by_sync_token.<locals>.<listcomp>  s'    KKKQl9J9Ja9J9J9Jr9   c                (    g | ]}|v |         S rc   rc   r   s     r7   r   z8JMAPClient.get_objects_by_sync_token.<locals>.<listcomp>  s'    NNNA<M<MLO<M<M<Mr9   )
ro   r   rK   r   r   r   rH   r   r   r   )r5   r   r@   changes_callr   created_idsupdated_ids	destroyedr   r   r   has_more	fetch_idsr]   get_responsesr   addedmodifiedr   s                     @r7   get_objects_by_sync_tokenz$JMAPClient.get_objects_by_sync_token  s   2 ##%%*7+=zJJMM<.11	!#!#!	)2 	 	%KA555FYZcFdFdC1h[) 	)#O: $7     +-	 	%r9$$"7#59EEExj11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	))r9   c                >   |                                  }t          |j        |g          }|                     |g          }|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.
        r   Nr   r=   )ro   r   rK   r   r   rJ   r   rH   )	r5   r   r@   r   r   r   r   r   not_destroyeds	            r7   delete_eventzJMAPClient.delete_event  s     ##%%&w'9H:FFMM4&))	)2 	 	%KA111/>y/I/I,1aA}},,))'=3JKKK	 2 '/:YZZZZr9   r   c                    |                      ||          D ]$}|j                            d          |k    r|c S %t          |                                 j        d|           )N)rL   r   r   z#No calendar object found with UID: r=   )r   r   rI   r   ro   rH   )r5   r   rL   r   objs        r7   _get_object_by_uidzJMAPClient._get_object_by_uid  s     <<K<GG 	 	Cx||E""c))


 * !!##+4_Z]4_4_
 
 
 	
r9   
list[dict]c                    |                                  }t          |j                  }|                     |gt                    }|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.
        rq   zTaskList/get)ro   r   rK   r   _TASK_USINGr   r   s          r7   get_task_listszJMAPClient.get_task_lists  s}     ##%%"7#566MM4&M<<	)2 	6 	6%KAn,,*955555 - 	r9   task_list_idtitlec                   |                                  }dt          t          j                              ||dddd}|                    |           t          |j        d|i          }|                     |gt                    }|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.
        Taskr   zneeds-action)z@typer   
taskListIdr   percentCompleteprogresspriorityr   r   Task/setr   No Task/set responser=   )ro   r'   uuiduuid4updater   rK   r   r   r   rJ   r   rH   )r5   r   r   kwargsr@   	task_dictr   r   r   r   r   r   r   s                r7   create_taskzJMAPClient.create_task  s     ##%%tz||$$& &
 
	 	   $W%7'99MNNMM4&M<<	)2 	. 	.%KAj((3A)3L3L0A{Aqk))))';w3GHHHw'----	 ) '/:PQQQQr9   task_idrB   c                T   |                                  }t          |j        |g          }|                     |gt                    }|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.
        r   r   zTask/getrs   zTask not found: r   rF   r   zNo Task/get responser=   )ro   r   rK   r   r   rI   r   rH   )	r5   r   r@   r   r   r   r   r   r   s	            r7   get_taskzJMAPClient.get_taskD  s     ##%%g0wi@@@MM4&M<<	)2 		  		 %KAj((!fb11 )#O;';;#-   
 Qx ) '/:PQQQQr9   r   c                N   |                                  }t          |j        ||i          }|                     |gt                    }|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.
        r   r   Nr   r=   )	ro   r   rK   r   r   r   rJ   r   rH   )
r5   r   r   r@   r   r   r   r   r   r   s
             r7   update_taskzJMAPClient.update_taska  s     ##%%$W%7'59IJJMM4&M<<	)2 	 	%KAj((-;I-F-F*1aKk))))';w3GHHH	 ) '/:PQQQQr9   c                L   |                                  }t          |j        |g          }|                     |gt                    }|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.
        r   r   Nr   r=   )	ro   r   rK   r   r   r   rJ   r   rH   )	r5   r   r@   r   r   r   r   r   r   s	            r7   delete_taskzJMAPClient.delete_taskx  s     ##%%%g&87)DDMM4&M<<	)2 	 	%KAj((/=i/H/H,1aA}m++))'=3IJJJ	 ) '/:PQQQQr9   )r.   re   )r.   r/   )r.   r    r1   )rp   rP   rq   rr   r.   rs   )r.   r   )rL   r'   r   r'   r.   r'   )r   r'   r.   r   )r   r'   r   r'   r.   r/   )NNNNN)rL   r)   rM   r)   rN   r)   rO   r)   r   r   r.   r   )NNNN)
rL   r)   rM   r)   rN   r)   rO   r)   r.   r   )r.   r'   )r   r'   r.   r   )r   r'   r.   r/   )NN)r   r'   rL   r)   r   r   r.   r   )r.   r   )r   r'   r   r'   r.   r'   )r   r'   r.   rB   )r   r'   r   rB   r.   r/   )r   r'   r.   r/   )r_   r`   ra   __doc__rh   rm   ro   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rc   r9   r7   re   re      s        &      # # # #7  7  7  7  7 r   ([ [ [ [@[ [ [ [@[ [ [ [6 #' &*    . #' V V V V V8[ [ [ [$>* >* >* >*@[ [ [ [. W[

 

 

 

 

    %R %R %R %RNR R R R:R R R R.R R R R R Rr9   re   )8r   
__future__r   loggingr   niquestsr   niquests.authr   ImportErrorrequests.authcaldav.jmap._methods.calendarr   r   caldav.jmap._methods.eventr   r   r	   r
   r   r   r   r   r   caldav.jmap._methods.taskr   r   r   r   r   r   r   caldav.jmap.constantsr   r   r   caldav.jmap.convertr   caldav.jmap.errorr   r   caldav.jmap.objects.calendarr   #caldav.jmap.objects.calendar_objectr   caldav.jmap.sessionr    r!   caldav.requestsr"   	getLoggerr|   r{   r   r$   re   rc   r9   r7   <module>r     s    # " " " " "  ,+++++++ , , ,OOO++++++++, Q P P P P P P P
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
                  X W W W W W W W W W - - - - - - < < < < < < < < 5 5 5 5 5 5 B B B B B B 6 6 6 6 6 6 6 6 * * * * * *g&&!#670e& e& e& e& e& e& e& e&PjR jR jR jR jR jR jR jR jR jRs   
 //