Skip to content

Add some missing logging features #5388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 74 additions & 33 deletions stdlib/logging/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ from collections.abc import Callable, Iterable, Mapping, MutableMapping, Sequenc
from string import Template
from time import struct_time
from types import FrameType, TracebackType
from typing import IO, Any, ClassVar, Optional, Tuple, Type, Union
from typing import IO, Any, ClassVar, Optional, Pattern, Tuple, Type, Union

_SysExcInfoType = Union[Tuple[type, BaseException, Optional[TracebackType]], Tuple[None, None, None]]
_SysExcInfoType = Union[Tuple[Type[BaseException], BaseException, Optional[TracebackType]], Tuple[None, None, None]]
_ExcInfoType = Union[None, bool, _SysExcInfoType, BaseException]
_ArgsType = Union[Tuple[Any, ...], Mapping[str, Any]]
_FilterType = Union[Filter, Callable[[LogRecord], int]]
Expand All @@ -31,7 +31,7 @@ class Filterer(object):
def removeFilter(self, filter: _FilterType) -> None: ...
def filter(self, record: LogRecord) -> bool: ...

class Manager(object):
class Manager(object): # undocumented
root: RootLogger
disable: int
emittedNoHandlerWarning: bool
Expand All @@ -44,14 +44,14 @@ class Manager(object):
def setLogRecordFactory(self, factory: Callable[..., LogRecord]) -> None: ...

class Logger(Filterer):
name: str
level: int
parent: Union[Logger, PlaceHolder]
name: str # undocumented
level: int # undocumented
parent: Optional[Logger] # undocumented
propagate: bool
handlers: list[Handler]
disabled: int
handlers: list[Handler] # undocumented
disabled: bool # undocumented
root: ClassVar[RootLogger] # undocumented
manager: ClassVar[Manager] # undocumented
manager: Manager # undocumented
def __init__(self, name: str, level: _Level = ...) -> None: ...
def setLevel(self, level: _Level) -> None: ...
def isEnabledFor(self, level: int) -> bool: ...
Expand Down Expand Up @@ -204,7 +204,6 @@ class Logger(Filterer):
extra: Optional[dict[str, Any]] = ...,
**kwargs: Any,
) -> None: ...
fatal = critical
def log(
self,
level: int,
Expand Down Expand Up @@ -233,6 +232,7 @@ class Logger(Filterer):
extra: Optional[dict[str, Any]] = ...,
stack_info: bool = ...,
) -> None: ... # undocumented
fatal = critical
def filter(self, record: LogRecord) -> bool: ...
def addHandler(self, hdlr: Handler) -> None: ...
def removeHandler(self, hdlr: Handler) -> None: ...
Expand All @@ -255,6 +255,7 @@ class Logger(Filterer):
sinfo: Optional[str] = ...,
) -> LogRecord: ...
def hasHandlers(self) -> bool: ...
def callHandlers(self, record: LogRecord) -> None: ... # undocumented

CRITICAL: int
FATAL: int
Expand All @@ -271,26 +272,31 @@ class Handler(Filterer):
lock: Optional[threading.Lock] # undocumented
name: Optional[str] # undocumented
def __init__(self, level: _Level = ...) -> None: ...
def get_name(self) -> str: ... # undocumented
def set_name(self, name: str) -> None: ... # undocumented
def createLock(self) -> None: ...
def acquire(self) -> None: ...
def release(self) -> None: ...
def setLevel(self, level: _Level) -> None: ...
def setFormatter(self, fmt: Formatter) -> None: ...
def setFormatter(self, fmt: Optional[Formatter]) -> None: ...
def filter(self, record: LogRecord) -> bool: ...
def flush(self) -> None: ...
def close(self) -> None: ...
def handle(self, record: LogRecord) -> None: ...
def handle(self, record: LogRecord) -> bool: ...
def handleError(self, record: LogRecord) -> None: ...
def format(self, record: LogRecord) -> str: ...
def emit(self, record: LogRecord) -> None: ...

class Formatter:
converter: Callable[[Optional[float]], struct_time]
_fmt: Optional[str]
datefmt: Optional[str]
_style: PercentStyle
_fmt: Optional[str] # undocumented
datefmt: Optional[str] # undocumented
_style: PercentStyle # undocumented
default_time_format: str
default_msec_format: str
if sys.version_info >= (3, 9):
default_msec_format: Optional[str]
else:
default_msec_format: str

if sys.version_info >= (3, 8):
def __init__(
Expand All @@ -303,15 +309,25 @@ class Formatter:
def formatException(self, ei: _SysExcInfoType) -> str: ...
def formatMessage(self, record: LogRecord) -> str: ... # undocumented
def formatStack(self, stack_info: str) -> str: ...
def usesTime(self) -> bool: ... # undocumented

class BufferingFormatter:
linefmt: Formatter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think line format could be a string like: '%(something)s %(something)s'. So, linefmt should be changed to:

    linefmt: Union[str, Formatter]

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically it can be anything with a .format() method, even a string. But that .format() method will be called with only one argument, a log record object. It is possible to create a string that formats them in a useful way, such as "{0.name}: {0.msg}", although that doesn't seem to be how it's intended to be used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the correct fix would be a protocol? We could leave as Any for the moment, though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly I would just use Formatter. It's what the author of the code intended. (This is old code, likely written before str.format was a thing)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the same impression as @Akuli, intended to be a Formatter

def __init__(self, linefmt: Optional[Formatter] = ...) -> None: ...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here:

    def __init__(self, linefmt: Optional[Union[str, Formatter]] = ...) -> None: ...

def formatHeader(self, records: Sequence[LogRecord]) -> str: ...
def formatFooter(self, records: Sequence[LogRecord]) -> str: ...
def format(self, records: Sequence[LogRecord]) -> str: ...

class Filter:
name: str # undocumented
nlen: int # undocumented
def __init__(self, name: str = ...) -> None: ...
def filter(self, record: LogRecord) -> bool: ...

class LogRecord:
args: _ArgsType
asctime: str
created: int
created: float
exc_info: Optional[_SysExcInfoType]
exc_text: Optional[str]
filename: str
Expand All @@ -320,17 +336,17 @@ class LogRecord:
levelno: int
lineno: int
module: str
msecs: int
msecs: float
message: str
msg: str
name: str
pathname: str
process: int
processName: str
relativeCreated: int
process: Optional[int]
processName: Optional[str]
relativeCreated: float
stack_info: Optional[str]
thread: int
threadName: str
thread: Optional[int]
threadName: Optional[str]
def __init__(
self,
name: str,
Expand All @@ -347,8 +363,13 @@ class LogRecord:

class LoggerAdapter:
logger: Logger
extra: Mapping[str, Any]
def __init__(self, logger: Logger, extra: Mapping[str, Any]) -> None: ...
manager: Manager # undocumented
if sys.version_info >= (3, 10):
extra: Optional[Mapping[str, Any]]
def __init__(self, logger: Logger, extra: Optional[Mapping[str, Any]]) -> None: ...
else:
extra: Mapping[str, Any]
def __init__(self, logger: Logger, extra: Mapping[str, Any]) -> None: ...
def process(self, msg: Any, kwargs: MutableMapping[str, Any]) -> tuple[Any, MutableMapping[str, Any]]: ...
if sys.version_info >= (3, 8):
def debug(
Expand Down Expand Up @@ -508,7 +529,7 @@ class LoggerAdapter:
) -> None: ...
def isEnabledFor(self, level: int) -> bool: ...
def getEffectiveLevel(self) -> int: ...
def setLevel(self, level: Union[int, str]) -> None: ...
def setLevel(self, level: _Level) -> None: ...
def hasHandlers(self) -> bool: ...
def _log(
self,
Expand All @@ -519,9 +540,11 @@ class LoggerAdapter:
extra: Optional[dict[str, Any]] = ...,
stack_info: bool = ...,
) -> None: ... # undocumented
@property
def name(self) -> str: ... # undocumented

def getLogger(name: Optional[str] = ...) -> Logger: ...
def getLoggerClass() -> type: ...
def getLoggerClass() -> Type[Logger]: ...
def getLogRecordFactory() -> Callable[..., LogRecord]: ...

if sys.version_info >= (3, 8):
Expand Down Expand Up @@ -675,7 +698,7 @@ else:
def disable(level: int) -> None: ...

def addLevelName(level: int, levelName: str) -> None: ...
def getLevelName(level: Union[int, str]) -> Any: ...
def getLevelName(level: _Level) -> Any: ...
def makeLogRecord(dict: Mapping[str, Any]) -> LogRecord: ...

if sys.version_info >= (3, 8):
Expand Down Expand Up @@ -724,12 +747,24 @@ class FileHandler(StreamHandler):
mode: str # undocumented
encoding: Optional[str] # undocumented
delay: bool # undocumented
def __init__(self, filename: StrPath, mode: str = ..., encoding: Optional[str] = ..., delay: bool = ...) -> None: ...
if sys.version_info >= (3, 9):
errors: Optional[str] # undocumented
def __init__(
self,
filename: StrPath,
mode: str = ...,
encoding: Optional[str] = ...,
delay: bool = ...,
errors: Optional[str] = ...,
) -> None: ...
else:
def __init__(self, filename: StrPath, mode: str = ..., encoding: Optional[str] = ..., delay: bool = ...) -> None: ...
def _open(self) -> IO[Any]: ...

class NullHandler(Handler): ...

class PlaceHolder:
class PlaceHolder: # undocumented
loggerMap: dict[Logger, None]
def __init__(self, alogger: Logger) -> None: ...
def append(self, alogger: Logger) -> None: ...

Expand All @@ -740,18 +775,24 @@ class RootLogger(Logger):

root: RootLogger

class PercentStyle(object):
class PercentStyle(object): # undocumented
default_format: str
asctime_format: str
asctime_search: str
if sys.version_info >= (3, 8):
validation_pattern: Pattern[str]
_fmt: str
def __init__(self, fmt: str) -> None: ...
def usesTime(self) -> bool: ...
if sys.version_info >= (3, 8):
def validate(self) -> None: ...
def format(self, record: Any) -> str: ...

class StrFormatStyle(PercentStyle): ...
class StrFormatStyle(PercentStyle): # undocumented
fmt_spec = Any
field_spec = Any

class StringTemplateStyle(PercentStyle):
class StringTemplateStyle(PercentStyle): # undocumented
_tpl: Template

_STYLES: dict[str, tuple[PercentStyle, str]]
Expand Down
31 changes: 27 additions & 4 deletions stdlib/logging/config.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,39 @@ from _typeshed import AnyPath, StrPath
from collections.abc import Callable
from configparser import RawConfigParser
from threading import Thread
from typing import IO, Any, Optional, Union
from typing import IO, Any, Optional, Pattern, Union

if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal

if sys.version_info >= (3, 7):
_Path = AnyPath
else:
_Path = StrPath

DEFAULT_LOGGING_CONFIG_PORT: int
RESET_ERROR: int # undocumented
IDENTIFIER: Pattern[str] # undocumented

def dictConfig(config: dict[str, Any]) -> None: ...
def fileConfig(
fname: Union[_Path, IO[str], RawConfigParser], defaults: Optional[dict[str, str]] = ..., disable_existing_loggers: bool = ...
) -> None: ...

if sys.version_info >= (3, 10):
def fileConfig(
fname: Union[_Path, IO[str], RawConfigParser],
defaults: Optional[dict[str, str]] = ...,
disable_existing_loggers: bool = ...,
encoding: Optional[str] = ...,
) -> None: ...

else:
def fileConfig(
fname: Union[_Path, IO[str], RawConfigParser],
defaults: Optional[dict[str, str]] = ...,
disable_existing_loggers: bool = ...,
) -> None: ...

def valid_ident(s: str) -> Literal[True]: ... # undocumented
def listen(port: int = ..., verify: Optional[Callable[[bytes], Optional[bytes]]] = ...) -> Thread: ...
def stopListening() -> None: ...
Loading