Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_debug.py107 linesDownload Raw Back to pq
1"""2libpq debugging tools3 4These functionalities are exposed here for convenience, but are not part of5the public interface and are subject to change at any moment.6 7Suggested usage::8 9    import logging10    import psycopg11    from psycopg import pq12    from psycopg.pq._debug import PGconnDebug13 14    logging.basicConfig(level=logging.INFO, format="%(message)s")15    logger = logging.getLogger("psycopg.debug")16    logger.setLevel(logging.INFO)17 18    assert pq.__impl__ == "python"19    pq.PGconn = PGconnDebug20 21    with psycopg.connect("") as conn:22        conn.pgconn.trace(2)23        conn.pgconn.set_trace_flags(24            pq.Trace.SUPPRESS_TIMESTAMPS | pq.Trace.REGRESS_MODE)25        ...26 27"""28 29# Copyright (C) 2022 The Psycopg Team30 31import inspect32import logging33from typing import Any, Callable, Type, TypeVar, TYPE_CHECKING34from functools import wraps35 36from . import PGconn37from .misc import connection_summary38 39if TYPE_CHECKING:40    from . import abc41 42Func = TypeVar("Func", bound=Callable[..., Any])43 44logger = logging.getLogger("psycopg.debug")45 46 47class PGconnDebug:48    """Wrapper for a PQconn logging all its access."""49 50    _Self = TypeVar("_Self", bound="PGconnDebug")51    _pgconn: "abc.PGconn"52 53    def __init__(self, pgconn: "abc.PGconn"):54        super().__setattr__("_pgconn", pgconn)55 56    def __repr__(self) -> str:57        cls = f"{self.__class__.__module__}.{self.__class__.__qualname__}"58        info = connection_summary(self._pgconn)59        return f"<{cls} {info} at 0x{id(self):x}>"60 61    def __getattr__(self, attr: str) -> Any:62        value = getattr(self._pgconn, attr)63        if callable(value):64            return debugging(value)65        else:66            logger.info("PGconn.%s -> %s", attr, value)67            return value68 69    def __setattr__(self, attr: str, value: Any) -> None:70        setattr(self._pgconn, attr, value)71        logger.info("PGconn.%s <- %s", attr, value)72 73    @classmethod74    def connect(cls: Type[_Self], conninfo: bytes) -> _Self:75        return cls(debugging(PGconn.connect)(conninfo))76 77    @classmethod78    def connect_start(cls: Type[_Self], conninfo: bytes) -> _Self:79        return cls(debugging(PGconn.connect_start)(conninfo))80 81    @classmethod82    def ping(self, conninfo: bytes) -> int:83        return debugging(PGconn.ping)(conninfo)84 85 86def debugging(f: Func) -> Func:87    """Wrap a function in order to log its arguments and return value on call."""88 89    @wraps(f)90    def debugging_(*args: Any, **kwargs: Any) -> Any:91        reprs = []92        for arg in args:93            reprs.append(f"{arg!r}")94        for k, v in kwargs.items():95            reprs.append(f"{k}={v!r}")96 97        logger.info("PGconn.%s(%s)", f.__name__, ", ".join(reprs))98        rv = f(*args, **kwargs)99        # Display the return value only if the function is declared to return100        # something else than None.101        ra = inspect.signature(f).return_annotation102        if ra is not None or rv is not None:103            logger.info("    <- %r", rv)104        return rv105 106    return debugging_  # type: ignore107 
codekingpro/portable-devtools · Team Ai