B
    id.                 @   s(  d dl Z 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l
mZmZmZmZmZmZmZmZ ddlmZmZ ddlmZ eedf ZeeZee ee d	d
dZG dd dZd.eeee ee dddZe	eee eeee ee f  dddZ d/eeeee!ee eee! eef dddZ"d0eeeee eee! ef dddZ#eeeee f  e!eeee f dddZ$eee d d!d"Z%d1ee!e!ed$d%d&Z&d2ee eee  e!e!e!ee e!d(d)d*Z'd3ee eee  e!e!ee eeee f d+d,d-Z(dS )4    N)OrderedDict)contextmanager)IODictIterableIteratorMappingOptionalTupleUnion   )Bindingparse_stream)parse_variableszos.PathLike[str])mappingsreturnc             c   s.   x(| D ] }|j r td|jj |V  qW d S )Nz;Python-dotenv could not parse statement starting at line %s)errorloggerwarningoriginalline)r   mapping r   //tmp/pip-unpacked-wheel-mbm0dzz5/dotenv/main.pywith_warn_for_invalid_lines   s    

r   c            	   @   s   e Zd Zdee eee  eee eeddddZe	e
ee  ddd	Zeeee f dd
dZe
eeee f  dddZedddZeee dddZdS )DotEnvNFT)dotenv_pathstreamverboseencodinginterpolateoverrider   c             C   s.   || _ || _d | _|| _|| _|| _|| _d S )N)r   r   _dictr   r   r    r!   )selfr   r   r   r   r    r!   r   r   r   __init__#   s    	zDotEnv.__init__)r   c          	   c   st   | j r8tj| j r8t| j | jd}|V  W d Q R X n8| jd k	rL| jV  n$| jrdt	d| j p`d t
dV  d S )N)r   z3Python-dotenv could not find configuration file %s.z.env )r   ospathisfileopenr   r   r   r   infoioStringIO)r#   r   r   r   r   _get_stream4   s    

zDotEnv._get_streamc             C   s@   | j r| j S |  }| jr0tt|| jd| _ n
t|| _ | j S )zReturn dotenv as dict)r!   )r"   parser    r   resolve_variablesr!   )r#   Z
raw_valuesr   r   r   dictC   s    
zDotEnv.dictc          	   c   sF   |   4}x,tt|D ]}|jd k	r|j|jfV  qW W d Q R X d S )N)r-   r   r   keyvalue)r#   r   r   r   r   r   r.   Q   s    

zDotEnv.parsec             C   sN   |   sdS x<|    D ],\}}|tjkr4| js4q|dk	r|tj|< qW dS )zI
        Load the current dotenv as system environment variable.
        FNT)r0   itemsr&   environr!   )r#   kvr   r   r   set_as_environment_variablesW   s    z#DotEnv.set_as_environment_variables)r1   r   c             C   s2   |   }||kr|| S | jr.td|| j dS )z	
        zKey %s not found in %s.N)r0   r   r   r   r   )r#   r1   datar   r   r   getf   s    z
DotEnv.get)NFNTT)__name__
__module____qualname__r	   StrPathr   strboolr$   r   r   r-   r   r0   r
   r.   r7   r9   r   r   r   r   r   "   s       	r   utf-8)r   
key_to_getr   r   c             C   s   t | d|d|S )z
    Get the value of a given key from the given .env.

    Returns `None` if the key isn't found or doesn't have a value.
    T)r   r   )r   r9   )r   rA   r   r   r   r   get_keyt   s    
rB   )r'   r   r   c          
   c   s   t j| s0t| d|d}|d W d Q R X tjd|ddP}y&t| |d}||fV  W d Q R X W n" tk
r   t |j	  Y nX W d Q R X t
|j	|  d S )Nw)moder   r%   F)rD   r   delete)r   )r&   r'   r(   r)   writetempfileNamedTemporaryFileBaseExceptionunlinknameshutilmove)r'   r   sourcedestr   r   r   rewrite   s    rP   alwaysF)r   
key_to_setvalue_to_set
quote_modeexportr   r   c          	   C   s  |dkrt d| |dkp.|dko.|  }|rHd|dd}n|}|rdd| d	| d
}n| d	| d
}t| |d|\}	}
d}d}xLtt|	D ]<}|j|kr|
| d}q|
|j	j
 |j	j
d
 }qW |s|r|
d
 |
| W dQ R X d||fS )z
    Adds or Updates a key/value to the given .env

    If the .env path given doesn't exist, fails instead of risking creating
    an orphan .env somewhere in the filesystem
    )rQ   autoneverzUnknown quote_mode: rQ   rV   z'{}''z\'zexport =
)r   FTN)
ValueErrorisalnumformatreplacerP   r   r   r1   rF   r   stringendswith)r   rR   rS   rT   rU   r   quoteZ	value_outZline_outrN   rO   ZreplacedZmissing_newliner   r   r   r   set_key   s0    


rb   )r   key_to_unsetrT   r   r   c          	   C   s   t j| s td|  d|fS d}t| |d>\}}x2tt|D ]"}|j|krXd}qD|	|j
j qDW W dQ R X |std||  d|fS ||fS )z
    Removes a given key from the given `.env` file.

    If the .env path given doesn't exist, fails.
    If the given key doesn't exist in the .env, fails.
    z(Can't delete from %s - it doesn't exist.NF)r   Tz/Key %s not removed from %s - key doesn't exist.)r&   r'   existsr   r   rP   r   r   r1   rF   r   r_   )r   rc   rT   r   removedrN   rO   r   r   r   r   	unset_key   s    
rf   )valuesr!   r   c                s   i }x|| D ]t\}}|d kr d }nVt |}i  |rH tj  | n |  tj d fdd|D }|||< q
W |S )Nr%   c             3   s   | ]}|  V  qd S )N)resolve).0Zatom)envr   r   	<genexpr>   s    z$resolve_variables.<locals>.<genexpr>)r   updater&   r4   join)rg   r!   Z
new_valuesrK   r2   resultZatomsr   )rj   r   r/      s    
r/   )r'   r   c             c   sx   t j| stdt j| r,t j| } d}t j| }x6||krr|V  t jt j|t jj}|| }}q>W dS )zL
    Yield directories starting from the given directory up to the root
    zStarting path not foundN)	r&   r'   rd   IOErrorr(   dirnameabspathrm   pardir)r'   Zlast_dirZcurrent_dir
parent_dirr   r   r   _walk_to_root   s    
rt   .env)filenameraise_error_if_not_foundusecwdr   c       
      C   s   dd }|s| st tddr(t }nNt }t}x$|jj|krX|jdk	sPt	|j}q6W |jj}tj
tj
|}x.t|D ]"}tj
|| }	tj
|	r|	S qW |rtddS )z
    Search in increasingly higher folders for the given file

    Returns path to the file if found, or an empty string otherwise
    c              S   s   t ddddgd} t| d S )z> Decide whether this is running in a REPL or IPython notebook __main__N__file__)fromlist)
__import__hasattr)mainr   r   r   _is_interactive  s    z$find_dotenv.<locals>._is_interactivefrozenFNzFile not foundr%   )getattrsysr&   getcwd	_getframerz   f_codeco_filenamef_backAssertionErrorr'   rp   rq   rt   rm   r(   ro   )
rv   rw   rx   r   r'   frameZcurrent_fileZframe_filenamerp   
check_pathr   r   r   find_dotenv  s"    

r   T)r   r   r   r!   r    r   r   c             C   s2   | dkr|dkrt  } t| |||||d}| S )a  Parse a .env file and then load all the variables found as environment variables.

    Parameters:
        dotenv_path: Absolute or relative path to .env file.
        stream: Text stream (such as `io.StringIO`) with .env content, used if
            `dotenv_path` is `None`.
        verbose: Whether to output a warning the .env file is missing.
        override: Whether to override the system environment variables with the variables
            from the `.env` file.
        encoding: Encoding to be used to read the file.
    Returns:
        Bool: True if at least one environment variable is set else False

    If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the
    .env file.
    N)r   r   r   r    r!   r   )r   r   r7   )r   r   r   r!   r    r   Zdotenvr   r   r   load_dotenv7  s    r   )r   r   r   r    r   r   c             C   s.   | dkr|dkrt  } t| |||d|d S )a  
    Parse a .env file and return its content as a dict.

    The returned dict will have `None` values for keys without values in the .env file.
    For example, `foo=bar` results in `{"foo": "bar"}` whereas `foo` alone results in
    `{"foo": None}`

    Parameters:
        dotenv_path: Absolute or relative path to the .env file.
        stream: `StringIO` object with .env content, used if `dotenv_path` is `None`.
        verbose: Whether to output a warning if the .env file is missing.
        encoding: Encoding to be used to read the file.

    If both `dotenv_path` and `stream` are `None`, `find_dotenv()` is used to find the
    .env file.
    NT)r   r   r   r    r!   r   )r   r   r0   )r   r   r   r    r   r   r   r   dotenv_values]  s    r   )r@   )rQ   Fr@   )rQ   r@   )ru   FF)NNFFTr@   )NNFTr@   ))r+   loggingr&   rL   r   rG   collectionsr   
contextlibr   typingr   r   r   r   r   r	   r
   r   parserr   r   	variablesr   r>   r=   	getLoggerr:   r   r   r   rB   rP   r?   rb   rf   r/   rt   r   r   r   r   r   r   r   <module>   s`   (

U	$  -   &          