From 2a6b4c051fd78fe1e2082ac0443447132143730d Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Fri, 8 Sep 2023 10:35:00 +0200 Subject: [PATCH] Make docstrings more readable by switching to Napoleon --- .github/CONTRIBUTING.md | 10 +- docs/api.rst | 1 + src/structlog/_base.py | 74 +++++++++----- src/structlog/_config.py | 94 ++++++++++------- src/structlog/_frames.py | 10 +- src/structlog/_log_levels.py | 13 ++- src/structlog/_output.py | 40 +++++--- src/structlog/_utils.py | 10 +- src/structlog/dev.py | 11 +- src/structlog/processors.py | 189 +++++++++++++++++++++-------------- src/structlog/stdlib.py | 169 +++++++++++++++++-------------- src/structlog/testing.py | 10 +- src/structlog/threadlocal.py | 14 ++- src/structlog/tracebacks.py | 60 ++++++----- src/structlog/twisted.py | 25 +++-- src/structlog/typing.py | 31 +++--- tests/test_processors.py | 43 ++++---- tests/test_stdlib.py | 4 - 18 files changed, 488 insertions(+), 320 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 384a1454..51bfcdbc 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -121,16 +121,20 @@ But it's way more comfortable to run it locally and catch avoidable errors befor ## Code - Obey [PEP 8](https://www.python.org/dev/peps/pep-0008/) and [PEP 257](https://www.python.org/dev/peps/pep-0257/). - We use the `"""`-on-separate-lines style for docstrings: + We use the `"""`-on-separate-lines style for docstrings with [Napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html)-style API documentation: ```python def func(x: str) -> str: """ Do something. - :param str x: A very important parameter. + Arguments: - :rtype: str + x: A very important parameter. + + Returns: + + A very important return value. """ ``` - If you add or change public APIs, tag the docstring using `.. versionadded:: 16.0.0 WHAT` or `.. versionchanged:: 16.2.0 WHAT`. diff --git a/docs/api.rst b/docs/api.rst index f58f50f0..5a911533 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -292,6 +292,7 @@ API Reference :members: bind, unbind, try_unbind, new, debug, info, warning, warn, error, critical, exception, log, adebug, ainfo, awarning, aerror, acritical, aexception, alog .. autoclass:: AsyncBoundLogger + :members: sync_bl .. autoclass:: LoggerFactory :members: __call__ diff --git a/src/structlog/_base.py b/src/structlog/_base.py index 6822c505..9fc6e7ce 100644 --- a/src/structlog/_base.py +++ b/src/structlog/_base.py @@ -78,7 +78,9 @@ def unbind(self, *keys: str) -> BoundLoggerBase: """ Return a new logger with *keys* removed from the context. - :raises KeyError: If the key is not part of the context. + Raises: + + KeyError: If the key is not part of the context. """ bl = self.bind() for key in keys: @@ -121,19 +123,29 @@ def _process_event( Call it to combine your *event* and *context* into an event_dict and process using the processor chain. - :param method_name: The name of the logger method. Is passed into - the processors. - :param event: The event -- usually the first positional argument to a - logger. - :param event_kw: Additional event keywords. For example if someone - calls ``log.info("foo", bar=42)``, *event* would to be ``"foo"`` - and *event_kw* ``{"bar": 42}``. + Arguments: + + method_name: + The name of the logger method. Is passed into the processors. + + event: + The event -- usually the first positional argument to a logger. + + event_kw: + Additional event keywords. For example if someone calls + ``log.info("foo", bar=42)``, *event* would to be ``"foo"`` and + *event_kw* ``{"bar": 42}``. + + Raises: + + structlog.DropEvent: if log entry should be dropped. - :raises: `structlog.DropEvent` if log entry should be dropped. - :raises: `ValueError` if the final processor doesn't return a - str, bytes, bytearray, tuple, or a dict. + ValueError: + if the final processor doesn't return a str, bytes, bytearray, + tuple, or a dict. - :returns: `tuple` of ``(*args, **kw)`` + Returns: + `tuple` of ``(*args, **kw)`` .. note:: @@ -169,7 +181,10 @@ def _process_event( if isinstance(event_dict, dict): return (), event_dict - msg = "Last processor didn't return an appropriate value. Valid return values are a dict, a tuple of (args, kwargs), bytes, or a str." + msg = ( + "Last processor didn't return an appropriate value. " + "Valid return values are a dict, a tuple of (args, kwargs), bytes, or a str." + ) raise ValueError(msg) def _proxy_to_logger( @@ -182,14 +197,20 @@ def _proxy_to_logger( handling :exc:`structlog.DropEvent`, and finally calls *method_name* on :attr:`_logger` with the result. - :param method_name: The name of the method that's going to get - called. Technically it should be identical to the method the - user called because it also get passed into processors. - :param event: The event -- usually the first positional argument to a - logger. - :param event_kw: Additional event keywords. For example if someone - calls ``log.info("foo", bar=42)``, *event* would to be ``"foo"`` - and *event_kw* ``{"bar": 42}``. + Arguments: + + method_name: + The name of the method that's going to get called. Technically + it should be identical to the method the user called because it + also get passed into processors. + + event: + The event -- usually the first positional argument to a logger. + + event_kw: + Additional event keywords. For example if someone calls + ``log.info("foo", bar=42)``, *event* would to be ``"foo"`` and + *event_kw* ``{"bar": 42}``. .. note:: @@ -211,12 +232,15 @@ def get_context(bound_logger: BindableLogger) -> Context: The type of *bound_logger* and the type returned depend on your configuration. - :param bound_logger: The bound logger whose context you want. + Arguments: + + bound_logger: The bound logger whose context you want. + + Returns: - :returns: The *actual* context from *bound_logger*. It is *not* copied - first. + The *actual* context from *bound_logger*. It is *not* copied first. - .. versionadded:: 20.2 + .. versionadded:: 20.2.0 """ # This probably will get more complicated in the future. return bound_logger._context diff --git a/src/structlog/_config.py b/src/structlog/_config.py index 05de0ca5..718bcfb6 100644 --- a/src/structlog/_config.py +++ b/src/structlog/_config.py @@ -81,7 +81,7 @@ def is_configured() -> bool: If `False`, *structlog* is running with builtin defaults. - .. versionadded: 18.1 + .. versionadded: 18.1.0 """ return _CONFIG.is_configured @@ -94,7 +94,7 @@ def get_config() -> dict[str, Any]: Changes to the returned dictionary do *not* affect *structlog*. - .. versionadded: 18.1 + .. versionadded: 18.1.0 """ return { "processors": _CONFIG.default_processors, @@ -114,12 +114,18 @@ def get_logger(*args: Any, **initial_values: Any) -> Any: >>> log.info("hello", x=42) y=23 x=42 event='hello' - :param args: *Optional* positional arguments that are passed unmodified to - the logger factory. Therefore it depends on the factory what they - mean. - :param initial_values: Values that are used to pre-populate your contexts. + Arguments: - :returns: A proxy that creates a correctly configured bound logger when + args: + *Optional* positional arguments that are passed unmodified to the + logger factory. Therefore it depends on the factory what they + mean. + + initial_values: Values that are used to pre-populate your contexts. + + Returns: + + A proxy that creates a correctly configured bound logger when necessary. The type of that bound logger depends on your configuration and is `structlog.BoundLogger` by default. @@ -128,8 +134,7 @@ def get_logger(*args: Any, **initial_values: Any) -> Any: If you prefer CamelCase, there's an alias for your reading pleasure: `structlog.getLogger`. - .. versionadded:: 0.4.0 - *args* + .. versionadded:: 0.4.0 *args* """ return wrap_logger(None, logger_factory_args=args, **initial_values) @@ -158,23 +163,28 @@ def wrap_logger( Default values for *processors*, *wrapper_class*, and *context_class* can be set using `configure`. - If you set an attribute here, `configure` calls have *no* effect for - the *respective* attribute. + If you set an attribute here, `configure` calls have *no* effect for the + *respective* attribute. In other words: selective overwriting of the defaults while keeping some *is* possible. - :param initial_values: Values that are used to pre-populate your contexts. - :param logger_factory_args: Values that are passed unmodified as - ``*logger_factory_args`` to the logger factory if not `None`. + Arguments: + + initial_values: Values that are used to pre-populate your contexts. - :returns: A proxy that creates a correctly configured bound logger when + logger_factory_args: + Values that are passed unmodified as ``*logger_factory_args`` to + the logger factory if not `None`. + + Returns: + + A proxy that creates a correctly configured bound logger when necessary. See `configure` for the meaning of the rest of the arguments. - .. versionadded:: 0.4.0 - *logger_factory_args* + .. versionadded:: 0.4.0 *logger_factory_args* """ return BoundLoggerLazyProxy( logger, @@ -207,22 +217,29 @@ def configure( Use `reset_defaults` to undo your changes. - :param processors: The processor chain. See :doc:`processors` for details. - :param wrapper_class: Class to use for wrapping loggers instead of - `structlog.BoundLogger`. See `standard-library`, :doc:`twisted`, and - `custom-wrappers`. - :param context_class: Class to be used for internal context keeping. The - default is a `dict` and since dictionaries are ordered as of Python - 3.6, there's few reasons to change this option. - :param logger_factory: Factory to be called to create a new logger that - shall be wrapped. - :param cache_logger_on_first_use: `wrap_logger` doesn't return an actual - wrapped logger but a proxy that assembles one when it's first used. If - this option is set to `True`, this assembled logger is cached. See - `performance`. - - .. versionadded:: 0.3.0 - *cache_logger_on_first_use* + Arguments: + + processors: The processor chain. See :doc:`processors` for details. + + wrapper_class: + Class to use for wrapping loggers instead of + `structlog.BoundLogger`. See `standard-library`, :doc:`twisted`, + and `custom-wrappers`. + + context_class: + Class to be used for internal context keeping. The default is a + `dict` and since dictionaries are ordered as of Python 3.6, there's + few reasons to change this option. + + logger_factory: + Factory to be called to create a new logger that shall be wrapped. + + cache_logger_on_first_use: + `wrap_logger` doesn't return an actual wrapped logger but a proxy + that assembles one when it's first used. If this option is set to + `True`, this assembled logger is cached. See `performance`. + + .. versionadded:: 0.3.0 *cache_logger_on_first_use* """ _CONFIG.is_configured = True @@ -251,7 +268,9 @@ def configure_once( It does *not* matter whether it was configured using `configure` or `configure_once` before. - Raises a `RuntimeWarning` if repeated configuration is attempted. + Raises: + + RuntimeWarning: if repeated configuration is attempted. """ if not _CONFIG.is_configured: configure( @@ -290,11 +309,10 @@ class BoundLoggerLazyProxy: The only points where a bound logger changes state are ``bind()``, ``unbind()``, and ``new()`` and that return the actual ``BoundLogger``. - If and only if configuration says so, that actual bound logger is - cached on first usage. + If and only if configuration says so, that actual bound logger is cached on + first usage. - .. versionchanged:: 0.4.0 - Added support for *logger_factory_args*. + .. versionchanged:: 0.4.0 Added support for *logger_factory_args*. """ def __init__( diff --git a/src/structlog/_frames.py b/src/structlog/_frames.py index 7db6a486..7a5fb6c3 100644 --- a/src/structlog/_frames.py +++ b/src/structlog/_frames.py @@ -40,10 +40,14 @@ def _find_first_app_frame_and_name( """ Remove all intra-structlog calls and return the relevant app frame. - :param additional_ignores: Additional names with which the first frame must - not start. + Arguments: - :returns: tuple of (frame, name) + additional_ignores: + Additional names with which the first frame must not start. + + Returns: + + tuple of (frame, name) """ ignores = ["structlog"] + (additional_ignores or []) f = sys._getframe() diff --git a/src/structlog/_log_levels.py b/src/structlog/_log_levels.py index 8a3a384f..b2e721b6 100644 --- a/src/structlog/_log_levels.py +++ b/src/structlog/_log_levels.py @@ -128,11 +128,14 @@ def make_filtering_bound_logger(min_level: int) -> type[FilteringBoundLogger]: - You *can* have (much) more fine-grained filtering by :ref:`writing a simple processor `. - :param min_level: The log level as an integer. You can use the constants - from `logging` like ``logging.INFO`` or pass the values directly. See - `this table from the logging docs - `_ for possible - values. + Arguments: + + min_level: + The log level as an integer. You can use the constants from + `logging` like ``logging.INFO`` or pass the values directly. See + `this table from the logging docs + `_ for + possible values. .. versionadded:: 20.2.0 .. versionchanged:: 21.1.0 The returned loggers are now pickleable. diff --git a/src/structlog/_output.py b/src/structlog/_output.py index 64dfb5e8..4c5efbf4 100644 --- a/src/structlog/_output.py +++ b/src/structlog/_output.py @@ -36,19 +36,21 @@ class PrintLogger: """ Print events into a file. - :param file: File to print to. (default: `sys.stdout`) + Arguments: + + file: File to print to. (default: `sys.stdout`) >>> from structlog import PrintLogger >>> PrintLogger().info("hello") hello - Useful if you follow - `current logging best practices `. + Useful if you follow `current logging best practices + `. Also very useful for testing and examples since `logging` is finicky in doctests. - .. versionchanged:: 22.1 + .. versionchanged:: 22.1.0 The implementation has been switched to use `print` for better monkeypatchability. """ @@ -120,7 +122,9 @@ class PrintLoggerFactory: To be used with `structlog.configure`\ 's ``logger_factory``. - :param file: File to print to. (default: `sys.stdout`) + Arguments: + + file: File to print to. (default: `sys.stdout`) Positional arguments are silently ignored. @@ -138,7 +142,9 @@ class WriteLogger: """ Write events into a file. - :param file: File to print to. (default: `sys.stdout`) + Arguments: + + file: File to print to. (default: `sys.stdout`) >>> from structlog import WriteLogger >>> WriteLogger().info("hello") @@ -152,7 +158,7 @@ class WriteLogger: A little faster and a little less versatile than `structlog.PrintLogger`. - .. versionadded:: 22.1 + .. versionadded:: 22.1.0 """ def __init__(self, file: TextIO | None = None): @@ -226,11 +232,13 @@ class WriteLoggerFactory: To be used with `structlog.configure`\ 's ``logger_factory``. - :param file: File to print to. (default: `sys.stdout`) + Arguments: + + file: File to print to. (default: `sys.stdout`) Positional arguments are silently ignored. - .. versionadded:: 22.1 + .. versionadded:: 22.1.0 """ def __init__(self, file: TextIO | None = None): @@ -244,12 +252,12 @@ class BytesLogger: r""" Writes bytes into a file. - :param file: File to print to. (default: `sys.stdout`\ ``.buffer``) + Arguments: + file: File to print to. (default: `sys.stdout`\ ``.buffer``) - Useful if you follow - `current logging best practices ` together with - a formatter that returns bytes (e.g. `orjson - `_). + Useful if you follow `current logging best practices + ` together with a formatter that returns bytes + (e.g. `orjson `_). .. versionadded:: 20.2.0 """ @@ -328,7 +336,9 @@ class BytesLoggerFactory: To be used with `structlog.configure`\ 's ``logger_factory``. - :param file: File to print to. (default: `sys.stdout`\ ``.buffer``) + Arguments: + + file: File to print to. (default: `sys.stdout`\ ``.buffer``) Positional arguments are silently ignored. diff --git a/src/structlog/_utils.py b/src/structlog/_utils.py index 28004e15..f03aeaea 100644 --- a/src/structlog/_utils.py +++ b/src/structlog/_utils.py @@ -20,9 +20,13 @@ def until_not_interrupted(f: Callable[..., Any], *args: Any, **kw: Any) -> Any: """ Retry until *f* succeeds or an exception that isn't caused by EINTR occurs. - :param f: A callable like a function. - :param *args: Positional arguments for *f*. - :param **kw: Keyword arguments for *f*. + Arguments: + + f: A callable like a function. + + *args: Positional arguments for *f*. + + **kw: Keyword arguments for *f*. """ while True: try: diff --git a/src/structlog/dev.py b/src/structlog/dev.py index 1bc9bbf0..5561d24c 100644 --- a/src/structlog/dev.py +++ b/src/structlog/dev.py @@ -515,11 +515,14 @@ def get_default_level_styles(colors: bool = True) -> Any: home-grown :func:`~structlog.stdlib.add_log_level` you could do:: my_styles = ConsoleRenderer.get_default_level_styles() - my_styles["EVERYTHING_IS_ON_FIRE"] = my_styles["critical"] - renderer = ConsoleRenderer(level_styles=my_styles) + my_styles["EVERYTHING_IS_ON_FIRE"] = my_styles["critical"] renderer + = ConsoleRenderer(level_styles=my_styles) - :param colors: Whether to use colorful styles. This must match the - *colors* parameter to `ConsoleRenderer`. Default: `True`. + Arguments: + + colors: + Whether to use colorful styles. This must match the *colors* + parameter to `ConsoleRenderer`. Default: `True`. """ styles: Styles styles = _ColorfulStyles if colors else _PlainStyles diff --git a/src/structlog/processors.py b/src/structlog/processors.py index 61b7216a..3d29faa9 100644 --- a/src/structlog/processors.py +++ b/src/structlog/processors.py @@ -63,16 +63,21 @@ class KeyValueRenderer: """ Render ``event_dict`` as a list of ``Key=repr(Value)`` pairs. - :param sort_keys: Whether to sort keys when formatting. - :param key_order: List of keys that should be rendered in this exact - order. Missing keys will be rendered as ``None``, extra keys depending - on *sort_keys* and the dict class. - :param drop_missing: When ``True``, extra keys in *key_order* will be - dropped rather than rendered as ``None``. - :param repr_native_str: When ``True``, :func:`repr()` is also applied - to native strings. - Setting this to ``False`` is useful if you want to have human-readable - non-ASCII output on Python 2. + Arguments: + + sort_keys: Whether to sort keys when formatting. + + key_order: + List of keys that should be rendered in this exact order. Missing + keys will be rendered as ``None``, extra keys depending on + *sort_keys* and the dict class. + + drop_missing: + When ``True``, extra keys in *key_order* will be dropped rather + than rendered as ``None``. + + repr_native_str: + When ``True``, :func:`repr()` is also applied to native strings. .. versionadded:: 0.2.0 *key_order* .. versionadded:: 16.1.0 *drop_missing* @@ -114,17 +119,27 @@ class LogfmtRenderer: .. _logfmt: https://brandur.org/logfmt - :param sort_keys: Whether to sort keys when formatting. - :param key_order: List of keys that should be rendered in this exact - order. Missing keys are rendered with empty values, extra keys - depending on *sort_keys* and the dict class. - :param drop_missing: When ``True``, extra keys in *key_order* will be - dropped rather than rendered with empty values. - :param bool_as_flag: When ``True``, render ``{"flag": True}`` as - ``flag``, instead of ``flag=true``. ``{"flag": False}`` is - always rendered as ``flag=false``. + Arguments: + + sort_keys: Whether to sort keys when formatting. + + key_order: + List of keys that should be rendered in this exact order. Missing + keys are rendered with empty values, extra keys depending on + *sort_keys* and the dict class. + + drop_missing: + When ``True``, extra keys in *key_order* will be dropped rather + than rendered with empty values. - :raises ValueError: If a key contains non printable or space characters. + bool_as_flag: + When ``True``, render ``{"flag": True}`` as ``flag``, instead of + ``flag=true``. ``{"flag": False}`` is always rendered as + ``flag=false``. + + Raises: + + ValueError: If a key contains non printable or space characters. .. versionadded:: 21.5.0 """ @@ -222,14 +237,16 @@ class UnicodeEncoder: """ Encode unicode values in ``event_dict``. - :param encoding: Encoding to encode to (default: ``"utf-8"``). - :param errors: How to cope with encoding errors (default - ``"backslashreplace"``). + Arguments: + + encoding: Encoding to encode to (default: ``"utf-8"``). - Useful if you're running Python 2 as otherwise ``u"abc"`` will be rendered - as ``'u"abc"'``. + errors: + How to cope with encoding errors (default ``"backslashreplace"``). Just put it in the processor chain before the renderer. + + .. note:: Not very useful in a Python 3-only world. """ _encoding: str @@ -255,12 +272,13 @@ class UnicodeDecoder: """ Decode byte string values in ``event_dict``. - :param encoding: Encoding to decode from (default: ``"utf-8"``). - :param errors: How to cope with encoding errors (default: - ``"replace"``). + Arguments: + + encoding: Encoding to decode from (default: ``"utf-8"``). + + errors: How to cope with encoding errors (default: ``"replace"``). - Useful if you're running Python 3 as otherwise ``b"abc"`` will be rendered - as ``'b"abc"'``. + Useful to prevent ``b"abc"`` being rendered as as ``'b"abc"'``. Just put it in the processor chain before the renderer. @@ -290,24 +308,23 @@ class JSONRenderer: """ Render the ``event_dict`` using ``serializer(event_dict, **dumps_kw)``. - :param dumps_kw: Are passed unmodified to *serializer*. If *default* - is passed, it will disable support for ``__structlog__``-based - serialization. - :param serializer: A :func:`json.dumps`-compatible callable that - will be used to format the string. This can be used to use alternative - JSON encoders like `orjson `__ or - `RapidJSON `_ (default: - :func:`json.dumps`). + Arguments: - .. versionadded:: 0.2.0 - Support for ``__structlog__`` serialization method. + dumps_kw: + Are passed unmodified to *serializer*. If *default* is passed, it + will disable support for ``__structlog__``-based serialization. - .. versionadded:: 15.4.0 - *serializer* parameter. + serializer: + A :func:`json.dumps`-compatible callable that will be used to + format the string. This can be used to use alternative JSON + encoders like `orjson `__ or + `RapidJSON `_ + (default: :func:`json.dumps`). + .. versionadded:: 0.2.0 Support for ``__structlog__`` serialization method. + .. versionadded:: 15.4.0 *serializer* parameter. .. versionadded:: 18.2.0 Serializer's *default* parameter can be overwritten now. - """ def __init__( @@ -365,13 +382,16 @@ class ExceptionRenderer: 3. If the value true but no tuple, obtain exc_info ourselves and render that. - If there is no ``exc_info`` key, the *event_dict* is not touched. - This behavior is analogue to the one of the stdlib's logging. + If there is no ``exc_info`` key, the *event_dict* is not touched. This + behavior is analogue to the one of the stdlib's logging. + + Arguments: - :param exception_formatter: A callable that is used to format the exception - from the ``exc_info`` field. + exception_formatter: + A callable that is used to format the exception from the + ``exc_info`` field. - .. versionadded:: 22.1 + .. versionadded:: 22.1.0 """ def __init__( @@ -419,7 +439,7 @@ def __call__( The treatment of the ``exc_info`` key is identical to `format_exc_info`. -.. versionadded:: 22.1 +.. versionadded:: 22.1.0 """ @@ -427,13 +447,18 @@ class TimeStamper: """ Add a timestamp to ``event_dict``. - :param fmt: strftime format string, or ``"iso"`` for `ISO 8601 - `_, or `None` for a `UNIX - timestamp `_. - :param utc: Whether timestamp should be in UTC or local time. - :param key: Target key in *event_dict* for added timestamps. + Arguments: + + fmt: + strftime format string, or ``"iso"`` for `ISO 8601 + `_, or `None` for a `UNIX + timestamp `_. + + utc: Whether timestamp should be in UTC or local time. + + key: Target key in *event_dict* for added timestamps. - .. versionchanged:: 19.2 Can be pickled now. + .. versionchanged:: 19.2.0 Can be pickled now. """ __slots__ = ("_stamper", "fmt", "utc", "key") @@ -571,13 +596,15 @@ class ExceptionPrettyPrinter: """ Pretty print exceptions and remove them from the ``event_dict``. - :param file: Target file for output (default: ``sys.stdout``). + Arguments: + + file: Target file for output (default: ``sys.stdout``). This processor is mostly for development and testing so you can read exceptions properly formatted. - It behaves like `format_exc_info` except it removes the exception - data from the event dictionary after printing it. + It behaves like `format_exc_info` except it removes the exception data from + the event dictionary after printing it. It's tolerant to having `format_exc_info` in front of itself in the processor chain but doesn't require it. In other words, it handles both @@ -622,13 +649,17 @@ class StackInfoRenderer: involving an exception and works analogously to the *stack_info* argument of the Python standard library logging. - :param additional_ignores: By default, stack frames coming from - *structlog* are ignored. With this argument you can add additional - names that are ignored, before the stack starts being rendered. They - are matched using ``startswith()``, so they don't have to match - exactly. The names are used to find the first relevant name, therefore - once a frame is found that doesn't start with *structlog* or one of - *additional_ignores*, **no filtering** is applied to subsequent frames. + Arguments: + + additional_ignores: + By default, stack frames coming from *structlog* are ignored. With + this argument you can add additional names that are ignored, before + the stack starts being rendered. They are matched using + ``startswith()``, so they don't have to match exactly. The names + are used to find the first relevant name, therefore once a frame is + found that doesn't start with *structlog* or one of + *additional_ignores*, **no filtering** is applied to subsequent + frames. .. versionadded:: 0.4.0 .. versionadded:: 22.1.0 *additional_ignores* @@ -706,15 +737,18 @@ class CallsiteParameterAdder: The keys used for callsite parameters in the event dictionary are the string values of `CallsiteParameter` enum members. - :param parameters: - A collection of `CallsiteParameter` values that should be added to the - event dictionary. + Arguments: + + parameters: + A collection of `CallsiteParameter` values that should be added to + the event dictionary. - :param additional_ignores: - Additional names with which a stack frame's module name must not - start for it to be considered when determening the callsite. + additional_ignores: + Additional names with which a stack frame's module name must not + start for it to be considered when determening the callsite. .. note:: + When used with `structlog.stdlib.ProcessorFormatter` the most efficient configuration is to either use this processor in ``foreign_pre_chain`` of `structlog.stdlib.ProcessorFormatter` and in ``processors`` of @@ -838,12 +872,15 @@ class EventRenamer: some processors may rely on the presence and meaning of the ``event`` key. - :param to: Rename ``event_dict["event"]`` to ``event_dict[to]`` - :param replace_by: Rename ``event_dict[replace_by]`` to - ``event_dict["event"]``. *replace_by* missing from ``event_dict`` is - handled gracefully. + Arguments: + + to: Rename ``event_dict["event"]`` to ``event_dict[to]`` + + replace_by: + Rename ``event_dict[replace_by]`` to ``event_dict["event"]``. + *replace_by* missing from ``event_dict`` is handled gracefully. - .. versionadded:: 22.1 + .. versionadded:: 22.1.0 See also the :ref:`rename-event` recipe. """ diff --git a/src/structlog/stdlib.py b/src/structlog/stdlib.py index ea6a7124..9de32fd9 100644 --- a/src/structlog/stdlib.py +++ b/src/structlog/stdlib.py @@ -55,16 +55,18 @@ def recreate_defaults(*, log_level: int | None = logging.NOTSET) -> None: As with vanilla defaults, the backwards-compatibility guarantees don't apply to the settings applied here. - :param log_level: If `None`, don't configure standard library logging **at - all**. + Arguments: - Otherwise configure it to log to `sys.stdout` at *log_level* - (``logging.NOTSET`` being the default). + log_level: + If `None`, don't configure standard library logging **at all**. - If you need more control over `logging`, pass `None` here and configure - it yourself. + Otherwise configure it to log to `sys.stdout` at *log_level* + (``logging.NOTSET`` being the default). - .. versionadded:: 22.1 + If you need more control over `logging`, pass `None` here and + configure it yourself. + + .. versionadded:: 22.1.0 """ if log_level is not None: kw = {"force": True} @@ -147,7 +149,9 @@ def unbind(self, *keys: str) -> BoundLogger: """ Return a new logger with *keys* removed from the context. - :raises KeyError: If the key is not part of the context. + Raises: + + KeyError: If the key is not part of the context. """ return super().unbind(*keys) # type: ignore[return-value] @@ -484,15 +488,16 @@ class AsyncBoundLogger: Only available for Python 3.7 and later. - :ivar structlog.stdlib.BoundLogger sync_bl: The wrapped synchronous logger. - It is useful to be able to log synchronously occasionally. - .. versionadded:: 20.2.0 .. versionchanged:: 20.2.0 fix _dispatch_to_sync contextvars usage + .. deprecated:: 23.1.0 + Use the regular `BoundLogger` with its a-prefixed methods instead. """ __slots__ = ("sync_bl", "_loop") + #: The wrapped synchronous logger. It is useful to be able to log + #: synchronously occasionally. sync_bl: BoundLogger # Blatant lie, we use a property for _context. Need this for Protocol @@ -637,11 +642,14 @@ class LoggerFactory: >>> from structlog.stdlib import LoggerFactory >>> configure(logger_factory=LoggerFactory()) - :param ignore_frame_names: When guessing the name of a logger, skip frames - whose names *start* with one of these. For example, in pyramid - applications you'll want to set it to - ``["venusian", "pyramid.config"]``. This argument is - called *additional_ignores* in other APIs throughout *structlog*. + Arguments: + + ignore_frame_names: + When guessing the name of a logger, skip frames whose names *start* + with one of these. For example, in pyramid applications you'll + want to set it to ``["venusian", "pyramid.config"]``. This argument + is called *additional_ignores* in other APIs throughout + *structlog*. """ def __init__(self, ignore_frame_names: list[str] | None = None): @@ -793,12 +801,15 @@ class ExtraAdder: This processor can be used for adding data passed in the ``extra`` parameter of the `logging` module's log methods to the event dictionary. - :param allow: An optional collection of attributes that, if present in - `logging.LogRecord` objects, will be copied to event dictionaries. + Arguments: + + allow: + An optional collection of attributes that, if present in + `logging.LogRecord` objects, will be copied to event dictionaries. - If ``allow`` is None all attributes of `logging.LogRecord` objects that - do not exist on a standard `logging.LogRecord` object will be copied to - event dictionaries. + If ``allow`` is None all attributes of `logging.LogRecord` objects + that do not exist on a standard `logging.LogRecord` object will be + copied to event dictionaries. .. versionadded:: 21.5.0 """ @@ -855,8 +866,9 @@ def render_to_log_kwargs( This allows you to defer formatting to `logging`. .. versionadded:: 17.1.0 - .. versionchanged:: 22.1.0 ``exc_info``, ``stack_info``, and ``stackLevel`` - are passed as proper kwargs and not put into ``extra``. + .. versionchanged:: 22.1.0 + ``exc_info``, ``stack_info``, and ``stackLevel`` are passed as proper + kwargs and not put into ``extra``. """ return { "msg": event_dict.pop("event"), @@ -881,56 +893,67 @@ class ProcessorFormatter(logging.Formatter): Please refer to :ref:`processor-formatter` for examples. - :param foreign_pre_chain: - If not `None`, it is used as a processor chain that is applied to - **non**-*structlog* log entries before the event dictionary is passed - to *processors*. (default: `None`) - :param processors: - A chain of *structlog* processors that is used to process **all** log - entries. The last one must render to a `str` which then gets passed on - to `logging` for output. - - Compared to *structlog*'s regular processor chains, there's a few - differences: - - - The event dictionary contains two additional keys: - - #. ``_record``: a `logging.LogRecord` that either was created using - `logging` APIs, **or** is a wrapped *structlog* log entry - created by `wrap_for_formatter`. - #. ``_from_structlog``: a `bool` that indicates whether or not - ``_record`` was created by a *structlog* logger. - - Since you most likely don't want ``_record`` and - ``_from_structlog`` in your log files, we've added - the static method `remove_processors_meta` to ``ProcessorFormatter`` - that you can add just before your renderer. - - - Since this is a `logging` *formatter*, raising `structlog.DropEvent` - will crash your application. - - :param keep_exc_info: ``exc_info`` on `logging.LogRecord`\ s is - added to the ``event_dict`` and removed afterwards. Set this to - ``True`` to keep it on the `logging.LogRecord`. (default: False) - :param keep_stack_info: Same as *keep_exc_info* except for ``stack_info``. - (default: False) - :param logger: Logger which we want to push through the *structlog* - processor chain. This parameter is necessary for some of the - processors like `filter_by_level`. (default: None) - :param pass_foreign_args: If True, pass a foreign log record's - ``args`` attribute to the ``event_dict`` under ``positional_args`` key. - (default: False) - :param processor: - A single *structlog* processor used for rendering the event - dictionary before passing it off to `logging`. Must return a `str`. - The event dictionary does **not** contain ``_record`` and - ``_from_structlog``. - - This parameter exists for historic reasons. Please consider using - *processors* instead. - - :raises TypeError: If both or neither *processor* and *processors* are - passed. + Arguments: + + foreign_pre_chain: + If not `None`, it is used as a processor chain that is applied to + **non**-*structlog* log entries before the event dictionary is + passed to *processors*. (default: `None`) + + processors: + A chain of *structlog* processors that is used to process **all** + log entries. The last one must render to a `str` which then gets + passed on to `logging` for output. + + Compared to *structlog*'s regular processor chains, there's a few + differences: + + - The event dictionary contains two additional keys: + + #. ``_record``: a `logging.LogRecord` that either was created + using `logging` APIs, **or** is a wrapped *structlog* log + entry created by `wrap_for_formatter`. + + #. ``_from_structlog``: a `bool` that indicates whether or not + ``_record`` was created by a *structlog* logger. + + Since you most likely don't want ``_record`` and + ``_from_structlog`` in your log files, we've added the static + method `remove_processors_meta` to ``ProcessorFormatter`` that + you can add just before your renderer. + + - Since this is a `logging` *formatter*, raising + `structlog.DropEvent` will crash your application. + + keep_exc_info: + ``exc_info`` on `logging.LogRecord`\ s is added to the + ``event_dict`` and removed afterwards. Set this to ``True`` to keep + it on the `logging.LogRecord`. (default: False) + + keep_stack_info: + Same as *keep_exc_info* except for ``stack_info``. (default: False) + + logger: + Logger which we want to push through the *structlog* processor + chain. This parameter is necessary for some of the processors like + `filter_by_level`. (default: None) + + pass_foreign_args: + If True, pass a foreign log record's ``args`` attribute to the + ``event_dict`` under ``positional_args`` key. (default: False) + + processor: + A single *structlog* processor used for rendering the event + dictionary before passing it off to `logging`. Must return a `str`. + The event dictionary does **not** contain ``_record`` and + ``_from_structlog``. + + This parameter exists for historic reasons. Please use *processors* + instead. + + Raises: + + TypeError: If both or neither *processor* and *processors* are passed. .. versionadded:: 17.1.0 .. versionadded:: 17.2.0 *keep_exc_info* and *keep_stack_info* diff --git a/src/structlog/testing.py b/src/structlog/testing.py index 34c62f94..8f5c093a 100644 --- a/src/structlog/testing.py +++ b/src/structlog/testing.py @@ -139,9 +139,13 @@ class CapturedCall(NamedTuple): Can also be unpacked like a tuple. - :param method_name: The method name that got called. - :param args: A tuple of the positional arguments. - :param kwargs: A dict of the keyword arguments. + Arguments: + + method_name: The method name that got called. + + args: A tuple of the positional arguments. + + kwargs: A dict of the keyword arguments. .. versionadded:: 20.2.0 """ diff --git a/src/structlog/threadlocal.py b/src/structlog/threadlocal.py index 62dc83a6..f57af92b 100644 --- a/src/structlog/threadlocal.py +++ b/src/structlog/threadlocal.py @@ -83,7 +83,9 @@ def wrap_dict(dict_class: type[Context]) -> type[Context]: The wrapped class and used to keep global in the current thread. - :param dict_class: Class used for keeping context. + Arguments: + + dict_class: Class used for keeping context. .. deprecated:: 22.1.0 """ @@ -104,10 +106,14 @@ def as_immutable(logger: TLLogger) -> TLLogger: """ Extract the context from a thread local logger into an immutable logger. - :param structlog.typing.BindableLogger logger: A logger with *possibly* - thread local state. + Arguments: + + logger (structlog.typing.BindableLogger): + A logger with *possibly* thread local state. + + Returns: - :returns: :class:`~structlog.BoundLogger` with an immutable context. + :class:`~structlog.BoundLogger` with an immutable context. .. deprecated:: 22.1.0 """ diff --git a/src/structlog/tracebacks.py b/src/structlog/tracebacks.py index 7f7b0ba9..bb9a2c5a 100644 --- a/src/structlog/tracebacks.py +++ b/src/structlog/tracebacks.py @@ -6,9 +6,10 @@ """ Extract a structured traceback from an exception. -Contributed by Will McGugan (see -https://github.com/hynek/structlog/pull/407#issuecomment-1150926246) from Rich: -https://github.com/Textualize/rich/blob/972dedff/rich/traceback.py +`Contributed by Will McGugan +`_ from +`rich.traceback +`_. """ from __future__ import annotations @@ -126,18 +127,25 @@ def extract( """ Extract traceback information. - :param exc_type: Exception type. - :param exc_value: Exception value. - :param traceback: Python Traceback object. - :param show_locals: Enable display of local variables. Defaults to False. - :param locals_max_string: Maximum length of string before truncating, or - ``None`` to disable. - :param max_frames: Maximum number of frames in each stack + Arguments: - :returns: A Trace instance with structured information about all - exceptions. + exc_type: Exception type. - .. versionadded:: 22.1 + exc_value: Exception value. + + traceback: Python Traceback object. + + show_locals: Enable display of local variables. Defaults to False. + + locals_max_string: + Maximum length of string before truncating, or ``None`` to disable. + + max_frames: Maximum number of frames in each stack + + Returns: + A Trace instance with structured information about all exceptions. + + .. versionadded:: 22.1.0 """ stacks: list[Stack] = [] @@ -212,16 +220,22 @@ class ExceptionDictTransformer: These dictionaries are based on :class:`Stack` instances generated by :func:`extract()` and can be dumped to JSON. - :param show_locals: Whether or not to include the values of a stack frame's - local variables. - :param locals_max_string: The maximum length after which long string - representations are truncated. - :param max_frames: Maximum number of frames in each stack. Frames are - removed from the inside out. The idea is, that the first frames - represent your code responsible for the exception and last frames the - code where the exception actually happened. With larger web - frameworks, this does not always work, so you should stick with the - default. + Arguments: + + show_locals: + Whether or not to include the values of a stack frame's local + variables. + + locals_max_string: + The maximum length after which long string representations are + truncated. + + max_frames: + Maximum number of frames in each stack. Frames are removed from + the inside out. The idea is, that the first frames represent your + code responsible for the exception and last frames the code where + the exception actually happened. With larger web frameworks, this + does not always work, so you should stick with the default. """ def __init__( diff --git a/src/structlog/twisted.py b/src/structlog/twisted.py index 84239d1c..64f7b386 100644 --- a/src/structlog/twisted.py +++ b/src/structlog/twisted.py @@ -204,7 +204,9 @@ class PlainFileLogObserver: Great to just print JSON to stdout where you catch it with something like runit. - :param file: File to print to. + Arguments: + + file: File to print to. .. versionadded:: 0.2.0 """ @@ -227,10 +229,13 @@ class JSONLogObserverWrapper: """ Wrap a log *observer* and render non-`JSONRenderer` entries to JSON. - :param ILogObserver observer: Twisted log observer to wrap. For example - :class:`PlainFileObserver` or Twisted's stock `FileLogObserver - `_ + Arguments: + + observer (ILogObserver): + Twisted log observer to wrap. For example + :class:`PlainFileObserver` or Twisted's stock `FileLogObserver + `_ .. versionadded:: 0.2.0 """ @@ -288,8 +293,11 @@ class EventAdapter: `_ behave as expected. - :param dictRenderer: Renderer that is used for the actual log message. - Please note that structlog comes with a dedicated `JSONRenderer`. + Arguments: + + dictRenderer: + Renderer that is used for the actual log message. Please note that + structlog comes with a dedicated `JSONRenderer`. **Must** be the last processor in the chain and requires a *dictRenderer* for the actual formatting as an constructor argument in order to be able to @@ -301,9 +309,6 @@ def __init__( dictRenderer: Callable[[WrappedLogger, str, EventDict], str] | None = None, ) -> None: - """ - :param dictRenderer: A processor used to format the log message. - """ self._dictRenderer = dictRenderer or _BUILTIN_DEFAULT_PROCESSORS[-1] def __call__( diff --git a/src/structlog/typing.py b/src/structlog/typing.py index c10e467a..66f6a7e0 100644 --- a/src/structlog/typing.py +++ b/src/structlog/typing.py @@ -9,7 +9,7 @@ For now, they are considered provisional. Especially `BindableLogger` will probably change to something more elegant. -.. versionadded:: 22.2 +.. versionadded:: 22.2.0 """ from __future__ import annotations @@ -38,7 +38,7 @@ *structlog* makes *no* assumptions about it. -.. versionadded:: 20.2 +.. versionadded:: 20.2.0 """ @@ -46,7 +46,7 @@ """ A dict-like context carrier. -.. versionadded:: 20.2 +.. versionadded:: 20.2.0 """ @@ -57,7 +57,7 @@ It's created by copying the configured `Context` but doesn't need to support copy itself. -.. versionadded:: 20.2 +.. versionadded:: 20.2.0 """ Processor = Callable[ @@ -69,14 +69,14 @@ See :doc:`processors`. -.. versionadded:: 20.2 +.. versionadded:: 20.2.0 """ ExcInfo = Tuple[Type[BaseException], BaseException, Optional[TracebackType]] """ An exception info tuple as returned by `sys.exc_info`. -.. versionadded:: 20.2 +.. versionadded:: 20.2.0 """ @@ -86,7 +86,7 @@ Used by `structlog.dev.ConsoleRenderer`. -.. versionadded:: 21.2 +.. versionadded:: 21.2.0 """ @@ -102,12 +102,16 @@ class ExceptionTransformer(Protocol): Used by `structlog.processors.format_exc_info()` and `structlog.processors.ExceptionPrettyPrinter`. - :param exc_info: Is the exception tuple to format + Arguments: - :returns: Anything that can be rendered by the last processor in your - chain, e.g., a string or a JSON-serializable structure. + exc_info: Is the exception tuple to format - .. versionadded:: 22.1 + Returns: + + Anything that can be rendered by the last processor in your chain, + for example, a string or a JSON-serializable structure. + + .. versionadded:: 22.1.0 """ def __call__(self, exc_info: ExcInfo) -> Any: @@ -120,7 +124,7 @@ class BindableLogger(Protocol): **Protocol**: Methods shared among all bound loggers and that are relied on by *structlog*. - .. versionadded:: 20.2 + .. versionadded:: 20.2.0 """ _context: Context @@ -145,8 +149,7 @@ class FilteringBoundLogger(BindableLogger, Protocol): The only way to instantiate one is using `make_filtering_bound_logger`. .. versionadded:: 20.2.0 - .. versionadded:: 22.2.0 - String interpolation using positional arguments. + .. versionadded:: 22.2.0 String interpolation using positional arguments. .. versionadded:: 22.2.0 Async variants ``alog()``, ``adebug()``, ``ainfo()``, and so forth. .. versionchanged:: 22.3.0 diff --git a/tests/test_processors.py b/tests/test_processors.py index d9363108..c8628302 100644 --- a/tests/test_processors.py +++ b/tests/test_processors.py @@ -1049,12 +1049,16 @@ def make_processor( supplied ``parameter_strings`` values and with the supplied ``additional_ignores`` values. - :param parameter_strings: - Strings for which corresponding ``CallsiteParameters`` should be - included in the resulting ``CallsiteParameterAdded``. - :param additional_ignores: - Used as ``additional_ignores`` for the resulting - ``CallsiteParameterAdded``. + Arguments: + + parameter_strings: + Strings for which corresponding ``CallsiteParameters`` should + be included in the resulting ``CallsiteParameterAdded``. + + additional_ignores: + + Used as ``additional_ignores`` for the resulting + ``CallsiteParameterAdded``. """ if parameter_strings is None: return CallsiteParameterAdder( @@ -1075,11 +1079,12 @@ def filter_parameters( Returns a set containing all ``CallsiteParameter`` members with values that are in ``parameter_strings``. - :param parameter_strings: - The parameters strings for which corresponding - ``CallsiteParameter`` members should be - returned. If this value is `None` then all - ``CallsiteParameter`` will be returned. + Arguments: + + parameter_strings: + The parameters strings for which corresponding + ``CallsiteParameter`` members should be returned. If this value + is `None` then all ``CallsiteParameter`` will be returned. """ if parameter_strings is None: return cls._all_parameters @@ -1097,9 +1102,11 @@ def filter_parameter_dict( Returns a dictionary that is equivalent to ``input`` but with all keys not in ``parameter_strings`` removed. - :param parameter_strings: - The keys to keep in the dictionary, if this value is ``None`` then - all keys matching ``cls.parameter_strings`` are kept. + Arguments: + + parameter_strings: + The keys to keep in the dictionary, if this value is ``None`` + then all keys matching ``cls.parameter_strings`` are kept. """ if parameter_strings is None: parameter_strings = cls.parameter_strings @@ -1115,9 +1122,11 @@ def get_callsite_parameters(cls, offset: int = 1) -> dict[str, object]: This function creates dictionary of callsite parameters for the line that is ``offset`` lines after the invocation of this function. - :param offset: - The amount of lines after the invocation of this function that - callsite parameters should be generated for. + Arguments: + + offset: + The amount of lines after the invocation of this function that + callsite parameters should be generated for. """ frame_info = inspect.stack()[1] frame_traceback = inspect.getframeinfo(frame_info[0]) diff --git a/tests/test_stdlib.py b/tests/test_stdlib.py index d097aa00..fa89a3b2 100644 --- a/tests/test_stdlib.py +++ b/tests/test_stdlib.py @@ -1133,10 +1133,6 @@ async def _abl(cl): return AsyncBoundLogger(cl, context={}, processors=[]) -@pytest.mark.skipif( - sys.version_info[:2] < (3, 7), - reason="AsyncBoundLogger is only for Python 3.7 and later.", -) class TestAsyncBoundLogger: def test_sync_bl(self, abl, cl): """