o
    .jS                     @   s6  d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ 	 d5ddZd6ddZ	d7d
dZ
dedefddZdd Zeg dZ							d8dededB dedB dedededB dedeeef dB fddZdeeef dB fddZdedB dedB deeef dB fd d!Z	d9dedB dededB deeef dB fd"d#ZdedB dedB dee fd$d%ZdedB dee fd&d'ZG d(d) d)Zd*ed+edeeef fd,d-Zd.eeef deeef dB fd/d0Z	d9dedB dedB deeeef  fd1d2Z	d9dedB deeeeef f fd3d4ZdS ):    Nfnmatch)Anydefaultc                    s  dkr fdd D S t t dr\d  v rMg }|s#t  }|   d D ]}||vrJ||vrJt ||D ]}||vrI|| q>q.|S  di ddrYg S gS fd	d D }t  }|D ]}t |t dr~|t | qj|| qj|S )
af  
    In the "normal" case, will return [ section ]

    We allow:

    * * includes all sections in config file
    * "Meta"-sections in the config file with the keyword "contains" followed by a list of section names
    * Recursive "meta"-sections
    * Glob patterns (work_* for all sections starting with work_)
    * Glob patterns in "meta"-sections
    *c                    s    g | ]} |  d ds|qS )disableF)get.0x)config B/home/thesage/.local/lib/python3.10/site-packages/caldav/config.py
<listcomp>    s     z)expand_config_section.<locals>.<listcomp>z[*?containssectionr   Fc                    s   g | ]	}t | r|qS r   r   r	   )r   r   r   r   8       )set
isdisjointaddexpand_config_sectionappendr   update)r   r   	blacklistresults
subsectionrecursivesubsectionmatching_sectionssr   )r   r   r   r      s2   

r   c                 C   sF   || v rd| | v rt | | | d }ni }|| v r!|| |  |S )Ninherits)config_sectionr   )r   r   retr   r   r   r    C   s   r    Fc                 C   s  | s/t jdd d}| d| d| d| ddd	fD ]}t|}|r,|  S q i S zz t| d
}t|W  d    W W S 1 sHw   Y  W W i S  tjjy   zGdd l	}z#t| d
}|||j
W  d    W W  Y W S 1 s{w   Y  W n |jj|jjfy } ztd|  d| |d }~ww W n ty   td|  dd w Y W i S w  ty   td|  d i  Y S  ty    w )NHOME/z	/.config/z/caldav/calendar.confz/caldav/calendar.yamlz/caldav/calendar.jsonz/calendar.confz/etc/calendar.confz/etc/caldav/calendar.confrbr   zconfig file z! is neither valid JSON nor YAML: z/ is not valid JSON, and pyyaml is not installedz
 not found)osenvironr   read_configopenjsonloaddecoderJSONDecodeErroryamlLoaderscannerScannerErrorparserParserError
ValueErrorImportErrorFileNotFoundErrorloggingdebug)fninteractive_errorcfgdirconfig_filecfgr-   er   r   r   r'   M   s`   (.
r'   valuereturnc                 C   sh   t | trd}dtjdtfdd}t||| S t | tr&dd |  D S t | tr2dd	 | D S | S )
a9  
    Expand environment variable references in configuration values.

    Supports two syntaxes:
    - ${VAR} - expands to the value of VAR, or empty string if not set
    - ${VAR:-default} - expands to the value of VAR, or 'default' if not set

    Works recursively on dicts and lists.

    Examples:
        >>> os.environ['TEST_VAR'] = 'hello'
        >>> expand_env_vars('${TEST_VAR}')
        'hello'
        >>> expand_env_vars('${MISSING:-default_value}')
        'default_value'
        >>> expand_env_vars({'key': '${TEST_VAR}'})
        {'key': 'hello'}
    z\$\{([^}:]+)(?::-([^}]*))?\}matchr?   c                 S   s4   |  d}|  dd ur|  dnd}tj||S )N       )groupr%   r&   r   )r@   var_namer   r   r   r   replacer   s   
z!expand_env_vars.<locals>.replacerc                 S   s   i | ]	\}}|t |qS r   expand_env_varsr
   kvr   r   r   
<dictcomp>   r   z#expand_env_vars.<locals>.<dictcomp>c                 S   s   g | ]}t |qS r   rG   )r
   rK   r   r   r   r      s    z#expand_env_vars.<locals>.<listcomp>)
isinstancestrreMatchsubdictitemslist)r>   patternrF   r   r   r   rH   }   s   


rH   c                 C   s   ddl }| du r
dS t| tr$| }|dr|tdd }t|j|S t| tr_d| v r_| d }t|tr_|drC|tdd }t	t|j|}| 
 D ]\}}|dkr\|||< qP|S | S )a  Resolve a features specification into a dict suitable for FeatureSet.

    Supports:
    - None: returns None (backward compatibility mode)
    - str: looks up a named profile from compatibility_hints
      e.g. "synology" or "compatibility_hints.synology"
    - dict with "base" key: loads a named profile and merges overrides
      e.g. {"base": "synology", "search.is-not-defined": {"support": "fragile"}}
    - dict without "base": used as-is
    r   Nzcompatibility_hints.base)caldav.compatibility_hintsrM   rN   
startswithlengetattrcompatibility_hintsrR   copydeepcopyrS   )featurescaldavfeature_name	base_namebase_featureskeyr>   r   r   r   resolve_features   s(   



rd   )urlproxyusernamepasswordtimeoutheaders	huge_treessl_verify_certssl_certauth	auth_typer^   enable_rfc6764require_tlsprotocolTcheck_config_filer;   
testconfigenvironmentnameexplicit_paramsc           	      K   s   |rdd |  D }|ds|dr|S |r)|s!tjd}|s)tjd}|s3|rFtjdrFt|||}|dur?|S td	 dS |rOt }|rO|S | rZt||}|rZ|S dS )
aH  
    Get connection parameters from multiple sources.

    This is THE single source of truth for configuration discovery.
    Both sync and async get_davclient() functions should use this.

    Priority (first non-empty wins):
    1. Explicit parameters (url=, username=, password=, etc.)
    2. Test server config (if testconfig=True or PYTHON_CALDAV_USE_TEST_SERVER env var)
    3. Environment variables (CALDAV_URL, CALDAV_USERNAME, etc.)
    4. Config file (CALDAV_CONFIG_FILE env var or default locations)

    Test Server Mode:
        When testconfig=True or PYTHON_CALDAV_USE_TEST_SERVER env var is set,
        only config file sections with 'testing_allowed: true' will be used.
        This prevents accidentally using personal/production servers for testing.

        If no test server is found, returns None (does NOT fall through to
        regular config file or environment variables).

        Environment variable PYTHON_CALDAV_TEST_SERVER_NAME can specify which
        config section to use for testing.

    Args:
        check_config_file: Whether to look for config files
        config_file: Explicit path to config file
        config_section: Section name in config file (default: "default")
        testconfig: Whether to use test server configuration
        environment: Whether to read from environment variables
        name: Name of test server/config section to use (for testconfig)
        **explicit_params: Explicit connection parameters

    Returns:
        Dict with connection parameters (url, username, password, etc.)
        or None if no configuration found.
    c                 S   s   i | ]\}}|t v r||qS r   )CONNKEYSrI   r   r   r   rL     s    z)get_connection_params.<locals>.<dictcomp>re   r^   CALDAV_CONFIG_FILECALDAV_CONFIG_SECTIONPYTHON_CALDAV_USE_TEST_SERVERNzTest server mode enabled but no server with testing_allowed=true found. Add 'testing_allowed: true' to a config section to enable it for testing.)	rS   r   r%   r&   _get_test_server_configr6   info_get_env_config_get_file_config)	rs   r;   r    rt   ru   rv   rw   conn_paramsconnr   r   r   get_connection_params   s4   .
r   c                  C   sp   i } t jD ],}|dr1|ds1|dd  }|dkr d}n|dkr&d}|tv r1t j| | |< q| r6| S dS )	zBExtract connection parameters from CALDAV_* environment variables.CALDAV_CALDAV_CONFIG   Npassrh   userrg   )r%   r&   rX   lowerrx   )confenv_keyrc   r   r   r   r~   3  s   
r~   	file_pathsection_namec                 C   s*   |sd}t | }|sdS t||}t|S )z/Extract connection parameters from config file.r   N)r'   r    !_extract_conn_params_from_section)r   r   r<   section_datar   r   r   r   C  s   
r   c                 C   s   |r| du rt jd} t| |D ]5}|j}z|  W n ty6 } ztd|j	| W Y d}~qd}~ww t
d|j	|j t||  S t
d dS )a  
    Get connection parameters for a test server.

    Uses the priority-ordered server list as the single source of truth.
    Embedded servers (xandikos priority 10, radicale priority 10) beat docker
    (20) and configured / testing_allowed servers (30) by default.  Any server
    can override its priority via ``priority: <int>`` in its config.

    When running from the source tree the full registry is used (embedded +
    docker + external).  When caldav is pip-installed without the test
    infrastructure, only embedded servers from ``caldav.testing`` plus any
    ``testing_allowed`` config-file sections are available.

    Args:
        name: Optional server name or server_type to restrict selection.
        environment: Whether to read PYTHON_CALDAV_TEST_SERVER_NAME.
        config_file: Explicit config file path (for testing_allowed fallback).

    Returns:
        Connection parameters dict, or None if no server could be started.
    NPYTHON_CALDAV_TEST_SERVER_NAMEz"Failed to start test server %s: %szUsing test server: %s at %szPYTHON_CALDAV_USE_TEST_SERVER is set but no test server is available. Install xandikos or radicale, or add 'testing_allowed: true' to a config section.)r%   r&   r   _collect_test_servers_startedstart	Exceptionr6   warningrv   r}   re   _test_server_to_params)rv   ru   r;   serverwas_already_startedr=   r   r   r   r|   P  s"   r|   c                    sX   zddl m} t|  }W n ty   t|}Y nw  dur* fdd|D }|S )z
    Return a priority-ordered list of available test servers.

    Tries the full registry first (source tree); falls back to embedded
    servers from ``caldav.testing`` plus ``testing_allowed`` config sections
    (pip-installed users).
    r   )get_registryNc                    s,   g | ]}   |j  |j  fv r|qS r   )r   rv   server_type)r
   r   rv   r   r   r     s   , z)_collect_test_servers.<locals>.<listcomp>)tests.test_servers.registryr   rT   enabled_serversr4   _get_pip_test_servers)rv   r;   r   serversr   r   r   r   |  s   r   c                 C   s   ddl m}m} g }zddl}||  W n	 ty   Y nw zddl}||  W n	 ty5   Y nw t|  D ]\}}|t	|| q<t
|dd dS )z
    Build a server list for pip-installed users (no tests/ available).

    Includes embedded servers from caldav.testing and any testing_allowed
    sections from config files, all sorted by priority.
    r   )RadicaleServerXandikosServerNc                 S   s   | j S N)priority)r   r   r   r   <lambda>  s    z'_get_pip_test_servers.<locals>.<lambda>)rc   )caldav.testingr   r   xandikosr   r4   radicaleget_all_test_serversrS   _ConfiguredServersorted)r;   r   r   r   r   r   r   paramsr   r   r   r     s"   r   c                   @   s   e Zd ZdZdZdedeeef ddfddZe	de
fd	d
Ze	defddZe	dedB fddZe	dedB fddZe	defddZdddZdddZdefddZdS )r   z
    Thin wrapper around a ``testing_allowed`` config-file section.

    Used only in pip-installed mode; in the source tree these sections are
    loaded into the registry as ``ExternalTestServer`` instances instead.
    externalrv   r   r?   Nc                 C   s   || _ || _d| _d S NF)rv   _paramsr   )selfrv   r   r   r   r   __init__  s   
z_ConfiguredServer.__init__c                 C   s   t | jddS )Nr      )intr   r   r   r   r   r   r     s   z_ConfiguredServer.priorityc                 C   s   | j ddS )Nre   rC   r   r   r   r   r   r   re     s   z_ConfiguredServer.urlc                 C      | j dS )Nrg   r   r   r   r   r   rg        z_ConfiguredServer.usernamec                 C   r   )Nrh   r   r   r   r   r   rh     r   z_ConfiguredServer.passwordc                 C   r   )Nr^   r   r   r   r   r   r^     r   z_ConfiguredServer.featuresc                 C   
   d| _ d S )NTr   r   r   r   r   r        
z_ConfiguredServer.startc                 C   r   r   r   r   r   r   r   stop  r   z_ConfiguredServer.stopc                 C   s
   t | jS r   )boolre   r   r   r   r   is_accessible  r   z_ConfiguredServer.is_accessible)r?   N)__name__
__module____qualname____doc__r   rN   rR   r   r   propertyr   r   re   rg   rh   r^   r   r   r   r   r   r   r   r   r     s"    

r   r   r   c                 C   sX   | j | jd}| jr| j|d< | jr| j|d< | jr| j|d< |s*d| fdd|d< |S )	zFBuild a ``get_davclient``-compatible params dict from a server object.)re   _server_namerg   rh   r^   Nc                 S   s   |  S r   )r   )_clientr   r   r   r   r     s    z(_test_server_to_params.<locals>.<lambda>	_teardown)re   rv   rg   rh   r^   )r   r   r   r   r   r   r     s   


r   r   c                 C   s   i }| D ]=}| dr1| | }|dur0|dd }|dkr d}n|dkr&d}|tv r0t|||< q|dkrA| | rAt| | |d< q|d	rI|S dS )
us  Extract connection parameters from a config section dict.

    Returns a dict containing only CONNKEYS entries.  Returns ``None`` if no
    server URL is present.  Calendar filter keys (``calendar_name``,
    ``calendar_url``) are intentionally excluded — callers that need them
    (e.g. :func:`get_all_file_connection_params`) read ``section_data``
    directly.
    caldav_Nr   r   rh   r   rg   r^   re   )rX   rx   rH   rd   r   )r   r   rJ   r>   rc   r   r   r   r     s"   	
r   c           	      C   st   |sd}t | }|sg S t||}g }|D ]"}t||}t|}|r7dD ]}||r1|| ||< q$|| q|S )am  Return connection-params dicts for every leaf section that ``section_name`` expands to.

    ``section_name`` follows the same rules as everywhere else in the config
    system: a plain name returns ``[section_name]``; a meta-section with
    ``contains: [...]`` expands recursively; ``*`` means all non-disabled
    sections; glob patterns (``work_*``) are also supported.

    Each dict contains CONNKEYS entries plus optional ``calendar_name`` /
    ``calendar_url`` calendar-filter keys read from the config section.

    Returns an empty list when the config file is absent or the section has
    no usable URL.
    r   )calendar_namecalendar_url)r'   r   r    r   r   r   )	r;   r   r<   sectionsresultr   r   r   rJ   r   r   r   get_all_file_connection_params  s$   



r   c                 C   sR   t | }|si S i }|D ]}t||}|dr&t|}|r&||d< |||< q|S )a  
    Get all test servers from config file.

    Finds all sections with 'testing_allowed: true' and returns their
    connection parameters.

    Args:
        config_file: Optional explicit path to config file.
                    If None, searches default locations.

    Returns:
        Dict mapping section names to connection parameter dicts.
        Each dict contains: url, username, password, features, etc.
    testing_allowed_raw_config)r'   r    r   r   )r;   r<   r   r   r   r   r   r   r   r   2  s   

r   )r   N)r   )F)TNNFTNr   )r\   r)   r6   r%   rO   r   typingr   r   r    r'   rH   rd   	frozensetrx   r   rN   rR   r   r~   r   r|   rT   r   r   r   r   r   r   r   r   r   r   r   <module>   s    
	
1

0$"
[*
",-&
'