U
    d/e                     @   s  d Z 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ZddlZddddddgZ	e
eZejeejd	d
dZddejejef eddddZdd Zejejejef ejdddZejdddddZejejejedf ejej dddZejejedf ejej dddZddejejedf ejejedf ejdddZeddeeje edddZdS )z3Generic re-useable self-contained helper functions.    Nattachmkdirsmapping_itemspromote_pathlikepromote_pathlike_directorydeprecate_positional_args)objectnamereturnc                    s    fdd}|S )a  Return a decorator doing ``setattr(object, name)`` with its argument.

    >>> spam = type('Spam', (object,), {})()  # doctest: +NO_EXE

    >>> @attach(spam, 'eggs')
    ... def func():
    ...     pass

    >>> spam.eggs  # doctest: +ELLIPSIS
    <function func at 0x...>
    c                    s   t  |  | S )N)setattrfuncr	   r    3/tmp/pip-unpacked-wheel-n8ok7rre/graphviz/_tools.py	decorator#   s    zattach.<locals>.decoratorr   )r   r	   r   r   r   r   r      s    i  )mode)filenamer   r
   c                C   s4   t j| }|sdS td| t j||dd dS )zPRecursively create directories up to the path of ``filename``
        as needed.Nzos.makedirs(%r)T)r   exist_ok)ospathdirnamelogdebugmakedirs)r   r   r   r   r   r   r   *   s
    c                 C   s(   t |  }t| tkr$t t|}|S )ay  Return an iterator over the ``mapping`` items,
        sort if it's a plain dict.

    >>> list(mapping_items({'spam': 0, 'ham': 1, 'eggs': 2}))  # doctest: +NO_EXE
    [('eggs', 2), ('ham', 1), ('spam', 0)]

    >>> from collections import OrderedDict
    >>> list(mapping_items(OrderedDict(enumerate(['spam', 'ham', 'eggs']))))
    [(0, 'spam'), (1, 'ham'), (2, 'eggs')]
    )iteritemstypedictsorted)mappingresultr   r   r   r   4   s    )filepathr
   c                 C   s   dS )z(Return path object for path-like-object.Nr   r"   r   r   r   r   E   s    c                 C   s   dS )zReturn None for None.Nr   r#   r   r   r   r   J   s    c                 C   s   dS )z9Return path object or ``None`` depending on ``filepath``.Nr   r#   r   r   r   r   O   s    c                 C   s   | dk	rt | S dS )zReturn path-like object ``filepath`` promoted into a path object.

    See also:
        https://docs.python.org/3/glossary.html#term-path-like-object
    N)pathlibPathr#   r   r   r   r   U   s    )default)	directoryr&   r
   c                C   s   t | dk	r| n|ptjS )zReturn path-like object ``directory`` promoted into a path object (default to ``os.curdir``).

    See also:
        https://docs.python.org/3/glossary.html#term-path-like-object
    N)r$   r%   r   curdir)r'   r&   r   r   r   r   _   s       )category
stacklevel)supported_numberr*   r+   c                    sT   dkst d dkr*dd }|S t ts8t d7  fdd}|S )	a  Mark supported_number of positional arguments as the maximum.

    Args:
        supported_number: Number of positional arguments
            for which no warning is raised.
        category: Type of Warning to raise
            or None to return a nulldecorator
            returning the undecorated function.
        stacklevel: See :func:`warning.warn`.

    Returns:
        Return a decorator raising a category warning
            on more than supported_number positional args.

    See also:
        https://docs.python.org/3/library/exceptions.html#FutureWarning
        https://docs.python.org/3/library/exceptions.html#DeprecationWarning
        https://docs.python.org/3/library/exceptions.html#PendingDeprecationWarning
    r   zsupported_number at least one: Nc                 S   s   | S )z Return the undecorated function.r   r   r   r   r   nulldecorator   s    z0deprecate_positional_args.<locals>.nulldecoratorr)   c                    s\   t }dd |j D  tdjj d   t	 fdd}|S )Nc                 S   s"   g | ]\}}|j tjjkr|qS r   )kindinspect	ParameterPOSITIONAL_OR_KEYWORD).0r	   paramr   r   r   
<listcomp>   s    z@deprecate_positional_args.<locals>.decorator.<locals>.<listcomp>z$deprecate positional args: %s.%s(%r)c            	   
      s   t | krt | }t|}t|}t|}|s:tjd}|d\}}}t	rb|rbtd
dd | D }tjdj d dt| d	| d
	d | |S )N_Z_legacyz, c                 s   s    | ]\}}| d |V  qdS )=Nr   )r2   r	   valuer   r   r   	<genexpr>   s   zPdeprecate_positional_args.<locals>.decorator.<locals>.wrapper.<locals>.<genexpr>zThe signature of z will be reduced to z positional args z: pass z as keyword arg(s))r+   r*   )lenzip	itertoolsislicer   AssertionError__name__lstrip	partitionsetjoinr   warningswarnlist)	argskwargsZ	call_args	supported
deprecated	func_nameseprestwanted)argnamesr*   r   r+   r,   r   r   wrapper   s"    

&z=deprecate_positional_args.<locals>.decorator.<locals>.wrapper)
r/   	signature
parametersr   r   r   
__module____qualname__	functoolswraps)r   rP   rO   r*   r+   r,   )rN   r   r   r      s    
 
z,deprecate_positional_args.<locals>.decorator)r=   
issubclassWarning)r,   r*   r+   r-   r   r   rV   r   r   k   s     )__doc__rT   r/   r;   loggingr   r$   typingrC   __all__	getLoggerr>   r   AnystrCallabler   UnionPathLikeintr   r   overloadr%   r   Optionalr   PendingDeprecationWarningTyperX   r   r   r   r   r   <module>   sT   
$
 

