o
    u]                     @   s  d Z ddlZddlZddlZddlZejjddddddZ	e
e	\ZZZZZZe	jejd	 e	jeje	jeje	jejd	 e	jeje	jejiZeee d eee d ed
Zeee  ejdddZe ZG dd dejZejs~ee  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*G d(d) d)ejZ+G d*d+ d+ejZ,d,d- Z-dS ).aa  
Functions to aid library logging. The default logging
:data:`~stem.util.log.Runlevel` is usually NOTICE and above.

**Stem users are more than welcome to listen for stem events, but these
functions are not being vended to our users. They may change in the future, use
them at your own risk.**

**Module Overview:**

::

  get_logger - provides the stem's Logger instance
  logging_level - converts a runlevel to its logging number
  escape - escapes special characters in a message in preparation for logging

  log - logs a message at the given runlevel
  log_once - logs a message, deduplicating if it has already been logged
  trace - logs a message at the TRACE runlevel
  debug - logs a message at the DEBUG runlevel
  info - logs a message at the INFO runlevel
  notice - logs a message at the NOTICE runlevel
  warn - logs a message at the WARN runlevel
  error - logs a message at the ERROR runlevel

  LogBuffer - Buffers logged events so they can be iterated over.
    |- is_empty - checks if there's events in our buffer
    +- __iter__ - iterates over and removes the buffered events

  log_to_stdout - reports further logged events to stdout

.. data:: Runlevel (enum)

  Enumeration for logging runlevels.

  ========== ===========
  Runlevel   Description
  ========== ===========
  **ERROR**  critical issue occurred, the user needs to be notified
  **WARN**   non-critical issue occurred that the user should be aware of
  **NOTICE** information that is helpful to the user
  **INFO**   high level library activity
  **DEBUG**  low level library activity
  **TRACE**  request/reply logging
  ========== ===========
    NTRACEDEBUGINFONOTICEWARNERROR   stem'%(asctime)s [%(levelname)s] %(message)s%m/%d/%Y %H:%M:%SZfmtZdatefmtc                   @      e Zd Zdd Zdd ZdS )_NullHandlerc                 C   s   t jj| t jd d d S )Nr   level)loggingHandler__init__FATALself r   //usr/lib/python3/dist-packages/stem/util/log.pyr   `   s   z_NullHandler.__init__c                 C   s   d S Nr   r   recordr   r   r   emitc   s   z_NullHandler.emitN__name__
__module____qualname__r   r   r   r   r   r   r   _   s    r   c                   C   s   t S )zH
  Provides the stem logger.

  :returns: **logging.Logger** for stem
  )LOGGERr   r   r   r   
get_loggerk   s   r"   c                 C   s   | rt |  S tjd S )z
  Translates a runlevel into the value expected by the logging module.

  :param stem.util.log.Runlevel runlevel: runlevel to be returned, no logging if **None**
  r   )
LOG_VALUESr   r   runlevelr   r   r   logging_levelu   s   
r&   c                  C   s&   t  jD ]} | jttkr dS qdS )z
  Checks if we're logging at the trace runlevel.

  .. versionadded:: 1.6.0

  :returns: **True** if we're logging at the trace runlevel and **False** otherwise
  TF)r"   handlersr   r&   r   )Zhandlerr   r   r   
is_tracing   s
   	r(   c                 C   s6   t j rt jj| } dD ]
\}}| ||} q| S )z
  Escapes specific sequences for logging (newlines, tabs, carriage returns). If
  the input is **bytes** then this converts it to **unicode** under python 3.x.

  :param str message: string to be escaped

  :returns: str that is escaped
  ))
z\n)z\r)	z\t)r	   ZprereqZis_python_3utilZ	str_toolsZ_to_unicodereplace)messagepatternZreplacementr   r   r   escape   s
   

r0   c                 C   s   | rt t|  | dS dS )z
  Logs a message at the given runlevel.

  :param stem.util.log.Runlevel runlevel: runlevel to log the message at, logging is skipped if **None**
  :param str message: message to be logged
  N)r!   logr#   )r%   r.   r   r   r   r1      s   r1   c                 C   s(   |r| t v rdS t |  t|| dS )a  
  Logs a message at the given runlevel. If a message with this ID has already
  been logged then this is a no-op.

  :param str message_id: unique message identifier to deduplicate on
  :param stem.util.log.Runlevel runlevel: runlevel to log the message at, logging is skipped if **None**
  :param str message: message to be logged

  :returns: **True** if we log the message, **False** otherwise
  FN)DEDUPLICATION_MESSAGE_IDSaddr1   )Z
message_idr%   r.   r   r   r   log_once   s   
r4   c                 C      t tj|  d S r   )r1   Runlevelr   r.   r   r   r   trace      r8   c                 C   r5   r   )r1   r6   r   r7   r   r   r   debug   r9   r:   c                 C   r5   r   )r1   r6   r   r7   r   r   r   info   r9   r;   c                 C   r5   r   )r1   r6   r   r7   r   r   r   notice   r9   r<   c                 C   r5   r   )r1   r6   r   r7   r   r   r   warn   r9   r=   c                 C   r5   r   )r1   r6   r   r7   r   r   r   error   r9   r>   c                   @   s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )	LogBuffera>  
  Basic log handler that listens for stem events and stores them so they can be
  read later. Log entries are cleared as they are read.

  .. versionchanged:: 1.4.0
     Added the yield_records argument.

  .. deprecated:: 1.8.0
     This will be dropped in Stem 2.x. Use python's logging.BufferingHandler instead.
  Fc                 C   s*   t jj| t|d t| _g | _|| _d S )Nr   )r   r   r   r&   	FORMATTER	formatter_buffer_yield_records)r   r%   Zyield_recordsr   r   r   r      s   
zLogBuffer.__init__c                 C   s   t | j S r   )boolrB   r   r   r   r   is_empty   s   zLogBuffer.is_emptyc                 c   s:    | j r| j d}| jr|n| j|V  | j sd S d S )Nr   )rB   poprC   rA   formatr   r   r   r   __iter__   s
   zLogBuffer.__iter__c                 C   s   | j | d S r   )rB   appendr   r   r   r   r      r9   zLogBuffer.emitN)F)r   r   r    __doc__r   rE   rH   r   r   r   r   r   r?      s    
r?   c                   @   r   )_StdoutLoggerc                 C   s(   t jj| t|d t jddd| _d S )Nr   r
   r   r   )r   r   r   r&   	FormatterrA   )r   r%   r   r   r   r     s
   z_StdoutLogger.__init__c                 C   s   t | j| d S r   )printrA   rG   r   r   r   r   r     s   z_StdoutLogger.emitNr   r   r   r   r   rK     s    rK   c                 C   s   t  t|  dS )z
  Logs further events to stdout.

  :param stem.util.log.Runlevel runlevel: minimum runlevel a message needs to be to be logged
  N)r"   
addHandlerrK   r$   r   r   r   log_to_stdout  s   rO   ).rJ   r   Zstem.prereqr	   Zstem.util.enumZstem.util.str_toolsr,   enumZUppercaseEnumr6   listr   r   r   r   r   ZERRr   r#   ZaddLevelNameZ	getLoggerr!   ZsetLevelrL   r@   setr2   r   r   r'   rN   r"   r&   r(   r0   r1   r4   r8   r:   r;   r<   r=   r>   r?   rK   rO   r   r   r   r   <module>   sR   /	

%