Skip to content
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

improve lazy support #1207

Open
trim21 opened this issue Sep 18, 2024 · 4 comments
Open

improve lazy support #1207

trim21 opened this issue Sep 18, 2024 · 4 comments
Labels
feature Request for adding a new feature

Comments

@trim21
Copy link
Contributor

trim21 commented Sep 18, 2024

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")
@reneleonhardt
Copy link

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
Copy link
Contributor Author

trim21 commented Sep 22, 2024

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
Copy link
Owner

Delgan commented Sep 22, 2024

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 Delgan added the feature Request for adding a new feature label Sep 22, 2024
@trim21
Copy link
Contributor Author

trim21 commented Sep 22, 2024

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__

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Request for adding a new feature
Projects
None yet
Development

No branches or pull requests

3 participants