a
    $af                      @   sN   d Z ddlZddlZddlZddlmZmZ edejZ	G dd de
ZdS )zr

ConfigSet: a special dict

The values put in :py:class:`ConfigSet` must be serializable (dicts, lists, strings)
    N)LogsUtilsz^(#)*?([^#=]*?)\ =\ (.*?)$c                   @   s   e Zd ZdZdZd6ddZdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 ZdS )7	ConfigSeta  
	A copy-on-write dict with human-readable serialized format. The serialization format
	is human-readable (python-like) and performed by using eval() and repr().
	For high performance prefer pickle. Do not store functions as they are not serializable.

	The values can be accessed by attributes or by keys::

		from waflib.ConfigSet import ConfigSet
		env = ConfigSet()
		env.FOO = 'test'
		env['FOO'] = 'test'
	)tableparentNc                 C   s   i | _ |r| | d S N)r   load)selffilename r   k/home/jack/SDK/ZBT-AX3000-OpenWrt-21.02/build_dir/hostpkg/samba-4.14.12/third_party/waf/waflib/ConfigSet.py__init__   s    zConfigSet.__init__c                 C   s6   || j v rdS z| j|W S  ty0   Y dS 0 dS )zJ
		Enables the *in* syntax::

			if 'foo' in env:
				print(env['foo'])
		TFN)r   r   __contains__AttributeErrorr	   keyr   r   r   r   (   s    
zConfigSet.__contains__c                 C   s@   t  }| }|r,||j  t|dd}q
t|}|  |S )zDict interfacer   N)setupdater   keysgetattrlistsort)r	   r   curr   r   r   r   6   s    zConfigSet.keysc                 C   s   t |  S r   )iterr   r	   r   r   r   __iter__A   s    zConfigSet.__iter__c                    s   d  fdd  D S )z=Text representation of the ConfigSet (for debugging purposes)
c                    s   g | ]}d |  |f qS )z%r %r)__getitem__).0xr   r   r   
<listcomp>F       z%ConfigSet.__str__.<locals>.<listcomp>)joinr   r   r   r   r   __str__D   s    zConfigSet.__str__c                 C   sB   z&| j |}|dur|W S | j} qW n ty<   g  Y S 0 dS )zx
		Dictionary interface: get value from key::

			def configure(conf):
				conf.env['foo'] = {}
				print(env['foo'])
		N)r   getr   r   )r	   r   r   r   r   r   r   H   s    zConfigSet.__getitem__c                 C   s   || j |< dS )z.
		Dictionary interface: set value from key
		N)r   r	   r   valuer   r   r   __setitem__Y   s    zConfigSet.__setitem__c                 C   s   g | |< dS )z5
		Dictionary interface: mark the value as missing
		Nr   r   r   r   r   __delitem___   s    zConfigSet.__delitem__c                 C   s"   || j v rt| |S | | S dS )z
		Attribute access provided for convenience. The following forms are equivalent::

			def configure(conf):
				conf.env.value
				conf.env['value']
		N)	__slots__object__getattribute__r	   namer   r   r   __getattr__e   s    
zConfigSet.__getattr__c                 C   s&   || j v rt| || n|| |< dS )z
		Attribute access provided for convenience. The following forms are equivalent::

			def configure(conf):
				conf.env.value = x
				env['value'] = x
		N)r)   r*   __setattr__)r	   r-   r&   r   r   r   r/   r   s    
zConfigSet.__setattr__c                 C   s"   || j v rt| | n| |= dS )z
		Attribute access provided for convenience. The following forms are equivalent::

			def configure(conf):
				del env.value
				del env['value']
		N)r)   r*   __delattr__r,   r   r   r   r0      s    
zConfigSet.__delattr__c                 C   s   t  }| |_|S )a  
		Returns a new ConfigSet deriving from self. The copy returned
		will be a shallow copy::

			from waflib.ConfigSet import ConfigSet
			env = ConfigSet()
			env.append_value('CFLAGS', ['-O2'])
			child = env.derive()
			child.CFLAGS.append('test') # warning! this will modify 'env'
			child.CFLAGS = ['-O3'] # new list, ok
			child.append_value('CFLAGS', ['-O3']) # ok

		Use :py:func:`ConfigSet.detach` to detach the child from the parent.
		)r   r   )r	   Znewenvr   r   r   derive   s    zConfigSet.derivec                 C   sX   |   }zt| d W n ty(   Y n,0 | }|D ]}t|| ||< q6|| _| S )z
		Detaches this instance from its parent (if present)

		Modifying the parent :py:class:`ConfigSet` will not change the current object
		Modifying this :py:class:`ConfigSet` will not modify the parent one.
		r   )get_merged_dictdelattrr   r   copydeepcopyr   )r	   tblr   r   r   r   r   detach   s    zConfigSet.detachc                 C   s    | | }t |tr|S d|S )z
		Returns a value as a string. If the input is a list, the value returned is space-separated.

		:param key: key to use
		:type key: string
		 )
isinstancestrr"   )r	   r   sr   r   r   get_flat   s    
zConfigSet.get_flatc                 C   s   z| j | }W n` tyn   z| j| }W n ty@   g }Y n 0 t|trZ|dd }n|g}|| j |< Y n0 t|ts|g | j |< }|S )z
		Returns a list value for further modification.

		The list may be modified inplace and there is no need to do this afterwards::

			self.table[var] = value
		N)r   KeyErrorr   r   r9   r   r%   r   r   r    _get_list_value_for_modification   s    


z*ConfigSet._get_list_value_for_modificationc                 C   s(   t |tr|g}| |}|| dS )z
		Appends a value to the specified config key::

			def build(bld):
				bld.env.append_value('CFLAGS', ['-O2'])

		The value must be a list or a tuple
		N)r9   r:   r>   extend)r	   varvalcurrent_valuer   r   r   append_value   s    	

zConfigSet.append_valuec                 C   s(   t |tr|g}|| | | j|< dS )z
		Prepends a value to the specified item::

			def configure(conf):
				conf.env.prepend_value('CFLAGS', ['-O2'])

		The value must be a list or a tuple
		N)r9   r:   r>   r   )r	   r@   rA   r   r   r   prepend_value   s    	
zConfigSet.prepend_valuec                 C   s:   t |tr|g}| |}|D ]}||vr|| qdS )z
		Appends a value to the specified item only if it's not already present::

			def build(bld):
				bld.env.append_unique('CFLAGS', ['-O2', '-g'])

		The value must be a list or a tuple
		N)r9   r:   r>   append)r	   r@   rA   rB   r   r   r   r   append_unique   s    	

zConfigSet.append_uniquec                 C   sV   g }| }| d|j z
|j}W q ty6   Y q:Y q0 qi }|D ]}|| qB|S )zm
		Computes the merged dictionary from the fusion of self and all its parent

		:rtype: a ConfigSet object
		r   )insertr   r   r   r   )r	   Z
table_listenvmerged_tabler   r   r   r   r2     s    
zConfigSet.get_merged_dictc                 C   s   zt t j|d  W n ty,   Y n0 g }|  }t| }|  zt	}W n t
yl   t}Y n0 |D ]&}|dkrr|d|||| f  qrt|d| dS )z
		Serializes the :py:class:`ConfigSet` data to a file. See :py:meth:`ConfigSet.load` for reading such files.

		:param filename: file to use
		:type filename: string
		r   
undo_stackz%s = %s
 N)osmakedirspathsplitOSErrorr2   r   r   r   ascii	NameErrorreprrE   r   writefr"   )r	   r
   bufrI   r   funkr   r   r   store  s     
zConfigSet.storec                 C   sP   | j }tj|dd}t|D ]}|j}t|d||d< qtd| j  dS )z
		Restores contents from a file (current values are not cleared). Files are written using :py:meth:`ConfigSet.store`.

		:param filename: file to use
		:type filename: string
		r)m      zenv: %sN)	r   r   readfre_impfinditergroupevalr   debug)r	   r
   r6   coderZ   gr   r   r   r   3  s    zConfigSet.loadc                 C   s   | j | dS )z
		Dictionary interface: replace values with the ones from another dict

		:param d: object to use the value from
		:type d: dict-like object
		N)r   r   )r	   dr   r   r   r   A  s    zConfigSet.updatec                 C   sH   | j }| j   }| _ | D ]}t|| ||< q| j|g | _dS )a5  
		Stores the object state to provide transactionality semantics::

			env = ConfigSet()
			env.stash()
			try:
				env.append_value('CFLAGS', '-O3')
				call_some_method(env)
			finally:
				env.revert()

		The history is kept in a stack, and is lost during the serialization by :py:meth:`ConfigSet.store`
		N)r   r4   r   r5   rJ   )r	   Zorigr6   r   r   r   r   stashJ  s
    zConfigSet.stashc                 C   s   | j d dS )zC
		Commits transactional changes. See :py:meth:`ConfigSet.stash`
		N)rJ   popr   r   r   r   commit^  s    zConfigSet.commitc                 C   s   | j d| _dS )zL
		Reverts the object to a previous state. See :py:meth:`ConfigSet.stash`
		rg   N)rJ   rh   r   r   r   r   r   revertd  s    zConfigSet.revert)N)__name__
__module____qualname____doc__r)   r   r   r   r   r#   r   r'   r(   r.   r/   r0   r1   r7   r<   r>   rC   rD   rF   r2   rX   r   r   rf   ri   rj   r   r   r   r   r      s6   

	r   )rn   r4   rerL   waflibr   r   compileMr^   r*   r   r   r   r   r   <module>   s   