o
    .j8                     @  sp  U d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	m
Z
mZmZ zddlmZ W n ey>   ddlmZ Y nw 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 dd	lmZ dd
lmZ ddlmZ ddl m!Z! erddlm"Z" ddlm#Z# ddl$m%Z% ddl&m'Z'm(Z( ej)dkree*e+e B eB  Z,de-d< nee* Z,de-d< G dd dZ.ddgZ/dS )z:Core functionality: querying the calendar for occurrences.    )annotationsN)TYPE_CHECKINGClassVar	GeneratorOptionalSequence)	TypeAlias)ComponentAdapter)DATE_MAX_DTDATE_MIN_DT)BadRuleStringFormatInvalidCalendarPeriodEndBeforeStart)OccurrenceID)Pages)SelectComponents)compare_greater)	Component)
Occurrence)Series)DateArgumentTime)   
   r   T_COMPONENTSc                   @  s   e Zd ZU dZeeejgZde	d< ddl
mZ 			dEdFddZedGddZdHddZejddejddejddejddgZdGddZdId#d$ZdJd(d)ZdKd,d-ZdLd.d/ZdMd1d2ZdNd4d5ZdOd7d8ZedPd9d:Z	;	;	<dQdRdCdDZd;S )SCalendarQuerya  Query a calendar for occurrences.

    Functions like :meth:`at`, :meth:`between` andm :meth:`after`
    can be used to query the selected components.
    If any malformed icalendar information is found,
    an :class:`InvalidCalendar` exception is raised.
    For other bad arguments, you should expect a :class:`ValueError`.

    Attributes:
        suppressed_errors: a list of errors to suppress when
            skip_bad_series is True
    zClassVar[type[Exception]]suppressed_errorsr   )ComponentsWithNameFVEVENTcalendarr   keep_recurrence_attributesbool
componentsr   skip_bad_seriesc                 C  sv   || _ |dddkrtdg | _|rt| jnd| _|D ]}t|tr+| 	|}n|}| j
||| j qdS )aA  Create an unfoldable calendar from a given calendar.

        Arguments:
            calendar: an :class:`icalendar.cal.Calendar` component like
                :class:`icalendar.cal.Calendar`.
            keep_recurrence_attributes: Whether to keep attributes that are only used
                to calculate the recurrence (``RDATE``, ``EXDATE``, ``RRULE``).
            components: A list of component type names of which the recurrences
                should be returned. This can also be instances of
                :class:`SelectComponents`.
                Examples: ``("VEVENT", "VTODO", "VJOURNAL", "VALARM")``
            skip_bad_series: Whether to skip series of components that contain
                errors. You can use :attr:`CalendarQuery.suppressed_errors` to
                specify which errors to skip.
        CALSCALE	GREGORIANz'Only Gregorian calendars are supported. N)r!   getr   seriestupler   _skip_errors
isinstancestrr   extendcollect_series_from)selfr    r!   r#   r$   component_adapter_idcomponent_adapterr'   r'   P/home/thesage/.local/lib/python3.10/site-packages/recurring_ical_events/query.py__init__D   s   
zCalendarQuery.__init__dater   c                 C  sn   t | tr| f} t | tr| ddt|   7 } tj|  S t | tr5t| dkr.tj| dS tj| dS | S )a  Convert date inputs of various sorts into a datetime object.

        Arguments:
            date: A date specification.

        Date Specification:

        - a year like ``(2019,)`` or ``2019`` (:class:`int`)
        - a month like ``(2019, 1)`` for January of 2019
        - a day like ``(2019, 1, 19)`` for the first of January 2019
        - a day with hours, ``(2019, 1, 19, 1)``
        - a day with minutes, ``(2019, 1, 19, 13, 30 )``
        - a day with seconds, ``(2019, 1, 19, 13, 30, 59)``
        - a :class:`datetime.datetime` or :class:`datetime.date`
        - a :class:`str` in the format ``yyyymmdd``
        - a :class:`str` in the format ``yyyymmddThhmmssZ``

        )   r      z%Y%m%dz%Y%m%dT%H%M%SZ)r,   intr*   lendatetimer-   strptime)r5   r'   r'   r3   to_datetimej   s   



zCalendarQuery.to_datetimereturnGenerator[Component]c                 C  s
   |  tS )zGenerate all Components.

        The Components are sorted from the first to the last Occurrence.
        Calendars can contain millions of Occurrences. This iterates
        safely across all of them.
        )afterr   r0   r'   r'   r3   all   s   
zCalendarQuery.allr6   days)hoursminutes)secondsc                 C  sX  t |tr|f}t |tr8t|dks| std|dt|dd dt|dd dt|dd f}t |tjrD| ||S t |tjrV| ||tj	dd	 S t|dkrn| |d
 ddf|d
 d ddfS t|dkr|\}}|dkr| |ddf|d ddfS | ||df||d dfS | 
|}| ||| jt|d   S )a  Return all events within the next 24 hours of starting at the given day.

        Arguments:
            date: A date specification, see :meth:`to_datetime`.

        This is translated to :meth:`between` in the following way:

        - A year returns all occurrences within that year.
            Example: ``(2019,)``, ``2019``
        - A month returns all occurrences within that month.
            Example: ``(2019, 1)``
        - A day returns all occurrences within that day.
            Examples:

            - ``(2019, 1, 19)``
            - ``datetime.date(2019, 1, 19)``
            - ``"20190101"``

        - An hour returns all occurrences within that hour.
            Example: ``(2019, 1, 19, 1)``
        - A minute returns all occurrences within that minute.
            Example: ``(2019, 1, 19, 13, 30 )``
        - A second returns all occurrences at that exact second.
            Examples:

            - ``(2019, 1, 19, 13, 30, 59)``
            - ``datetime.datetime(2019, 1, 19, 13, 30, 59)``
            - ``datetime.datetime(2019, 1, 19, tzinfo=datetime.timezone.utc)``,
            - ``datetime.datetime(2019, 1, 19, 13, 30, 59, tzinfo=ZoneInfo('Europe/London'))``
            - ``"20190119T133059Z"``
        r7   zFormat yyyymmdd expected for .N   r      r6   rB   r         r   )r,   r8   r-   r9   isdigit
ValueErrorr:   betweenr5   	timedeltar<   _between_DELTAS)r0   r5   yearmonthdtr'   r'   r3   at   s&   
 
2$
zCalendarQuery.atstartstop!DateArgument | datetime.timedeltac                 C  s4   |  |}t|tjr|| n|  |}| ||S )a  Return events at a time between start (inclusive) and end (inclusive)

        Arguments:
            start: A date specification. See :meth:`to_datetime`.
            stop: A date specification or a :class:`datetime.timedelta`
                relative to start.

        .. warning::

            If you pass a :class:`datetime.datetime` to both ``start`` and
            ``stop``, make sure the :attr:`datetime.datetime.tzinfo` is
            the same.
        )r<   r,   r:   rP   rQ   )r0   rW   rX   r'   r'   r3   rO      s   


zCalendarQuery.betweenoccurrenceslist[Occurrence]list[Component]c                   s    fdd|D S )zMap occurrences to components.c                   s   g | ]}|  jqS r'   )as_componentr!   ).0
occurrencer@   r'   r3   
<listcomp>   s    
z<CalendarQuery._occurrences_to_components.<locals>.<listcomp>r'   )r0   rZ   r'   r@   r3   _occurrences_to_components   s   
z(CalendarQuery._occurrences_to_componentsr   endc                 C  s   |  | ||S )z5Return the occurrences between the start and the end.)ra   _occurrences_between)r0   rW   rb   r'   r'   r3   rQ      s   zCalendarQuery._betweenc              	   C  sR   g }| j D ]!}t| j |||| W d   n1 s!w   Y  q|S )z4Return the components between the start and the end.N)r)   
contextlibsuppressr+   r.   rO   )r0   rW   rb   rZ   r)   r'   r'   r3   rc      s   
z"CalendarQuery._occurrences_betweenearliest_endc                 c  s.    |  |}| |D ]	}|| jV  qdS )a  Iterate over components happening during or after earliest_end.

        Arguments:
            earliest_end: A date specification. See :meth:`to_datetime`.
                Anything happening during or after earliest_end is returned
                in the order of start time.
        N)r<   _afterr]   r!   )r0   rf   r_   r'   r'   r3   r?      s
   
zCalendarQuery.afterGenerator[Occurrence]c           	      c  s    t jdd}t jdd}d}t }|s`z|| }W n ty/   t}t||r+Y dS d}Y nw | ||}|  |D ]}|j|vrL|V  |	|j q<t
|rT|d n|d |}|}|rdS dS )	z@Iterate over occurrences happening during or after earliest_end.r6   rB      rE   FNTrK   )r:   rP   setOverflowErrorr
   r   rc   sortidaddmax)	r0   rf   	time_spanmin_time_spandone
result_idsnext_endrZ   r_   r'   r'   r3   rg     s6   

zCalendarQuery._afterr8   c                 C  s   d}|   D ]}|d7 }q|S )zReturn the amount of recurring components in this calendar.

        .. warning::

            Do not use this in production as it generates all occurrences.
        r   r6   )rA   )r0   i_r'   r'   r3   count#  s   
zCalendarQuery.countc                 C  s   |   D ]}|  S td)zReturn the first recurring component in this calendar.

        Returns:
            The first recurring component in this calendar.

        Raises:
            IndexError: if the calendar is empty
        zNo components found.)rA   
IndexError)r0   	componentr'   r'   r3   first/  s   
zCalendarQuery.firstN 	page_sizeOptional[DateArgument]latest_startnext_page_idr-   r   c           
      C  s   |du rdn|  |}|du rtn|  |}|r[t|}t||jsU| |j}g }|D ]&}|| |j}	|	|krDt	
|g|} nt|	j|jrSt	
||} nq-n| |}n| |}t|||| jdS )at  Return pages for pagination.

        Args:
            page_size: the number of components per page
            earliest_end: the start of the first page
                All components occur after this date.
                See :meth:`to_datetime` for possible values.
            latest_start: the end of the last page
                All components occur before this date.
                See :meth:`to_datetime` for possible values.
            next_page_id: The id of the next page.
                This is optional for the first page.
                These are safe to pass outside of the application and back in.
        N)occurrence_iteratorsizerX   r!   )r<   r   r   from_stringr   rW   rg   appendrm   	itertoolschainr   r!   )
r0   r|   rf   r~   r   first_occurrence_iditeratorlost_occurrencesr_   oidr'   r'   r3   paginate=  s6   


zCalendarQuery.paginate)Fr   F)r    r   r!   r"   r#   r   r$   r"   )r5   r   )r=   r>   )rW   r   rX   rY   )rZ   r[   r=   r\   )rW   r   rb   r   r=   r\   )rW   r   rb   r   r=   r[   )rf   r   r=   r>   )rf   r   r=   rh   )r=   r8   )r=   r   )NNr{   )
r|   r8   rf   r}   r~   r}   r   r-   r=   r   )__name__
__module____qualname____doc__r   r   	icalendarr   r   __annotations__$recurring_ical_events.selection.namer   r4   staticmethodr<   rA   r:   rP   rR   rV   rO   ra   rQ   rc   r?   rg   rw   propertyrz   r   r'   r'   r'   r3   r   /   sB   
 &






4

	



r   )0r   
__future__r   rd   r:   r   systypingr   r   r   r   r   r   ImportErrortyping_extensionsr   (recurring_ical_events.adapters.componentr	   recurring_ical_events.constantsr
   r   recurring_ical_events.errorsr   r   r    recurring_ical_events.occurrencer   recurring_ical_events.pagesr   $recurring_ical_events.selection.baser   recurring_ical_events.utilr   r   r   recurring_ical_events.seriesr   recurring_ical_events.typesr   r   version_infor-   typer   r   r   __all__r'   r'   r'   r3   <module>   s@    
  C