Skip to main content
Glama

propublica-mcp

_output.py•9.12 kB
# SPDX-License-Identifier: MIT OR Apache-2.0 # This file is dual licensed under the terms of the Apache License, Version # 2.0, and the MIT License. See the LICENSE file in the root of this # repository for complete details. """ Logger classes responsible for output. """ from __future__ import annotations import copy import sys import threading from pickle import PicklingError from sys import stderr, stdout from typing import IO, Any, BinaryIO, TextIO WRITE_LOCKS: dict[IO[Any], threading.Lock] = {} def _get_lock_for_file(file: IO[Any]) -> threading.Lock: lock = WRITE_LOCKS.get(file) if lock is None: lock = threading.Lock() WRITE_LOCKS[file] = lock return lock class PrintLogger: """ Print events into a file. Args: file: File to print to. (default: `sys.stdout`) >>> from structlog import PrintLogger >>> PrintLogger().info("hello") hello Useful if you follow `current logging best practices <logging-best-practices>`. Also very useful for testing and examples since `logging` is finicky in doctests. .. versionchanged:: 22.1.0 The implementation has been switched to use `print` for better monkeypatchability. """ def __init__(self, file: TextIO | None = None): self._file = file or stdout self._lock = _get_lock_for_file(self._file) def __getstate__(self) -> str: """ Our __getattr__ magic makes this necessary. """ if self._file is stdout: return "stdout" if self._file is stderr: return "stderr" raise PicklingError( "Only PrintLoggers to sys.stdout and sys.stderr can be pickled." ) def __setstate__(self, state: Any) -> None: """ Our __getattr__ magic makes this necessary. """ if state == "stdout": self._file = stdout else: self._file = stderr self._lock = _get_lock_for_file(self._file) def __deepcopy__(self, memodict: dict[str, object]) -> PrintLogger: """ Create a new PrintLogger with the same attributes. Similar to pickling. """ if self._file not in (stdout, stderr): raise copy.error( "Only PrintLoggers to sys.stdout and sys.stderr " "can be deepcopied." ) newself = self.__class__(self._file) newself._lock = _get_lock_for_file(newself._file) return newself def __repr__(self) -> str: return f"<PrintLogger(file={self._file!r})>" def msg(self, message: str) -> None: """ Print *message*. """ f = self._file if self._file is not stdout else None with self._lock: print(message, file=f, flush=True) log = debug = info = warn = warning = msg fatal = failure = err = error = critical = exception = msg class PrintLoggerFactory: r""" Produce `PrintLogger`\ s. To be used with `structlog.configure`\ 's ``logger_factory``. Args: file: File to print to. (default: `sys.stdout`) Positional arguments are silently ignored. .. versionadded:: 0.4.0 """ def __init__(self, file: TextIO | None = None): self._file = file def __call__(self, *args: Any) -> PrintLogger: return PrintLogger(self._file) class WriteLogger: """ Write events into a file. Args: file: File to print to. (default: `sys.stdout`) >>> from structlog import WriteLogger >>> WriteLogger().info("hello") hello Useful if you follow `current logging best practices <logging-best-practices>`. Also very useful for testing and examples since `logging` is finicky in doctests. A little faster and a little less versatile than `structlog.PrintLogger`. .. versionadded:: 22.1.0 """ def __init__(self, file: TextIO | None = None): self._file = file or sys.stdout self._write = self._file.write self._flush = self._file.flush self._lock = _get_lock_for_file(self._file) def __getstate__(self) -> str: """ Our __getattr__ magic makes this necessary. """ if self._file is stdout: return "stdout" if self._file is stderr: return "stderr" raise PicklingError( "Only WriteLoggers to sys.stdout and sys.stderr can be pickled." ) def __setstate__(self, state: Any) -> None: """ Our __getattr__ magic makes this necessary. """ if state == "stdout": self._file = stdout else: self._file = stderr self._lock = _get_lock_for_file(self._file) def __deepcopy__(self, memodict: dict[str, object]) -> WriteLogger: """ Create a new WriteLogger with the same attributes. Similar to pickling. """ if self._file not in (sys.stdout, sys.stderr): raise copy.error( "Only WriteLoggers to sys.stdout and sys.stderr " "can be deepcopied." ) newself = self.__class__(self._file) newself._write = newself._file.write newself._flush = newself._file.flush newself._lock = _get_lock_for_file(newself._file) return newself def __repr__(self) -> str: return f"<WriteLogger(file={self._file!r})>" def msg(self, message: str) -> None: """ Write and flush *message*. """ with self._lock: self._write(message + "\n") self._flush() log = debug = info = warn = warning = msg fatal = failure = err = error = critical = exception = msg class WriteLoggerFactory: r""" Produce `WriteLogger`\ s. To be used with `structlog.configure`\ 's ``logger_factory``. Args: file: File to print to. (default: `sys.stdout`) Positional arguments are silently ignored. .. versionadded:: 22.1.0 """ def __init__(self, file: TextIO | None = None): self._file = file def __call__(self, *args: Any) -> WriteLogger: return WriteLogger(self._file) class BytesLogger: r""" Writes bytes into a file. Args: file: File to print to. (default: `sys.stdout`\ ``.buffer``) Useful if you follow `current logging best practices <logging-best-practices>` together with a formatter that returns bytes (e.g. `orjson <https://github.com/ijl/orjson>`_). .. versionadded:: 20.2.0 """ __slots__ = ("_file", "_flush", "_lock", "_write") def __init__(self, file: BinaryIO | None = None): self._file = file or sys.stdout.buffer self._write = self._file.write self._flush = self._file.flush self._lock = _get_lock_for_file(self._file) def __getstate__(self) -> str: """ Our __getattr__ magic makes this necessary. """ if self._file is sys.stdout.buffer: return "stdout" if self._file is sys.stderr.buffer: return "stderr" raise PicklingError( "Only BytesLoggers to sys.stdout and sys.stderr can be pickled." ) def __setstate__(self, state: Any) -> None: """ Our __getattr__ magic makes this necessary. """ if state == "stdout": self._file = sys.stdout.buffer else: self._file = sys.stderr.buffer self._write = self._file.write self._flush = self._file.flush self._lock = _get_lock_for_file(self._file) def __deepcopy__(self, memodict: dict[str, object]) -> BytesLogger: """ Create a new BytesLogger with the same attributes. Similar to pickling. """ if self._file not in (sys.stdout.buffer, sys.stderr.buffer): raise copy.error( "Only BytesLoggers to sys.stdout and sys.stderr " "can be deepcopied." ) newself = self.__class__(self._file) newself._write = newself._file.write newself._flush = newself._file.flush newself._lock = _get_lock_for_file(newself._file) return newself def __repr__(self) -> str: return f"<BytesLogger(file={self._file!r})>" def msg(self, message: bytes) -> None: """ Write *message*. """ with self._lock: self._write(message + b"\n") self._flush() log = debug = info = warn = warning = msg fatal = failure = err = error = critical = exception = msg class BytesLoggerFactory: r""" Produce `BytesLogger`\ s. To be used with `structlog.configure`\ 's ``logger_factory``. Args: file: File to print to. (default: `sys.stdout`\ ``.buffer``) Positional arguments are silently ignored. .. versionadded:: 20.2.0 """ __slots__ = ("_file",) def __init__(self, file: BinaryIO | None = None): self._file = file def __call__(self, *args: Any) -> BytesLogger: return BytesLogger(self._file)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/asachs01/propublica-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server