U
    T?hI.                     @   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mZ ddlm	Z	m
Z
 ddlmZmZmZmZmZmZ dZdZdZeeZG d	d
 d
eZdddZdddZdd Zdd Zdd ZdS )aw  
Easy to use UNIX system logging for Python's :mod:`logging` module.

Admittedly system logging has little to do with colored terminal output, however:

- The `coloredlogs` package is my attempt to do Python logging right and system
  logging is an important part of that equation.

- I've seen a surprising number of quirks and mistakes in system logging done
  in Python, for example including ``%(asctime)s`` in a format string (the
  system logging daemon is responsible for adding timestamps and thus you end
  up with duplicate timestamps that make the logs awful to read :-).

- The ``%(programname)s`` filter originated in my system logging code and I
  wanted it in `coloredlogs` so the step to include this module wasn't that big.

- As a bonus this Python module now has a test suite and proper documentation.

So there :-P. Go take a look at :func:`enable_system_logging()`.
    N)coerce_boolean)on_macos
on_windows)DEFAULT_LOG_LEVELProgramNameFilteradjust_levelfind_program_namelevel_to_numberreplace_handlerz/var/run/syslogz/dev/logz7%(programname)s[%(process)d]: %(levelname)s %(message)sc                   @   s*   e Zd ZdZdd Zdd Zd	ddZdS )
SystemLoggingz)Context manager to enable system logging.c                 O   s   || _ || _d| _dS )z
        Initialize a :class:`SystemLogging` object.

        :param args: Positional arguments to :func:`enable_system_logging()`.
        :param kw: Keyword arguments to :func:`enable_system_logging()`.
        N)argskwhandler)selfr   r    r   D/var/www/html/venv/lib/python3.8/site-packages/coloredlogs/syslog.py__init__N   s    zSystemLogging.__init__c                 C   s    | j dkrt| j| j| _ | j S )z0Enable system logging when entering the context.N)r   enable_system_loggingr   r   )r   r   r   r   	__enter__Y   s    
zSystemLogging.__enter__Nc                 C   sF   | j dk	rB|dk	r tjddd | jdp2t | j  d| _ dS )a	  
        Disable system logging when leaving the context.

        .. note:: If an exception is being handled when we leave the context a
                  warning message including traceback is logged *before* system
                  logging is disabled.
        Nz4Disabling system logging due to unhandled exception!T)exc_infologger)r   r   warningr   getlogging	getLoggerremoveHandler)r   exc_type	exc_value	tracebackr   r   r   __exit___   s
    
zSystemLogging.__exit__)NNN)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   J   s   r   Tc                 K   s   t  s
dS | pt } |pt }|p&t}t|dt}t|t	|\}}|rP|rt
f |}|rtj||| d |t| || t|| |S )au  
    Redirect :mod:`logging` messages to the system log (e.g. ``/var/log/syslog``).

    :param programname: The program name to embed in log messages (a string, defaults
                         to the result of :func:`~coloredlogs.find_program_name()`).
    :param fmt: The log format for system log messages (a string, defaults to
                :data:`DEFAULT_LOG_FORMAT`).
    :param logger: The logger to which the :class:`~logging.handlers.SysLogHandler`
                   should be connected (defaults to the root logger).
    :param level: The logging level for the :class:`~logging.handlers.SysLogHandler`
                  (defaults to :data:`.DEFAULT_LOG_LEVEL`). This value is coerced
                  using :func:`~coloredlogs.level_to_number()`.
    :param reconfigure: If :data:`True` (the default) multiple calls to
                        :func:`enable_system_logging()` will each override
                        the previous configuration.
    :param kw: Refer to :func:`connect_to_syslog()`.
    :returns: A :class:`~logging.handlers.SysLogHandler` object or
              :data:`None`. If an existing handler is found and `reconfigure`
              is :data:`False` the existing handler object is returned. If the
              connection to the system logging daemon fails :data:`None` is
              returned.

    As of release 15.0 this function uses :func:`is_syslog_supported()` to
    check whether system logging is supported and appropriate before it's
    enabled.

    .. note:: When the logger's effective level is too restrictive it is
              relaxed (refer to `notes about log levels`_ for details).
    Nlevel)r   fmtprogramname)is_syslog_supportedr   r   r   DEFAULT_LOG_FORMATr	   r   r   r
   match_syslog_handlerconnect_to_syslogr   installsetFormatter	Formatter
addHandlerr   )r&   r%   r   reconfigurer   r$   r   r   r   r   r   n   s    



r   c              	   C   s   | s
t  } |dkrtjjj}|dkr(t}tjtjdfD ]^}t	|| d}|dk	rV||d< ztjjf |}W n t
k
r|   Y q6X |t| |  S q6dS )ae  
    Create a :class:`~logging.handlers.SysLogHandler`.

    :param address: The device file or network address of the system logging
                    daemon (a string or tuple, defaults to the result of
                    :func:`find_syslog_address()`).
    :param facility: Refer to :class:`~logging.handlers.SysLogHandler`.
                     Defaults to ``LOG_USER``.
    :param level: The logging level for the :class:`~logging.handlers.SysLogHandler`
                  (defaults to :data:`.DEFAULT_LOG_LEVEL`). This value is coerced
                  using :func:`~coloredlogs.level_to_number()`.
    :returns: A :class:`~logging.handlers.SysLogHandler` object or :data:`None` (if the
              system logging daemon is unavailable).

    The process of connecting to the system logging daemon goes as follows:

    - The following two socket types are tried (in decreasing preference):

       1. :data:`~socket.SOCK_RAW` avoids truncation of log messages but may
          not be supported.
       2. :data:`~socket.SOCK_STREAM` (TCP) supports longer messages than the
          default (which is UDP).
    N)facilityaddresssocktype)find_syslog_addressr   handlersSysLogHandlerLOG_USERr   socketSOCK_RAWSOCK_STREAMdictIOErrorsetLevelr	   )r1   r0   r$   r2   r   r   r   r   r   r*      s     
r*   c                   C   s:   t jdkrtjtrtS tjtr*tS dtjj	fS dS )a  
    Find the most suitable destination for system log messages.

    :returns: The pathname of a log device (a string) or an address/port tuple as
              supported by :class:`~logging.handlers.SysLogHandler`.

    On Mac OS X this prefers :data:`LOG_DEVICE_MACOSX`, after that :data:`LOG_DEVICE_UNIX`
    is checked for existence. If both of these device files don't exist the default used
    by :class:`~logging.handlers.SysLogHandler` is returned.
    darwin	localhostN)
sysplatformospathexistsLOG_DEVICE_MACOSXLOG_DEVICE_UNIXr   r4   SYSLOG_UDP_PORTr   r   r   r   r3      s
    r3   c                  C   s.   t jd} | dk	rt| S t p&t  S dS )aK  
    Determine whether system logging is supported.

    :returns:

        :data:`True` if system logging is supported and can be enabled,
        :data:`False` if system logging is not supported or there are good
        reasons for not enabling it.

    The decision making process here is as follows:

    Override
     If the environment variable ``$COLOREDLOGS_SYSLOG`` is set it is evaluated
     using :func:`~humanfriendly.coerce_boolean()` and the resulting value
     overrides the platform detection discussed below, this allows users to
     override the decision making process if they disagree / know better.

    Linux / UNIX
     On systems that are not Windows or MacOS (see below) we assume UNIX which
     means either syslog is available or sending a bunch of UDP packets to
     nowhere won't hurt anyone...

    Microsoft Windows
     Over the years I've had multiple reports of :pypi:`coloredlogs` spewing
     extremely verbose errno 10057 warning messages to the console (once for
     each log message I suppose) so I now assume it a default that
     "syslog-style system logging" is not generally available on Windows.

    Apple MacOS
     There's cPython issue `#38780`_ which seems to result in a fatal exception
     when the Python interpreter shuts down. This is (way) worse than not
     having system logging enabled. The error message mentioned in `#38780`_
     has actually been following me around for years now, see for example:

     - https://github.com/xolox/python-rotate-backups/issues/9 mentions Docker
       images implying Linux, so not strictly the same as `#38780`_.

     - https://github.com/xolox/python-npm-accel/issues/4 is definitely related
       to `#38780`_ and is what eventually prompted me to add the
       :func:`is_syslog_supported()` logic.

    .. _#38780: https://bugs.python.org/issue38780
    ZCOLOREDLOGS_SYSLOGN)rA   environr   r   r   r   )overrider   r   r   r'      s    ,r'   c                 C   s   t | tjjS )aF  
    Identify system logging handlers.

    :param handler: The :class:`~logging.Handler` class to check.
    :returns: :data:`True` if the handler is a
              :class:`~logging.handlers.SysLogHandler`,
              :data:`False` otherwise.

    This function can be used as a callback for :func:`.find_handler()`.
    )
isinstancer   r4   r5   )r   r   r   r   r)     s    r)   )NNNT)NNN)r#   r   logging.handlersrA   r7   r?   Zhumanfriendlyr   Zhumanfriendly.compatr   r   Zcoloredlogsr   r   r   r   r	   r
   rD   rE   r(   r   r    r   objectr   r   r*   r3   r'   r)   r   r   r   r   <module>   s$    	
$
8
-3