
    F2jS                        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 	 d'dZd(dZ	d)dZ
d	ed
efdZd Z eg d          Z	 	 	 	 	 	 d*dededz  dedz  dedededz  ded
eeef         dz  fdZd
eeef         dz  fdZdedz  dedz  d
eeef         dz  fdZ	 d+dedz  dededz  d
eeef         dz  fdZdedz  dedz  d
ee         fdZdedz  d
ee         fdZ G d d          Zd ed!ed
eeef         fd"Zd#eeef         d
eeef         dz  fd$Z	 d+dedz  dedz  d
eeeef                  fd%Z	 d+dedz  d
eeeeef         f         fd&ZdS ),    Nfnmatch)Anydefaultc                     dk    r fd D             S t                                        t          d                    rd          v rog }|st                      }|                                         d         D ]7}||vr1||vr-t           ||          D ]}||vr|                    |           8|S                      di                               dd          rg S gS fd D             }t                      }|D ]j}t          |                              t          d                    r$|                    t           |                     U|                    |           k|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                 L    g | ] }|                              d d          |!S )disableF)get).0xconfigs     U/home/thesage/.hermes/hermes-agent/venv/lib/python3.11/site-packages/caldav/config.py
<listcomp>z)expand_config_section.<locals>.<listcomp>    s0    IIIay%)H)HIIII    z[*?containssectionr
   Fc                 4    g | ]}t          |          |S  r   )r   r   r   s     r   r   z)expand_config_section.<locals>.<listcomp>8   s(    BBBqga.A.ABBBBr   )set
isdisjointaddexpand_config_sectionappendr   update)r   r   	blacklistresults
subsectionrecursivesubsectionmatching_sectionsss   ``      r   r   r      s    #~~IIII6IIII 7||s5zz** ((G "EE	MM'"""$Woj9 @ @
W,,91L1L/DVZYb/c/c @ @+.g==#NN+>???N zz)R((,,Y>> 	 9BBBBFBBBeeG  q66SZZ(( 	NN0;;<<<< KKNNNNNr   c                     || v r'd| |         v rt          | | |         d                   }ni }|| v r|                    | |                    |S )Ninherits)config_sectionr   )r   r   rets      r   r$   r$   C   s`    &Z6'?::VVG_Z%@AA&

6'?###Jr   Fc                    | sQt           j                            dd           d}| d| d| d| ddd	fD ]}t          |          }|r|c S i S 	 	 t	          | d
          5 }t          j        |          cd d d            S # 1 swxY w Y   n# t
          j        j        $ r 	 dd l	}	 t	          | d
          5 }|                    ||j
                  cd d d            cY S # 1 swxY w Y   n9# |j        j        |j        j        f$ r}t          d|  d|           |d }~ww xY wn"# t           $ r t          d|  d          d w xY wY nw xY wn4# t"          $ r t%          j        d|  d           i cY S t          $ r  w xY wi S )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cfgr2   es          r   r,   r,   M   s    JNN63//:::,,,,,,,,,%%% '
 
	 
	K k**C 


		b$ .;y--. . . . . . . . . . . . . . . . .|+ 	 	 	eb$ C;#yydkBBC C C C C C C C C C C C C C C C C C C14;3JK e e e$%\B%\%\YZ%\%\]]cddeC
     V2VVV C C	"    3R333444			    Is   B &B:B BB BB E E(D--C3=C'C3$E%E 'C+	+C3.C+	/C32D-3D)D$$D))D-,E-EEE EE $F<Fvaluereturnc                 6   t          | t                    r/d}dt          j        dt          fd}t          j        |||           S t          | t
                    rd |                                 D             S t          | t                    r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\$\{([^}:]+)(?::-([^}]*))?\}matchrD   c                     |                      d          }|                      d          |                      d          nd}t          j                            ||          S )N       )groupr*   r+   r   )rF   var_namer   s      r   replacerz!expand_env_vars.<locals>.replacer   sI    {{1~~H(-A(Bekk!nnnG:>>(G444r   c                 4    i | ]\  }}|t          |          S r   expand_env_varsr   kvs      r   
<dictcomp>z#expand_env_vars.<locals>.<dictcomp>   s&    @@@$!Q?1%%@@@r   c                 ,    g | ]}t          |          S r   rO   )r   rS   s     r   r   z#expand_env_vars.<locals>.<listcomp>   s     222q""222r   )
isinstancestrreMatchsubdictitemslist)rC   patternrM   s      r   rP   rP   }   s    & % 31	5BH 	5 	5 	5 	5 	5
 vgx///	E4	 	  3@@%++--@@@@	E4	 	  322E2222Lr   c                 &   ddl }| dS t          | t                    rC| }|                    d          r|t	          d          d         }t          |j        |          S t          | t                    rd| v r| d         }t          |t                    rz|                    d          r|t	          d          d         }t          j	        t          |j        |                    }| 
                                D ]\  }}|dk    r|||<   |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_hintsrV   rW   
startswithlengetattrcompatibility_hintsr[   copydeepcopyr\   )featurescaldavfeature_name	base_namebase_featureskeyrC   s          r   resolve_featuresrn      s8    &%%%t(C   A""#9:: 	G',B(C(C(E(EFLv1<@@@(D!! 	!f&8&8V$	i%% 	!##$:;; E%c*@&A&A&C&CD	 M'&2Li*X*XYYM&nn.. / /
U&==).M#&  Or   )urlproxyusernamepasswordtimeoutheaders	huge_treessl_verify_certssl_certauth	auth_typerh   enable_rfc6764require_tlsprotocolTcheck_config_filer@   r$   
testconfigenvironmentnameexplicit_paramsc                    |rJd |                                 D             }|                    d          s|                    d          r|S |rB|st          j                            d          }|st          j                            d          }|s!|rJt          j                            d          r+t	          |||          }||S t          j        d           dS |rt                      }|r|S | rt          ||          }|r|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                 ,    i | ]\  }}|t           v ||S r   )CONNKEYSrQ   s      r   rT   z)get_connection_params.<locals>.<dictcomp>  s#    QQQ11==q!===r   ro   rh   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.)	r\   r   r*   r+   _get_test_server_configr;   info_get_env_config_get_file_config)	r}   r@   r$   r~   r   r   r   conn_paramsconns	            r   get_connection_paramsr      sT   \  QQ(=(=(?(?QQQ??5!! 	[__Z%@%@ 	
   E 	?*..)=>>K 	EZ^^,CDDN  
k 
bjnn5T&U&U 
&t[+FFK 	X	
 	
 	
 t  %'' 	  &{NCC 	4r   c                     i } t           j        D ]w}|                    d          r`|                    d          sK|dd                                         }|dk    rd}n|dk    rd}|t          v rt           j        |         | |<   x| r| ndS )	zBExtract connection parameters from CALDAV_* environment variables.CALDAV_CALDAV_CONFIG   Npassrr   userrq   )r*   r+   rb   lowerr   )confenv_keyrm   s      r   r   r   3  s    D: 	0 	0i(( 	01C1CO1T1T 	0!""+##%%Cf}}  hJw/S	!44T!r   	file_pathsection_namec                 n    |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   rA   section_datas       r   r   r   C  sF     ! 
i
 
 C t!#|44L,\:::r   c                    |r!| t           j                            d          } t          | |          D ]}|j        }	 |                                 n2# t          $ r%}t          j        d|j	        |           Y d}~Id}~ww xY wt          j
        d|j	        |j                   t          ||          c S t          j
        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	Exceptionr;   warningr   r   ro   _test_server_to_params)r   r   r@   serverwas_already_startedrB   s         r   r   r   P  s    0  @t|z~~>??'k:: C C$o	LLNNNN 	 	 	O@&+qQQQHHHH	 	2FKLLL%f.ABBBBBL	\   4s   A
BA==Bc                      	 ddl m} t           |                                                      }n# t          $ r t          |          }Y nw xY w  f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                     g | ]J}                                 |j                                         |j                                         fv H|KS r   )r   r   server_type)r   r!   r   s     r   r   z)_collect_test_servers.<locals>.<listcomp>  sH    aaa!&,,..!-J]J]J_J_9`)`)`1)`)`)`r   )tests.test_servers.registryr   r]   enabled_serversr9   _get_pip_test_servers)r   r@   r   serverss   `   r   r   r   |  s    5<<<<<<!,,.."@"@"B"BCC 5 5 5'445 aaaagaaaNs   /3 AAc                    ddl m}m} g }	 ddl}|                     |                       n# t
          $ r Y nw xY w	 ddl}|                     |                       n# t
          $ r Y nw xY wt          |                                           D ](\  }}|                    t          ||                     )t          |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                     | j         S N)priority)r!   s    r   <lambda>z'_get_pip_test_servers.<locals>.<lambda>  s     r   )rm   )caldav.testingr   r   xandikosr   r9   radicaleget_all_test_serversr\   _ConfiguredServersorted)r@   r   r   r   r   r   r   paramss           r   r   r     s    >=======G~~''((((   ~~''((((    !5[ A A G G I I @ @f(v>>????'334444s   !. 
;;!A! !
A.-A.c                       e Zd ZdZdZdedeeef         ddfdZe	de
fd            Ze	defd	            Ze	dedz  fd
            Ze	dedz  fd            Ze	defd            ZddZddZdef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.
    externalr   r   rD   Nc                 0    || _         || _        d| _        d S NF)r   _paramsr   )selfr   r   s      r   __init__z_ConfiguredServer.__init__  s    	r   c                 R    t          | j                            dd                    S )Nr      )intr   r   r   s    r   r   z_ConfiguredServer.priority  s"    4<##J33444r   c                 8    | j                             dd          S )Nro   rJ   r   r   r   s    r   ro   z_ConfiguredServer.url  s    |r***r   c                 6    | j                             d          S )Nrq   r   r   s    r   rq   z_ConfiguredServer.username      |
+++r   c                 6    | j                             d          S )Nrr   r   r   s    r   rr   z_ConfiguredServer.password  r   r   c                 6    | j                             d          S )Nrh   r   r   s    r   rh   z_ConfiguredServer.features  r   r   c                     d| _         d S )NTr   r   s    r   r   z_ConfiguredServer.start  s    r   c                     d| _         d S r   r   r   s    r   stopz_ConfiguredServer.stop  s    r   c                 *    t          | j                  S r   )boolro   r   s    r   is_accessiblez_ConfiguredServer.is_accessible  s    DH~~r   )rD   N)__name__
__module____qualname____doc__r   rW   r[   r   r   propertyr   r   ro   rq   rr   rh   r   r   r   r   r   r   r   r   r     sd         KS $sCx. T    
 5# 5 5 5 X5 +S + + + X+ ,#* , , , X, ,#* , , , X, ,# , , , X,      t      r   r   r   r   c                     | j         | j        d}| j        r
| j        |d<   | j        r
| j        |d<   | j        r
| j        |d<   |s	d| fd|d<   |S )zFBuild a ``get_davclient``-compatible params dict from a server object.)ro   _server_namerq   rr   rh   Nc                 *    |                                 S r   )r   )_clientr!   s     r   r   z(_test_server_to_params.<locals>.<lambda>  s    QVVXX r   	_teardown)ro   r   rq   rr   rh   )r   r   r   s      r   r   r     s     z F  -#_z -#_z -#_z  F-1VEEE{Mr   r   c                 :   i }| D ]~}|                     d          rA| |         }|6|dd         }|dk    rd}n|dk    rd}|t          v rt          |          ||<   X|dk    r | |         rt          | |                   |d<   |                    d	          r|n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   rr   r   rq   rh   ro   )rb   r   rP   rn   r   )r   r   rR   rC   rm   s        r   r   r     s     #%K H H<<	"" 	H OE e&==$CCF]]$C(??'6u'='=K$*__a_&6|A&G&GK
#%//%00:;;d:r   c                    |sd}t          |           }|sg S t          ||          }g }|D ]]}t          ||          }t          |          }|r:dD ]"}|                    |          r||         ||<   #|                    |           ^|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   rA   sectionsresultr!   r   r   rR   s	            r   get_all_file_connection_paramsr     s    "  ! 
k
"
"C 	$S,77H#%F " "%c1--2<@@ 	"6 0 0##A&& 0 ,QF1IMM&!!!Mr   c                     t          |           }|si S i }|D ]B}t          ||          }|                    d          rt          |          }|r
||d<   |||<   C|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@   rA   r   r   r   r   s         r   r   r   2  s    " k
"
"C 	(*F 3 3%c<88-.. 	3;LIIK 3 .:M*'2|$Mr   )r   N)r   )F)TNNFTNr   )rf   r.   r;   r*   rX   r   typingr   r   r$   r,   rP   rn   	frozensetr   r   rW   r[   r   r   r   r   r]   r   r   r   r   r   r   r   r   r   r   <module>r      s      				 				            . . . .b   - - - -`!3 !3 ! ! ! !H  D 9   , #"!%X XXtX $JX 	X
 X *X X 
#s(^dX X X Xv"c3h$. " " " " 
;d
 
;#* 
;cSVhZ^I^ 
; 
; 
; 
; DH) )
*)#')69Dj)	#s(^d) ) ) )Xd
 t S	    (5sTz 5d3i 5 5 5 5>* * * * * * * *Z3 T d3PS8n    &;DcN ;tCQTH~X\G\ ; ; ; ;>  $# #t#*# 
$sCx.# # # #N #   t 	#tCH~
           r   