File: session_logger.py

package info (click to toggle)
python-nubia 0.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 772 kB
  • sloc: python: 4,182; makefile: 9; sh: 1
file content (68 lines) | stat: -rw-r--r-- 1,754 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/usr/bin/env python3

# Copyright (c) Facebook, Inc. and its affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

import re
import sys
import threading
from contextlib import contextmanager


class SessionLogger:
    """
    SessionLogger is used to intercept stdout content and duplicates it to
    a session log file.
    Inspired from prompt_toolkit.StdoutProxy but without the buffering.
    """

    def __init__(self, file):
        self._log_file = file
        self._lock = threading.RLock()
        self.original_stdout = sys.stdout

        # errors/encoding attribute for compatibility with sys.stdout.
        self.errors = sys.stdout.errors
        self.encoding = sys.stdout.encoding

    def path(self):
        return self._log_file.name

    def log_command(self, cmd):
        cmd = self._strip_ansii_colors(cmd)
        with self._lock:
            self._log_file.write(f"\n> {cmd}\n")

    def write(self, data):
        with self._lock:
            self.original_stdout.write(data)
            self._log_file.write(self._strip_ansii_colors(data))

    def flush(self):
        with self._lock:
            self.original_stdout.flush()
            self._log_file.flush()

    def _strip_ansii_colors(self, text):
        return re.sub("\x1b\\[.+?m", "", text)

    def isatty(self):
        return self.original_stdout.isatty()

    def fileno(self):
        return self.original_stdout.fileno()

    @contextmanager
    def patch(self):
        original_stdout = sys.stdout

        sys.stdout = self

        try:
            yield
        finally:
            self.flush()
            sys.stdout = original_stdout