| 19 | """Keys are output categories, values are CaptureOutput instances.""" |
| 20 | |
| 21 | def __init__(self, whose, category, fd, stream): |
| 22 | assert category not in self.instances |
| 23 | self.instances[category] = self |
| 24 | log.info("Capturing {0} of {1}.", category, whose) |
| 25 | |
| 26 | self.category = category |
| 27 | self._whose = whose |
| 28 | self._fd = fd |
| 29 | self._decoder = codecs.getincrementaldecoder("utf-8")(errors="surrogateescape") |
| 30 | |
| 31 | if stream is None: |
| 32 | # Can happen if running under pythonw.exe. |
| 33 | self._stream = None |
| 34 | else: |
| 35 | self._stream = stream.buffer |
| 36 | encoding = stream.encoding |
| 37 | if encoding is None or encoding == "cp65001": |
| 38 | encoding = "utf-8" |
| 39 | try: |
| 40 | self._encode = codecs.getencoder(encoding) |
| 41 | except Exception: |
| 42 | log.swallow_exception( |
| 43 | "Unsupported {0} encoding {1!r}; falling back to UTF-8.", |
| 44 | category, |
| 45 | encoding, |
| 46 | level="warning", |
| 47 | ) |
| 48 | self._encode = codecs.getencoder("utf-8") |
| 49 | else: |
| 50 | log.info("Using encoding {0!r} for {1}", encoding, category) |
| 51 | |
| 52 | self._worker_thread = threading.Thread(target=self._worker, name=category) |
| 53 | self._worker_thread.start() |
| 54 | |
| 55 | def __del__(self): |
| 56 | fd = self._fd |