U
    :vh!                     @   sx  d Z ddlZddlZddlZddlmZ ddlmZmZ ddl	m
Z
mZmZmZ dZG dd deZd	d
 Zdd Zeeef edddZeeee
eeee
f  f eeef eeef eeef dddZdZdd ZeedddZdd ZedddZedddZeedf dd d!Zee dd"d#Zee dd$d%Z edd&d'Z!edd(d)Z"edd*d+Z#dS ),a  
Various utilities that could not be gathered logically in a specific module.

The contents of this module are internal to fpdf2, and not part of the public API.
They may change at any time without prior warning or any deprecation period,
in non-backward-compatible ways.
    N)Number)get_traced_memory
is_tracing)Iterable
NamedTupleTupleUnion   c                   @   s\   e Zd ZU dZeed< dZeed< dZeed< dZeed< e	e
eeeef dddZd	S )
Paddingr   toprightbottomleft)paddingc                 C   s   t |ttfrt||||S t|dkrFt|d |d |d |d S t|dkrpt|d |d |d |d S t|dkrt| S tdt| dS )zbReturn a 4-tuple of padding values from a single value or a 2, 3 or 4-tuple according to CSS rules   r            zBpadding shall be a number or a sequence of 2, 3 or 4 numbers, got N)
isinstanceintfloatr
   len
ValueErrorstr)clsr    r   -/tmp/pip-unpacked-wheel-dvf6lv8i/fpdf/util.pynew   s    zPadding.newN)__name__
__module____qualname__r   r   __annotations__r   r   r   classmethodr   r   r   tuplelistr   r   r   r   r   r
      s   
r
   c                 C   sV   t | }t |t |ks,td| d| | | | d} t | |ksRt| S )Nzplaceholder=z value=r   )r   AssertionErrorreplaceencode)bufferplaceholdervaluebuffer_sizer   r   r   buffer_subst+   s
    $r,   c                 C   sR   t | tr.| ddddddddS | d	d
ddddddS )z*Add a backslash character before , ( and )\z\\)z\)(z\(z\r   \s   \\   )s   \)   (s   \(   s   \r)r   r   r&   )sr   r   r   escape_parens3   s.    
      r6   )unitreturnc                 C   sT   t | trt| S | dkrdS | dkr*dS | dkr6dS | dkrBdS td	|  d
S )z
    Get how many pts are in a unit. (k)

    Args:
        unit (str, float, int): Any of "pt", "mm", "cm", "in", or a number.
    Returns:
        float: The number of points in that unit (assuming 72dpi)
    Raises:
        ValueError
    ptr   mmgjZ@cmgbX<@ing      R@zIncorrect unit: N)r   r   r   r   )r7   r   r   r   get_scale_factorD   s    
r=   )
to_convertold_unitnew_unitr8   c                    s8   t |t |  t| tr0t fdd| D S |   S )a,  
     Convert a number or sequence of numbers from one unit to another.

     If either unit is a number it will be treated as the number of points per unit.  So 72 would mean 1 inch.

     Args:
        to_convert (float, int, Iterable): The number / list of numbers, or points, to convert
        old_unit (str, float, int): A unit accepted by fpdf.FPDF or a number
        new_unit (str, float, int): A unit accepted by fpdf.FPDF or a number
    Returns:
        (float, tuple): to_convert converted from old_unit to new_unit or a tuple of the same
    c                 3   s   | ]}t |d  V  qdS )r   N)convert_unit).0iZunit_conversion_factorr   r   	<genexpr>p   s     zconvert_unit.<locals>.<genexpr>)r=   r   r   r#   )r>   r?   r@   r   rD   r   rA   ]   s    
rA   ))Mi  )ZCMi  )Di  )ZCDi  )Cd   )ZXCZ   )L2   )ZXL(   )X
   )ZIX	   )V   )ZIVr   )Ir   c                 C   s<   d}| dkr|S t D ]"\}}| |kr||7 }| |8 } qq|S )z#Convert an integer to Roman numeral N)ROMAN_NUMERAL_MAP)nresultZnumeralintegerr   r   r   	int2roman   s    rY   )rV   r8   c                 C   s8   | dkr(t t| d d t | d  S t| td S )zXConvert an integer to a letter value (A to Z for the first 26, then AA to ZZ, and so on)      r   A)int_to_lettersr   chrord)rV   r   r   r   r]      s     r]   c                 C   s   t t|  d S N)printget_mem_usage)prefixr   r   r   print_mem_usage   s    rd   )r8   c                 C   sD   t  }t }t }d}t r(dt  }| dd| d| d| S )NrT   zMalloc stats: z<40 z | Pillow: z | Process RSS: )gcZcollectget_process_rssget_pillow_allocated_memoryr   get_tracemalloc_traced_memory)rc   Z_collected_countZrssZpillowZmalloc_statsr   r   r   rb      s    
rb   c                  C   s   t  } | r| ddS dS )N.1f MiB<unavailable>)get_process_rss_as_mib)Z
rss_as_mibr   r   r   rg      s    rg   c               
   C   sx   t  } zTtd|  ddd6}t|  d t d d d W  5 Q R  W S Q R X W n tk
rr   Y dS X dS )	zInspired by psutil source code/proc/z/statmutf8encodingr   SC_PAGE_SIZE   N)osgetpidopenr   readlinesplitsysconfFileNotFoundError)pidZstatmr   r   r   rm      s    rm   c               	   C   s   d\} }t  }z,td| ddd}t|}W 5 Q R X W n tk
rX   | |f Y S X |D ]}| }|d |d  }}|d\}	}
t|	d	t|
d	 }	}
|
|	 }|d
kr|d d dd} q^|dkr^|d d dd}q^| |fS )N)rl   rl   rn   z/mapsro   rp   r   -r	   z[heap]rs   rj   rk   z[stack])rt   ru   rv   r$   rz   rx   r   )Zheap_size_in_mibZstack_size_in_mibr{   Z	maps_fileZ
maps_lineslinewordsZ
addr_rangepathZ
addr_startZaddr_endsizer   r   r    get_process_heap_and_stack_sizes   s$    r   c                  C   s   zddl m}  d\}}|    D ]J}|drLt| d dd}q$|dr$t| d dd}q$|d	 d	 d
d|d	 d	 d
dW S  tk
r   t	
d Y dS X dS )za
    Get PyMalloc stats from sys._debugmallocstats()
    From experiments, not very reliable
    r   )get_debugmallocstats)r|   r|   ZTotalr|   ,rT   z# bytes in allocated blocksrs   rj   z / rk   z>pymemtrace could not be imported - Run: pip install pymemtracerl   N)Zpymemtrace.debug_malloc_statsr   decode
splitlines
startswithr   rx   r&   ImportErrorwarningswarn)r   Z	allocatedtotalr~   r   r   r   &get_pymalloc_allocated_over_total_size   s    

&
r   c                     sd   z>ddl m} m  t fdd|  D }|d d ddW S  tk
r^   td Y d	S X d
S )z#From experiments, not very reliabler   )get_objects	getsizeofc                 3   s   | ]} |V  qd S r`   r   )rB   objr   r   r   rE      s     z1get_gc_managed_objs_total_size.<locals>.<genexpr>rs   rj   rk   z8pympler could not be imported - Run: pip install pymplerrl   N)Zpympler.muppyr   r   sumr   r   r   )r   Zobjs_total_sizer   r   r   get_gc_managed_objs_total_size   s    
r   c                  C   s.   t  \} }| d d dd|d d ddS )zRequires python -X tracemallocrs   rj   z (peak=z) MiB)r   )currentZpeakr   r   r   ri      s    
ri   c                  C   s6   ddl m}  | j }|d |d  }|t ddS )Nr   )ImageZallocated_blocksZfreed_blocksrj   rk   )ZPILr   coreZ	get_statsPIL_MEM_BLOCK_SIZE_IN_MIB)r   statsZblocks_in_user   r   r   rh     s    
rh   )$__doc__rf   rt   r   Znumbersr   tracemallocr   r   typingr   r   r   r   r   r
   r,   r6   r   r   r=   r   r#   rA   rU   rY   r]   rd   rb   rg   rm   r   r   r   ri   rh   r   r   r   r   <module>   s8   


