Delgan / loguru

Python logging made (stupidly) simple
MIT License
19.91k stars 696 forks source link

improve lazy support #1207

Open trim21 opened 1 month ago

trim21 commented 1 month ago

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

from loguru import logger

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

class LazyValue:
    __slots__ = ('fn',)

    def __init__(self, fn: Callable[[], Any]):
        self.fn = fn

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

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

logger.debug("hello {} from {}", LazyValue(expensive_func), "Alice")
logger.info("hello {} from {}", LazyValue(expensive_func), "Alice")
reneleonhardt commented 1 month ago

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?

trim21 commented 1 month ago

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"

Delgan commented 1 month ago

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.

trim21 commented 1 month ago

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__