
    <`PC                        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Zd dlm	Z	 ej
        ZddddZ G d d	ej                  Zd
 ZddZ G d de          Z G d dej                  Z G d dej                  Z G d de          ZefdZefdZedk    r/d dlZ e j         ej        ej                  j                    dS dS )    Nwraps)MappingCallable)PercentStylez%(levelname)s: %(message)sz%(message)s)*INFODEBUGc                   .     e Zd ZdZd fd	Z fdZ xZS )LevelFormatteray  Log formatter with level-specific formatting.

	Formatter class which optionally takes a dict of logging levels to
	format strings, allowing to customise the log records appearance for
	specific levels.


	Attributes:
		fmt: A dictionary mapping logging levels to format strings.
			The ``*`` key identifies the default format string.
		datefmt: As per py:class:`logging.Formatter`
		style: As per py:class:`logging.Formatter`

	>>> import sys
	>>> handler = logging.StreamHandler(sys.stdout)
	>>> formatter = LevelFormatter(
	...     fmt={
	...         '*':     '[%(levelname)s] %(message)s',
	...         'DEBUG': '%(name)s [%(levelname)s] %(message)s',
	...         'INFO':  '%(message)s',
	...     })
	>>> handler.setFormatter(formatter)
	>>> log = logging.getLogger('test')
	>>> log.setLevel(logging.DEBUG)
	>>> log.addHandler(handler)
	>>> log.debug('this uses a custom format string')
	test [DEBUG] this uses a custom format string
	>>> log.info('this also uses a custom format string')
	this also uses a custom format string
	>>> log.warning("this one uses the default format string")
	[WARNING] this one uses the default format string
	N%c                    |dk    rt          d          |t          }t          |t                    r|}i }nMt          |t                    r&t          |          }|                    dd           }nt          d|z            t          t          |           
                    ||           | j        | _        i | _        |                                D ]#\  }}t          j        |          }|| j        |<   $d S )Nr   z:only '%' percent style is supported in both python 2 and 3r   z&fmt must be a str or a dict of str: %r)
ValueErrorDEFAULT_FORMATS
isinstancestrr   dictpop	TypeErrorsuperr   __init___fmtdefault_formatcustom_formatsitemslogging_checkLevel)selffmtdatefmtstyler   r   level	__class__s          ;lib/python3.11/site-packages/fontTools/misc/loggingTools.pyr   zLevelFormatter.__init__8   s   
c\\	@
B 
B B[	3S C>>>#w CII>"&&sD11>>	;cA	B	BB&&~w???	$$"((** $ $jeSu%%5 #4u$ $    c                    | j         rR| j                             |j        | j                  }| j        |k    r"|| _        t
          rt          |          | _        t          t          |           	                    |          S N)
r   getlevelnor   r   r   _styler   r   format)r   recordr   r#   s      r$   r+   zLevelFormatter.formatM   st    	 %			 	 1D	E	E3
i3DI %$$T[	~t	$	$	+	+F	3	33r%   )NNr   )__name__
__module____qualname____doc__r   r+   __classcell__r#   s   @r$   r   r      sa         B$ $ $ $ $ $*4 4 4 4 4 4 4 4 4r%   r   c                     |                      dd          }|d| v rd| v rt          d          nd| v sd| v rt          d          |q|                      dd          }|                      dd          }|rt          j        ||          }n*|                      dd          }t          j        |          }|g}|                      d	d
          }|rt          |t                    rt          j        |          }t          |j	                   |                      dd          }|                      dd          }|                      dd          }	t          |||	          }
|                      dg           }|D ]T}|j        |                    |
           |j        s|D ]}|                    |           |                    |           U|j	        dk    r|                      dd          |_        |                      dd          }||                    |           | r9d                    |                                           }t          d|z            dS )a  A more sophisticated logging system configuation manager.

	This is more or less the same as :py:func:`logging.basicConfig`,
	with some additional options and defaults.

	The default behaviour is to create a ``StreamHandler`` which writes to
	sys.stderr, set a formatter using the ``DEFAULT_FORMATS`` strings, and add
	the handler to the top-level library logger ("fontTools").

	A number of optional keyword arguments may be specified, which can alter
	the default behaviour.

	Args:

		logger: Specifies the logger name or a Logger instance to be
			configured. (Defaults to "fontTools" logger). Unlike ``basicConfig``,
			this function can be called multiple times to reconfigure a logger.
			If the logger or any of its children already exists before the call is
			made, they will be reset before the new configuration is applied.
		filename: Specifies that a ``FileHandler`` be created, using the
			specified filename, rather than a ``StreamHandler``.
		filemode: Specifies the mode to open the file, if filename is
			specified. (If filemode is unspecified, it defaults to ``a``).
		format: Use the specified format string for the handler. This
			argument also accepts a dictionary of format strings keyed by
			level name, to allow customising the records appearance for
			specific levels. The special ``'*'`` key is for 'any other' level.
		datefmt: Use the specified date/time format.
		level: Set the logger level to the specified level.
		stream: Use the specified stream to initialize the StreamHandler. Note
			that this argument is incompatible with ``filename`` - if both
			are present, ``stream`` is ignored.
		handlers: If specified, this should be an iterable of already created
			handlers, which will be added to the logger. Any handler in the
			list which does not have a formatter assigned will be assigned the
			formatter created in this function.
		filters: If specified, this should be an iterable of already created
			filters. If the ``handlers`` do not already have filters assigned,
			these filters will be added to them.
		propagate: All loggers have a ``propagate`` attribute which determines
			whether to continue searching for handlers up the logging hierarchy.
			If not provided, the "propagate" attribute will be set to ``False``.
	handlersNstreamfilenamez8'stream' and 'filename' should not be specified togetherzG'stream' or 'filename' should not be specified together with 'handlers'filemodealogger	fontTools)parentr+   r    r!   r   filtersroot	propagateFr"   z, zUnrecognised argument(s): %s)r   r   r   FileHandlerStreamHandlerr   r   	getLogger_resetExistingLoggersnamer   	formattersetFormatterr<   	addFilter
addHandlerr>   setLeveljoinkeys)kwargsr4   r6   modehr5   r9   fsdfsr!   r   r<   fr"   rJ   s                  r$   configLoggerrQ   X   s   Z JJz4((J&00	  
 
  ://	 - 
. 
. .ZZ
D))(	J	$	$$ %8T**11JJx&&6V$$1S(
**X{
+
+ %*VS)) %V$$&fk****jj4  zz)T""	GS	!	!b#u%%::i$$
  Q[>>#	
   qKKNNNNA
K6ZZU33&	GT	"	"	//%
 :	6;;==	!	!$1D8999: :r%   r=   c                    t           j        }t          |j        j                                                  }| dk    r| g|z   }n| |vrdS | |v r~| g}|                    |           dz   }| dz   }t          |          }t          |          }||k     r:||         d|         |k    r|                    ||                    |dz  }||k     :|D ]}|dk    ru|	                    t           j
                   |j        dd         D ]}	|                    |	           |j        dd         D ]}
|                    |
           d|_        }|j        j        |         }t           j        |_        g |_        g |_        d|_        d|_        dS )z Reset the logger named 'parent' and all its children to their initial
	state, if they already exist in the current configuration.
	r=   N   .FT)r   r=   sortedmanager
loggerDictrJ   indexlenappendrH   WARNINGr4   removeHandlerr<   removeFiltersdisabledNOTSETr"   r>   )r;   r=   existingloggers_to_resetiprefixedpflennum_existingrC   rM   rP   r9   s               r$   rB   rB      s    	4<*//1122
fX(H&XnnVq !c\(
h--%X,	Lqk&5&X%%HQK(((61 	
L   T	V^^==!!!M!!!  qqLO  qq4==L#D)6.6<6?6>66?? r%   c                   p    e Zd ZdZej        ZdZdZddZ	ddZ
d Zd Zd	 Zd
 Zd ZddZd Zd Zd ZdS )Timera   Keeps track of overall time and split/lap times.

	>>> import time
	>>> timer = Timer()
	>>> time.sleep(0.01)
	>>> print("First lap:", timer.split())
	First lap: ...
	>>> time.sleep(0.02)
	>>> print("Second lap:", timer.split())
	Second lap: ...
	>>> print("Overall time:", timer.time())
	Overall time: ...

	Can be used as a context manager inside with-statements.

	>>> with Timer() as t:
	...     time.sleep(0.01)
	>>> print("%0.3f seconds" % t.elapsed)
	0... seconds

	If initialised with a logger, it can log the elapsed time automatically
	upon exiting the with-statement.

	>>> import logging
	>>> log = logging.getLogger("my-fancy-timer-logger")
	>>> configLogger(logger=log, level="DEBUG", format="%(message)s", stream=sys.stdout)
	>>> with Timer(log, 'do something'):
	...     time.sleep(0.01)
	Took ... to do something

	The same Timer instance, holding a reference to a logger, can be reused
	in multiple with-statements, optionally with different messages or levels.

	>>> timer = Timer(log)
	>>> with timer():
	...     time.sleep(0.01)
	elapsed time: ...s
	>>> with timer('redo it', level=logging.INFO):
	...     time.sleep(0.02)
	Took ... to redo it

	It can also be used as a function decorator to log the time elapsed to run
	the decorated function.

	>>> @timer()
	... def test1():
	...    time.sleep(0.01)
	>>> @timer('run test 2', level=logging.INFO)
	... def test2():
	...    time.sleep(0.02)
	>>> test1()
	Took ... to run 'test1'
	>>> test2()
	Took ... to run test 2
	zelapsed time: %(time).3fszTook %(time).3fs to %(msg)sNc                     |                      |           |8dD ]5}t                                          |          t          d|z            6|| _        ||nt
          | _        || _        d S )N)msgr"   z*'%s' can't be specified without a 'logger')resetlocalsr(   r   r9   
TIME_LEVELr"   ri   )r   r9   ri   r"   startargs         r$   r   zTimer.__init__  s    **U^ : :sxx||C$2S8: : : % $+)uuz$*$(((r%   c                 r    ||                                  | _        n|| _        | j        | _        d| _        dS )z2 Reset timer to 'start_time' or the current time. N        )_timerm   lastelapsed)r   rm   s     r$   rj   zTimer.reset*  s3    
]

4::4:j$)$,,,r%   c                 :    |                                  | j        z
  S )z? Return the overall time (in seconds) since the timer started. )rq   rm   r   s    r$   timez
Timer.time3  s    	
	""r%   c                 d    |                                  }|| j        z
  | _        || _        | j        S )z? Split and return the lap time (in seconds) in between splits. rq   rr   rs   )r   currents     r$   splitzTimer.split7  s,    JJLL'49$$,$)	r%   c                     |s| j         }|                    d          dk     r| j        ||dz  }n 	 |d|iz  }n# t          t          f$ r Y nw xY w|S )z Format 'time' value in 'msg' and return formatted string.
		If 'msg' contains a '%(time)' format string, try to use that.
		Otherwise, use the predefined 'default_format'.
		If 'msg' is empty or None, fall back to 'default_msg'.
		z%(time)r   ri   rv   rv   )default_msgfindr   KeyErrorr   )r   ri   rv   s      r$   
formatTimezTimer.formatTime>  s     
 		3XXi1		sD99	933	

CCZ
  	 	 	D		*s   : AAc                 F    |                                  | _        d| _        | S )z Start a new lap rp   rx   ru   s    r$   	__enter__zTimer.__enter__O  s    jjll$)$,	+r%   c                     |                                  }| j        |rdS |                     | j        |          }| j        |d}| j                            | j        ||           dS )z End the current lap. If timer has a logger, log the time elapsed,
		using the format string in self.msg (or the default one).
		Nr|   )rz   r9   r   ri   logr"   )r   exc_type	exc_value	tracebackrv   message	msg_partss          r$   __exit__zTimer.__exit__U  sk     
$	[H 
6OODHd++' x//)+//$*gy11111r%   c                 6    t          |t                    r5| j        sdj        z   _        t	                     fd            }|S |p|                    d          }|                    d j                  }                      j        ||          S )a9   If the first argument is a function, return a decorator which runs
		the wrapped function inside Timer's context manager.
		Otherwise, treat the first argument as a 'msg' string and return an updated
		Timer instance, referencing the same logger.
		A 'level' keyword can also be passed to override self.level.
		zrun '%s'c                  L    5   | i |cd d d            S # 1 swxY w Y   d S r'    )argskwdsfuncr   s     r$   wrapperzTimer.__call__.<locals>.wrapperq  s    	    D$$                                   s   ri   r"   )	r   r   ri   r-   r   r(   r"   r#   r9   )r   func_or_msgrK   r   ri   r"   r   s   `     @r$   __call__zTimer.__call__d  s     X&& 2
4
( *DM)DH	$KK          K  >		)

5))3::gtz**5
..c5
1
11r%   c                     | j         S r'   rs   ru   s    r$   	__float__zTimer.__float__{  s
    	r%   c                 *    t          | j                  S r'   )intrs   ru   s    r$   __int__zTimer.__int__~  s    	T\		r%   c                     d| j         z  S )Nz%.3fr   ru   s    r$   __str__zTimer.__str__  s    	$,	r%   )NNNNr'   )r-   r.   r/   r0   timeitdefault_timerrq   r}   r   r   rj   rv   rz   r   r   r   r   r   r   r   r   r%   r$   rg   rg      s        6 6r 
	*/	 	 	 	   # # #    "  2 2 22 2 2 2.        r%   rg   c                       e Zd ZdZd Zd ZdS )ChannelsFiltera  Provides a hierarchical filter for log entries based on channel names.

	Filters out records emitted from a list of enabled channel names,
	including their children. It works the same as the ``logging.Filter``
	class, but allows the user to specify multiple channel names.

	>>> import sys
	>>> handler = logging.StreamHandler(sys.stdout)
	>>> handler.setFormatter(logging.Formatter("%(message)s"))
	>>> filter = ChannelsFilter("A.B", "C.D")
	>>> handler.addFilter(filter)
	>>> root = logging.getLogger()
	>>> root.addHandler(handler)
	>>> root.setLevel(level=logging.DEBUG)
	>>> logging.getLogger('A.B').debug('this record passes through')
	this record passes through
	>>> logging.getLogger('A.B.C').debug('records from children also pass')
	records from children also pass
	>>> logging.getLogger('C.D').debug('this one as well')
	this one as well
	>>> logging.getLogger('A.B.').debug('also this one')
	also this one
	>>> logging.getLogger('A.F').debug('but this one does not!')
	>>> logging.getLogger('C.DE').debug('neither this one!')
	c                 ^    || _         t          |          | _        d |D             | _        d S )Nc                 .    i | ]}|t          |          S r   )rY   ).0ns     r$   
<dictcomp>z+ChannelsFilter.__init__.<locals>.<dictcomp>  s     +++!SVV+++r%   )namesrY   numlengths)r   r   s     r$   r   zChannelsFilter.__init__  s/    $*ZZ$(++U+++$,,,r%   c                     | j         dk    rdS | j        D ]Q}| j        |         }||j        k    r dS |j                            |d|          dk    r|j        |         dk    r dS RdS )Nr   TrT   F)r   r   r   rC   r~   )r   r,   rC   nlens       r$   filterzChannelsFilter.filter  s    	X]]
$j  d
,t
4
fk44			$4	(	(A	-	-	T	c	!	!44	r%   N)r-   r.   r/   r0   r   r   r   r%   r$   r   r     s<         4, , ,

 
 
 
 
r%   r   c                   8     e Zd Z fdZd Zd Zd ZddZ xZS )CapturingLogHandlerc                     t          t          |                               |           g | _        t	          |t
                    rt          j        |          | _        d S || _        d S )N)r"   )	r   r   r   recordsr   r   r   rA   r9   )r   r9   r"   r#   s      r$   r   zCapturingLogHandler.__init__  s_    T""++%+888$, "6**4;;;4;;;r%   c                    | j         j        | _        | j         j        | _        | j         j        | _        | j                             |            | j                             | j                   d| j         _        d| j         _        | S )NF)	r9   r^   original_disabledr"   original_levelr>   original_propagaterG   rH   ru   s    r$   r   zCapturingLogHandler.__enter__  sp    ;/$)$ K1$++tz"""$+$+	+r%   c                     | j                             |            | j                             | j                   | j        | j         _        | j        | j         _        | S r'   )r9   r\   rH   r   r   r^   r   r>   )r   typevaluer   s       r$   r   zCapturingLogHandler.__exit__  sP    +D!!!+t*+++/$+1$+	+r%   c                 :    | j                             |           d S r'   )r   rZ   )r   r,   s     r$   emitzCapturingLogHandler.emit  s    ,fr%   Nc                     dd l }|                    |          }| j        D ],}|                    |                                          r dS -|d|z  }J |            )Nr   Tz(Pattern '%s' not found in logger records)recompiler   search
getMessage)r   regexpri   r   patternrs         r$   assertRegexzCapturingLogHandler.assertRegex  so    )))JJv'<  annQ\\^^$$ 44[	3f	<3C---r%   r'   )	r-   r.   r/   r   r   r   r   r   r1   r2   s   @r$   r   r     sy            
 
 
           r%   r   c                   (    e Zd ZdZed             ZdS )LogMixina   Mixin class that adds logging functionality to another class.

	You can define a new class that subclasses from ``LogMixin`` as well as
	other base classes through multiple inheritance.
	All instances of that class will have a ``log`` property that returns
	a ``logging.Logger`` named after their respective ``<module>.<class>``.

	For example:

	>>> class BaseClass(object):
	...     pass
	>>> class MyClass(LogMixin, BaseClass):
	...     pass
	>>> a = MyClass()
	>>> isinstance(a.log, logging.Logger)
	True
	>>> print(a.log.name)
	fontTools.misc.loggingTools.MyClass
	>>> class AnotherClass(MyClass):
	...     pass
	>>> b = AnotherClass()
	>>> isinstance(b.log, logging.Logger)
	True
	>>> print(b.log.name)
	fontTools.misc.loggingTools.AnotherClass
	c                     t          | d          sDd                    | j        j        | j        j        f          }t          j        |          | _        | j        S )N_logrT   )hasattrrI   r#   r.   r-   r   rA   r   )r   rC   s     r$   r   zLogMixin.log  sU    	v		 '
((	^ 78 4  &&49	r%   N)r-   r.   r/   r0   propertyr   r   r%   r$   r   r     s9         6   (  r%   r   c                 >    t          j        | d||d           dS )z< Raise a warning about deprecated function argument 'name'.  is deprecated;    category
stacklevelN)warningswarn)rC   ri   r   s      r$   deprecateArgumentr     s=    	 DD##&aI I I I I Ir%   c                       fd}|S )zD Decorator to raise a warning when a deprecated function is called. c                 B     t                      fd            }|S )Nc                  V    t          j        j        dd            | i |S )Nr      r   )r   r   r-   )r   rK   r   r   ri   s     r$   r   z5deprecateFunction.<locals>.decorator.<locals>.wrapper  sH    ="mmmSS1!% % % % $


r%   r   )r   r   r   ri   s   ` r$   	decoratorz$deprecateFunction.<locals>.decorator  s>    ;;            ; 
 
.r%   r   )ri   r   r   s   `` r$   deprecateFunctionr   	  s*          	r%   __main__)optionflags)r=   )!sysr   r   	functoolsr   collections.abcr   r   r   r   r
   rl   r   	Formatterr   rQ   rB   objectrg   Filterr   Handlerr   r   UserWarningr   r   r-   doctestexittestmodELLIPSISfailedr   r%   r$   <module>r      s   



         - - - - - - - -              ]

 #	
 ?4 ?4 ?4 ?4 ?4W& ?4 ?4 ?4D]: ]: ]:@& & & &Ra a a a aF a a aH* * * * *W^ * * *Z( ( ( ( ('/ ( ( (V# # # # #v # # #L +6 I I I I %0 
 
 
 
 z	/'/g&6
7
7
7
>????? r%   