python (3.11.7)

(root)/
lib/
python3.11/
site-packages/
pip/
_vendor/
rich/
logging.py
       1  import logging
       2  from datetime import datetime
       3  from logging import Handler, LogRecord
       4  from pathlib import Path
       5  from types import ModuleType
       6  from typing import ClassVar, Iterable, List, Optional, Type, Union
       7  
       8  from pip._vendor.rich._null_file import NullFile
       9  
      10  from . import get_console
      11  from ._log_render import FormatTimeCallable, LogRender
      12  from .console import Console, ConsoleRenderable
      13  from .highlighter import Highlighter, ReprHighlighter
      14  from .text import Text
      15  from .traceback import Traceback
      16  
      17  
      18  class ESC[4;38;5;81mRichHandler(ESC[4;38;5;149mHandler):
      19      """A logging handler that renders output with Rich. The time / level / message and file are displayed in columns.
      20      The level is color coded, and the message is syntax highlighted.
      21  
      22      Note:
      23          Be careful when enabling console markup in log messages if you have configured logging for libraries not
      24          under your control. If a dependency writes messages containing square brackets, it may not produce the intended output.
      25  
      26      Args:
      27          level (Union[int, str], optional): Log level. Defaults to logging.NOTSET.
      28          console (:class:`~rich.console.Console`, optional): Optional console instance to write logs.
      29              Default will use a global console instance writing to stdout.
      30          show_time (bool, optional): Show a column for the time. Defaults to True.
      31          omit_repeated_times (bool, optional): Omit repetition of the same time. Defaults to True.
      32          show_level (bool, optional): Show a column for the level. Defaults to True.
      33          show_path (bool, optional): Show the path to the original log call. Defaults to True.
      34          enable_link_path (bool, optional): Enable terminal link of path column to file. Defaults to True.
      35          highlighter (Highlighter, optional): Highlighter to style log messages, or None to use ReprHighlighter. Defaults to None.
      36          markup (bool, optional): Enable console markup in log messages. Defaults to False.
      37          rich_tracebacks (bool, optional): Enable rich tracebacks with syntax highlighting and formatting. Defaults to False.
      38          tracebacks_width (Optional[int], optional): Number of characters used to render tracebacks, or None for full width. Defaults to None.
      39          tracebacks_extra_lines (int, optional): Additional lines of code to render tracebacks, or None for full width. Defaults to None.
      40          tracebacks_theme (str, optional): Override pygments theme used in traceback.
      41          tracebacks_word_wrap (bool, optional): Enable word wrapping of long tracebacks lines. Defaults to True.
      42          tracebacks_show_locals (bool, optional): Enable display of locals in tracebacks. Defaults to False.
      43          tracebacks_suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback.
      44          locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
      45              Defaults to 10.
      46          locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80.
      47          log_time_format (Union[str, TimeFormatterCallable], optional): If ``log_time`` is enabled, either string for strftime or callable that formats the time. Defaults to "[%x %X] ".
      48          keywords (List[str], optional): List of words to highlight instead of ``RichHandler.KEYWORDS``.
      49      """
      50  
      51      KEYWORDS: ClassVar[Optional[List[str]]] = [
      52          "GET",
      53          "POST",
      54          "HEAD",
      55          "PUT",
      56          "DELETE",
      57          "OPTIONS",
      58          "TRACE",
      59          "PATCH",
      60      ]
      61      HIGHLIGHTER_CLASS: ClassVar[Type[Highlighter]] = ReprHighlighter
      62  
      63      def __init__(
      64          self,
      65          level: Union[int, str] = logging.NOTSET,
      66          console: Optional[Console] = None,
      67          *,
      68          show_time: bool = True,
      69          omit_repeated_times: bool = True,
      70          show_level: bool = True,
      71          show_path: bool = True,
      72          enable_link_path: bool = True,
      73          highlighter: Optional[Highlighter] = None,
      74          markup: bool = False,
      75          rich_tracebacks: bool = False,
      76          tracebacks_width: Optional[int] = None,
      77          tracebacks_extra_lines: int = 3,
      78          tracebacks_theme: Optional[str] = None,
      79          tracebacks_word_wrap: bool = True,
      80          tracebacks_show_locals: bool = False,
      81          tracebacks_suppress: Iterable[Union[str, ModuleType]] = (),
      82          locals_max_length: int = 10,
      83          locals_max_string: int = 80,
      84          log_time_format: Union[str, FormatTimeCallable] = "[%x %X]",
      85          keywords: Optional[List[str]] = None,
      86      ) -> None:
      87          super().__init__(level=level)
      88          self.console = console or get_console()
      89          self.highlighter = highlighter or self.HIGHLIGHTER_CLASS()
      90          self._log_render = LogRender(
      91              show_time=show_time,
      92              show_level=show_level,
      93              show_path=show_path,
      94              time_format=log_time_format,
      95              omit_repeated_times=omit_repeated_times,
      96              level_width=None,
      97          )
      98          self.enable_link_path = enable_link_path
      99          self.markup = markup
     100          self.rich_tracebacks = rich_tracebacks
     101          self.tracebacks_width = tracebacks_width
     102          self.tracebacks_extra_lines = tracebacks_extra_lines
     103          self.tracebacks_theme = tracebacks_theme
     104          self.tracebacks_word_wrap = tracebacks_word_wrap
     105          self.tracebacks_show_locals = tracebacks_show_locals
     106          self.tracebacks_suppress = tracebacks_suppress
     107          self.locals_max_length = locals_max_length
     108          self.locals_max_string = locals_max_string
     109          self.keywords = keywords
     110  
     111      def get_level_text(self, record: LogRecord) -> Text:
     112          """Get the level name from the record.
     113  
     114          Args:
     115              record (LogRecord): LogRecord instance.
     116  
     117          Returns:
     118              Text: A tuple of the style and level name.
     119          """
     120          level_name = record.levelname
     121          level_text = Text.styled(
     122              level_name.ljust(8), f"logging.level.{level_name.lower()}"
     123          )
     124          return level_text
     125  
     126      def emit(self, record: LogRecord) -> None:
     127          """Invoked by logging."""
     128          message = self.format(record)
     129          traceback = None
     130          if (
     131              self.rich_tracebacks
     132              and record.exc_info
     133              and record.exc_info != (None, None, None)
     134          ):
     135              exc_type, exc_value, exc_traceback = record.exc_info
     136              assert exc_type is not None
     137              assert exc_value is not None
     138              traceback = Traceback.from_exception(
     139                  exc_type,
     140                  exc_value,
     141                  exc_traceback,
     142                  width=self.tracebacks_width,
     143                  extra_lines=self.tracebacks_extra_lines,
     144                  theme=self.tracebacks_theme,
     145                  word_wrap=self.tracebacks_word_wrap,
     146                  show_locals=self.tracebacks_show_locals,
     147                  locals_max_length=self.locals_max_length,
     148                  locals_max_string=self.locals_max_string,
     149                  suppress=self.tracebacks_suppress,
     150              )
     151              message = record.getMessage()
     152              if self.formatter:
     153                  record.message = record.getMessage()
     154                  formatter = self.formatter
     155                  if hasattr(formatter, "usesTime") and formatter.usesTime():
     156                      record.asctime = formatter.formatTime(record, formatter.datefmt)
     157                  message = formatter.formatMessage(record)
     158  
     159          message_renderable = self.render_message(record, message)
     160          log_renderable = self.render(
     161              record=record, traceback=traceback, message_renderable=message_renderable
     162          )
     163          if isinstance(self.console.file, NullFile):
     164              # Handles pythonw, where stdout/stderr are null, and we return NullFile
     165              # instance from Console.file. In this case, we still want to make a log record
     166              # even though we won't be writing anything to a file.
     167              self.handleError(record)
     168          else:
     169              try:
     170                  self.console.print(log_renderable)
     171              except Exception:
     172                  self.handleError(record)
     173  
     174      def render_message(self, record: LogRecord, message: str) -> "ConsoleRenderable":
     175          """Render message text in to Text.
     176  
     177          Args:
     178              record (LogRecord): logging Record.
     179              message (str): String containing log message.
     180  
     181          Returns:
     182              ConsoleRenderable: Renderable to display log message.
     183          """
     184          use_markup = getattr(record, "markup", self.markup)
     185          message_text = Text.from_markup(message) if use_markup else Text(message)
     186  
     187          highlighter = getattr(record, "highlighter", self.highlighter)
     188          if highlighter:
     189              message_text = highlighter(message_text)
     190  
     191          if self.keywords is None:
     192              self.keywords = self.KEYWORDS
     193  
     194          if self.keywords:
     195              message_text.highlight_words(self.keywords, "logging.keyword")
     196  
     197          return message_text
     198  
     199      def render(
     200          self,
     201          *,
     202          record: LogRecord,
     203          traceback: Optional[Traceback],
     204          message_renderable: "ConsoleRenderable",
     205      ) -> "ConsoleRenderable":
     206          """Render log for display.
     207  
     208          Args:
     209              record (LogRecord): logging Record.
     210              traceback (Optional[Traceback]): Traceback instance or None for no Traceback.
     211              message_renderable (ConsoleRenderable): Renderable (typically Text) containing log message contents.
     212  
     213          Returns:
     214              ConsoleRenderable: Renderable to display log.
     215          """
     216          path = Path(record.pathname).name
     217          level = self.get_level_text(record)
     218          time_format = None if self.formatter is None else self.formatter.datefmt
     219          log_time = datetime.fromtimestamp(record.created)
     220  
     221          log_renderable = self._log_render(
     222              self.console,
     223              [message_renderable] if not traceback else [message_renderable, traceback],
     224              log_time=log_time,
     225              time_format=time_format,
     226              level=level,
     227              path=path,
     228              line_no=record.lineno,
     229              link_path=record.pathname if self.enable_link_path else None,
     230          )
     231          return log_renderable
     232  
     233  
     234  if __name__ == "__main__":  # pragma: no cover
     235      from time import sleep
     236  
     237      FORMAT = "%(message)s"
     238      # FORMAT = "%(asctime)-15s - %(levelname)s - %(message)s"
     239      logging.basicConfig(
     240          level="NOTSET",
     241          format=FORMAT,
     242          datefmt="[%X]",
     243          handlers=[RichHandler(rich_tracebacks=True, tracebacks_show_locals=True)],
     244      )
     245      log = logging.getLogger("rich")
     246  
     247      log.info("Server starting...")
     248      log.info("Listening on http://127.0.0.1:8080")
     249      sleep(1)
     250  
     251      log.info("GET /index.html 200 1298")
     252      log.info("GET /imgs/backgrounds/back1.jpg 200 54386")
     253      log.info("GET /css/styles.css 200 54386")
     254      log.warning("GET /favicon.ico 404 242")
     255      sleep(1)
     256  
     257      log.debug(
     258          "JSONRPC request\n--> %r\n<-- %r",
     259          {
     260              "version": "1.1",
     261              "method": "confirmFruitPurchase",
     262              "params": [["apple", "orange", "mangoes", "pomelo"], 1.123],
     263              "id": "194521489",
     264          },
     265          {"version": "1.1", "result": True, "error": None, "id": "194521489"},
     266      )
     267      log.debug(
     268          "Loading configuration file /adasd/asdasd/qeqwe/qwrqwrqwr/sdgsdgsdg/werwerwer/dfgerert/ertertert/ertetert/werwerwer"
     269      )
     270      log.error("Unable to find 'pomelo' in database!")
     271      log.info("POST /jsonrpc/ 200 65532")
     272      log.info("POST /admin/ 401 42234")
     273      log.warning("password was rejected for admin site.")
     274  
     275      def divide() -> None:
     276          number = 1
     277          divisor = 0
     278          foos = ["foo"] * 100
     279          log.debug("in divide")
     280          try:
     281              number / divisor
     282          except:
     283              log.exception("An error of some kind occurred!")
     284  
     285      divide()
     286      sleep(1)
     287      log.critical("Out of memory!")
     288      log.info("Server exited with code=-1")
     289      log.info("[bold]EXITING...[/bold]", extra=dict(markup=True))