Skip to content

Commit

Permalink
Make docstrings more readable by switching to Napoleon
Browse files Browse the repository at this point in the history
  • Loading branch information
hynek committed Sep 8, 2023
1 parent 0d873c5 commit 2a6b4c0
Show file tree
Hide file tree
Showing 18 changed files with 488 additions and 320 deletions.
10 changes: 7 additions & 3 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand Down
74 changes: 49 additions & 25 deletions src/structlog/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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::
Expand Down Expand Up @@ -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(
Expand All @@ -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::
Expand All @@ -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
94 changes: 56 additions & 38 deletions src/structlog/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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,
Expand All @@ -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.
Expand All @@ -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)

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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__(
Expand Down
10 changes: 7 additions & 3 deletions src/structlog/_frames.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
13 changes: 8 additions & 5 deletions src/structlog/_log_levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <finer-filtering>`.
: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
<https://docs.python.org/3/library/logging.html#levels>`_ 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
<https://docs.python.org/3/library/logging.html#levels>`_ for
possible values.
.. versionadded:: 20.2.0
.. versionchanged:: 21.1.0 The returned loggers are now pickleable.
Expand Down
Loading

0 comments on commit 2a6b4c0

Please sign in to comment.