loguru icon indicating copy to clipboard operation
loguru copied to clipboard

improve lazy support

Open trim21 opened this issue 1 year ago • 5 comments

since we are using new style format, it's possible to control how value are formatted with __format__

current lazy option is not necessary, we can add a LazyValue type, this make is possible to mix lazy and un-lazy arguments

import logging
import sys
import time
from typing import Callable, Any, ParamSpec

from loguru import logger

logger.remove()
logger.add(sys.stderr, level="INFO")


P = ParamSpec("P")


class LazyValue:
    __slots__ = ("fn", "args", "kwargs")

    def __init__(self, fn: Callable[P, Any], *args: P.args, **kwargs: P.kwargs):
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    def __format__(self, format_spec: str):
        return format(self.fn(*self.args, **self.kwargs), format_spec)


def expensive_func() -> int:
    print("expensive_func called")
    time.sleep(1)
    return 1


def expensive_func_2(s: int) -> int:
    print("expensive_func called")
    time.sleep(s)
    return 1


logger.debug("hello {} from {}", LazyValue(expensive_func), "Alice")
logger.info("hello {} from {}", LazyValue(expensive_func_2, 5), "Alice")

trim21 avatar Sep 18 '24 13:09 trim21

Nice! Wouldn't it be easier to just accept a supplier function (i.e. lambda: "Hello" or an object method None.__str__) to be evaluated instead of a custom class?

reneleonhardt avatar Sep 21 '24 13:09 reneleonhardt

Nice! Wouldn't it be easier to just accept a supplier function (i.e. lambda: "Hello" or an object method None.__str__) to be evaluated instead of a custom class?

I think that's very strange behavior for "formatting"

trim21 avatar Sep 22 '24 16:09 trim21

If anything, it already exists as an external library like lazy-string for example.

I agree it's more powerful than the current opt(lazy=True) design.

Delgan avatar Sep 22 '24 16:09 Delgan

If anything, it already exists as an external library like lazy-string for example.

I agree it's more powerful than the current opt(lazy=True) design.

it only support old style percent formatting, not new style {} formatting

from lazy_string import LazyString
from loguru import logger


def make_foo() -> int:
    return 1


logger.info("nice, {:05d}".format(LazyString(make_foo)))
Traceback (most recent call last):
  File "C:\Users\Trim21\proj\test\f.py", line 9, in <module>
    logger.info("nice, {:05d}".format(LazyString(make_foo)))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unsupported format string passed to LazyString.__format__

trim21 avatar Sep 22 '24 17:09 trim21

now we have https://peps.python.org/pep-0750/ , any new thoughts?

trim21 avatar Nov 18 '25 02:11 trim21