
    i?                        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eef         d
eeef         dz  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     H/root/projects/butler/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          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 


		eb$ .;y--. . . . . . . . . . . . . . . . .|+ 	e 	e 	e
e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
  e e e !c!c!c!cdddeC C	e    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   1  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   A  sF     ! 
i
 
 C t!#|44L,\:::r   c                    |r!| t           j                            d          } t          |          }|r| Vt	          | t
                    sAt          |t          |                     }|                    d          rt          |          S | R|D ]O}t          ||          }|                    d          r(t          j
        d|            t          |          c S PdS )a  
    Get connection parameters for test server.

    Priority:
    1. Config file sections with 'testing_allowed: true'

    Args:
        name: Specific config section or test server name/index to use.
              Can be a config section name, test server name, or numeric index.
        environment: Whether to check environment variables for server selection.
        config_file: Explicit config file path to check.

    Returns:
        Connection parameters dict, or None if no test server configured.
    NPYTHON_CALDAV_TEST_SERVER_NAMEtesting_allowedz'Using test server from config section: )r*   r+   r   r,   rV   intr$   rW   r   r;   r   )r   r   r@   rA   r   r   s         r   r   r   N  s   &  @t|z~~>?? k
"
"C
 KJtS$9$9)#s4yy99L 122 G8FFF < # K K-c<@@##$566 KL!Y<!Y!YZZZ<\JJJJJK
 4r   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 )
z9Extract connection parameters from a config section dict.caldav_Nr   r   rr   r   rq   rh   ro   )rb   r   rP   rn   r   )r   r   rR   rC   rm   s        r   r   r   y  s    "$K H H<<	"" 	H OE e&==$CCF]]$C(??'6u'='=K$*__a_&6|A&G&GK
#%//%00:;;d:r   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.
    r   _raw_config)r,   r$   r   r   )r@   rA   resultr   r   r   s         r   get_all_test_serversr     s    " k
"
"C 	(*F 3 3%c<88-.. 	3;LIIK 3 .:M*'2|$Mr   )r   N)r   )F)TNNFTN)N)rf   r.   r;   r*   rX   r   typingr   r   r$   r,   rP   rn   	frozensetr   boolrW   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( ( ( (V;DcN ;tCQTH~X\G\ ; ; ; ;. #   t 	#tCH~
           r   