o
    .j)                     @  s   d 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 ddlmZ erBddlmZmZ dd	lmZ dd
lmZmZ G dd dZdS )z%Parsing a component's iCalendar data.    )annotations)TYPE_CHECKINGClassVar)ContentlineContentlines)split_on_unescaped_comma)vBroken)tzp)	ComponentComponentFactory)
Parameters)	VPROPERTYTypesFactoryc                   @  s   e Zd ZU dZdZded< 	 dAddZded< dBddZdCddZdd Z	dDddZ
dEd d!ZdEd"d#ZdFd$d%ZdGd'd(ZdFd)d*ZedHd,d-ZdId1d2ZdJd5d6ZdKd:d;ZdLd<d=ZdMd>d?Zd@S )NComponentIcalParserzA parser for a component's iCalendar data.

    This uses the template method pattern, where the main parsing
    logic can be refined in subclasses.
    )DTSTARTDTENDzRECURRENCE-IDDUERDATEEXDATEzClassVar[tuple[str, ...]]datetime_namesdatabytes | str | list[Contentline]component_factoryr   types_factoryr   c                 C  s   || _ || _|| _t| _dS )aL  Initialize the parser with the raw data.

        Parameters:
            data: The raw iCalendar data to parse, either as bytes
                or a list of content lines.
            component_factory: The factory to use for creating components.
            types_factory: The factory to use for creating property values.
        N)_data_component_factory_types_factoryr	   _tzp)selfr   r   r    r   T/home/thesage/.local/lib/python3.10/site-packages/icalendar/parser/ical/component.py__init__'   s   
zComponentIcalParser.__init__zlist[Contentline]_content_linesnamestrreturnboolc                   s,   |    d|   t fdd| jD S )z)Check if the parser contains a component.zBEGIN:c                 3  s,    | ]}t |t  ko|  kV  qd S N)lenupper).0content_line
begin_liner   r    	<genexpr>@   s
    
z9ComponentIcalParser.contains_component.<locals>.<genexpr>)initialize_parsingr)   anyr"   )r   r#   r   r,   r    contains_component<   s
   z&ComponentIcalParser.contains_componentuidc                   s    |    t fdd| jD S )zDetermines whether the component contains a ``uid``.

        Returns:
            ``True`` if the component contains a ``uid``, else ``False``.
        c                 3  s    | ]} |v V  qd S r'   r   )r*   liner2   r   r    r.   L   s    z3ComponentIcalParser.contains_uid.<locals>.<genexpr>)r/   r0   r"   )r   r2   r   r4   r    contains_uidE   s   z ComponentIcalParser.contains_uidc                 C  sB   g | _ g | _t| jtr| jnt| j | _| _t| j| _	d S r'   )
_stack_components
isinstancer   listr   	from_icalr"   iter_content_lines_iteratorr   r   r   r    r/   N   s   


z&ComponentIcalParser.initialize_parsing	exception	Exceptionc                 C  s,   | j }|r|js
||jdt|f dS )zHandle a line parsing error.N)	componentignore_exceptionserrorsappendr$   )r   r>   r@   r   r   r    handle_line_parse_errorX   s   
z+ComponentIcalParser.handle_line_parse_errorvalsNonec                 C  s<   |  }| j|}| }t|dds||_| j| dS )z$Handle the beginning of a component.r#    N)r)   r   get_component_classgetattrr#   r6   rC   )r   rE   c_namec_classr@   r   r   r    handle_begin_componentb   s   z*ComponentIcalParser.handle_begin_componentc                 C  sf   | j std| j  }| j s| j| n| j d | | dkr/d|v r1t| dS dS dS )zHandle the end of a component.z.END encountered without an accompanying BEGIN!	VTIMEZONETZIDN)	r6   
ValueErrorpopr7   rC   add_componentr)   r	   cache_timezone_component)r   rE   r@   r   r   r    handle_end_componentq   s   
z(ComponentIcalParser.handle_end_componentc                 C  s   dS )z_Prepare the parsed components.

        This is called when all components are parsed.
        Nr   r=   r   r   r    prepare_components   s    z&ComponentIcalParser.prepare_componentslist[Component]c                 C  s   |    |   |   | jS )zParse the raw data.)r/   parse_content_linesrU   r7   r=   r   r   r    parse   s   zComponentIcalParser.parsec                 C  s   | j D ]F}|sqz	| \}}}W n ty( } z| | W Y d}~qd}~ww | }|dkr7| | q|dkrA| | q| |||| qdS )zParse the content lines.NBEGINEND)r<   partsrP   rD   r)   rL   rT   handle_property)r   r3   r#   paramsrE   eunamer   r   r    rW      s"   

z'ComponentIcalParser.parse_content_linesComponent | Nonec                 C  s   | j r| j d S d S )NrM   )r6   r=   r   r   r    r@      s   zComponentIcalParser.componentr]   r   r   c                 C  s   | j ||jS )zGet the factory for a property.)r   for_propertyvalue)r   r#   r]   r   r   r    get_factory_for_property   s   z,ComponentIcalParser.get_factory_for_propertyr3   r   c                 C  s   | j s|dkr	dS td| d|r|| jv r|dnd}|dkr0| |||r,dS |g}n|dkr:|d}n|d	krE|d
krEg }n|g}|D ]}| ||||| qJdS )a4  Handle a property line.

        Add properties to the top of the current stack.

        Parameters:
            name: The name of the property, uppercased.
            params: The parameters of the property.
            vals: The value of the property.
            line: The original content line.
        z	X-COMMENTNz
Property "z#" does not have a parent component.rO   
CATEGORIESFREEBUSY,r   rG   )r@   rP   r   gethandle_categoriessplitparse_and_add_property)r   r#   r]   rE   r3   tzid	vals_listvalr   r   r    r\      s"   z#ComponentIcalParser.handle_propertyrm   rk   
str | Nonec           
   
   C  s   |  ||}z|r|||}n||}W n ttfy4 } z| ||||| W Y d}~dS d}~ww ||}	||	_| jj||	dd dS )z;Parse a property value and add it to the current component.NFencode)rc   r:   rP   	TypeErrorhandle_property_parse_errorr]   r@   add)
r   r#   r]   rm   rk   r3   factory
parsed_valr^   	vals_instr   r   r    rj      s   	
 z*ComponentIcalParser.parse_and_add_propertyc           	      C  sx   | j js|dd  dks|| ||}t|dd}tj|||||d}| j j|t	|f | j j
||dd dS )	z&Handle the parse error for a property.N   zX-__name__unknown)	raw_valuer]   property_nameexpected_typeerrorr   ro   )r@   rA   r)   rc   rI   r   from_parse_errorrB   rC   r$   rs   )	r   r>   r#   r]   rm   r3   rt   r|   broken_propr   r   r    rr      s   	z/ComponentIcalParser.handle_property_parse_errorc              
   C  s   t |}|d}|dkrO||d d }zt|}| d|}||}	||	_| jjd|	dd W dS  tyN }
 z| |
d||| W Y d}
~
dS d}
~
ww dS )	z{Handle the special case of CATEGORIES property.

        Returns:
            ``True`` if handled, else ``False``.
        :r      Nrd   ro   TF)	r$   rfindr   rc   r]   r@   rs   rP   rr   )r   r]   rE   r3   line_str	colon_idxrz   category_listrt   rv   r^   r   r   r    rh     s&   


z%ComponentIcalParser.handle_categoriesN)r   r   r   r   r   r   )r#   r$   r%   r&   )r2   r$   r%   r&   )r>   r?   )rE   r$   r%   rF   )r%   rF   )r%   rV   )r%   r`   )r#   r$   r]   r   r%   r   )
r#   r$   r]   r   rE   r$   r3   r   r%   rF   )
r#   r$   r]   r   rm   r$   rk   rn   r3   r   )
r>   r?   r#   r$   r]   r   rm   r$   r3   r   )r]   r   rE   r$   r3   r   r%   r&   )rx   
__module____qualname____doc__r   __annotations__r!   r1   r5   r/   rD   rL   rT   rU   rX   rW   propertyr@   rc   r\   rj   rr   rh   r   r   r   r    r      s,   
 


		










+
r   N)r   
__future__r   typingr   r   icalendar.parser.content_liner   r   icalendar.parser.propertyr   icalendar.propr   icalendar.timezoner	   icalendar.calr
   r   icalendar.parser.parameterr   r   r   r   r   r   r   r    <module>   s    