a
    6iA                     @   sj   d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZ dd	lmZmZ G d
d dZdS )z+Load configuration settings for protonfixes    N)ConfigParser)is_dataclass)Path)Any)Callable   )logLogLevelc                   @   s   e Zd ZU dZedZejed< e	e
e
dddZeejfe
eddd	d
ZeddddZdeddddZeedddZeedddZdS )
ConfigBasea1  Base class for configuration objects.

    This reflects a given config file and populates the object with it's values.
    It also injects attributes from the sub classes, this isn't compatible with static type checking though.
    You can define the attributes accordingly to satisfy type checkers.
    z(((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))_ConfigBase__CAMEL_CASE_PATTERN)inputreturnc                 C   s   | j d| S )zConverts CamelCase to snake_case.

        Args:
            input (str): The string to convert.

        Returns:
            str: The converted string.

        z_\1)r   sublower)clsr    r   d/home/james-whalen/.local/share/Steam/compatibilitytools.d/GE-Proton10-32/protonfixes/config_base.py
snake_case   s    zConfigBase.snake_caseN)messagelevelr   c                 C   s   t  d|  | d S )Nz
[CONFIG]: )r   )r   r   r   r   r   Z__log(   s    zConfigBase.__log)pathr   c                 C   sP   |sJ |  r| | n0| s8|   | | ntd|  ddS )aI  Initialize the instance from a given config file.

        Defaults will be used if the file doesn't exist.
        The file will also be created in this case.

        Args:
            path (Path): The reflected config file's path.

        Raises:
            IsADirectoryError: If the path exists, but isn't a file.

        zGiven path "z" exists, but is not a file.N)is_fileparse_config_fileexistsinit_sectionswrite_config_fileIsADirectoryErrorabsolute)selfr   r   r   r   __init__,   s    zConfigBase.__init__F)forcer   c                 C   sl   | j j D ]Z\}}|dr|dr*qt|s4q|d}| |}t| |rX|sXqt	| ||  qdS )aJ  Find sub-classes and initialize them as attributes.

        Sub-classes are initialized and injected as attributes.
        Example: `MainSection` will be injected as `main` to the config (this) object.

        Args:
            force (bool, optional): Force initialization? This results in a reset. Defaults to False.

        ZSection_N)
	__class____dict__itemsendswith
startswithr   removesuffixr   hasattrsetattr)r   r    member_namemembersection_namer   r   r   r   D   s    


zConfigBase.init_sections)filer   c              
      s    d | sdS zt }|| j D ]v\}}||sFq2||  tttgt	f d fdd}|j D ].\}}t
|j}||}	|	|}
t|||
 qxq2W nB ty } z*d| d| dtj W Y d	}~dS d	}~0 0 dS )
a  Parse a config file.

        This resets the data in the sections, regardless if the file exists or is loaded.

        Args:
            file (Path): The reflected config file's path.

        Returns:
            bool: True, if the config file was successfully loaded.

        TF)	type_namer   c                    sV    j  j j fdd fdd jd| d }|sR j}d|  dtj |S )Nc                    s   t  | dS N r   getoptionparser_itemsr   r   <lambda>       zKConfigBase.parse_config_file.<locals>._get_parse_function.<locals>.<lambda>c                    s   t  | dS r/   r1   r3   r5   r   r   r7      r8   )intfloatboolr   	PosixPathstrzUnknown type "z", falling back to "str".)getintgetfloat
getbooleanr2   _ConfigBase__logr	   WARN)r.   valuer6   r   r   r   _get_parse_function   s     


z9ConfigBase.parse_config_file.<locals>._get_parse_functionzFailed to parse config file "". Exception: ""N)r   r   r   readr#   r$   has_sectionr=   r   r   type__name__r)   	ExceptionrA   r	   CRIT)r   r-   parserr,   sectionrE   option_nameoption_itemr.   funcrC   exr   rD   r   r   `   s.    


 
zConfigBase.parse_config_filec           	   
   C   s   |j  sdS zt }| j D ]B\}}||s<|| |j D ]\}}|||t| qFq |j	dd}|
| W d   n1 s0    Y  W nB ty } z*| d| d| dtj W Y d}~dS d}~0 0 dS )	zWrite the current config to a file.

        Args:
            file (Path): The file path to write to.

        Returns:
            bool: True, if the file was successfully written.

        Fw)modeNzFailed to create config file "rF   rG   T)parentis_dirr   r#   r$   rI   add_sectionsetr=   openwriterL   rA   r	   rM   )	r   r-   rN   r,   Zsection_itemrP   rQ   streamrS   r   r   r   r      s$    



,zConfigBase.write_config_file)F)rK   
__module____qualname____doc__recompiler   Pattern__annotations__classmethodr=   r   staticmethodr	   INFOrA   r   r   r;   r   r   r   r   r   r   r   r
      s   
@r
   )r_   r`   configparserr   dataclassesr   pathlibr   typingr   collections.abcr   loggerr   r	   r
   r   r   r   r   <module>   s   