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

Tracking variable whereabouts in a plugin #9010

Open
kornicameister opened this issue Jun 17, 2020 · 11 comments
Open

Tracking variable whereabouts in a plugin #9010

kornicameister opened this issue Jun 17, 2020 · 11 comments
Labels
question topic-plugins The plugin API and ideas for new plugins

Comments

@kornicameister
Copy link

Please provide more information to help us understand the issue:

  • Type: question
  • Referecenes:
  • Expected behavior: being able to track down variable i.e. from a process it was initialized.
    Code below should illustrate an expected behavior.
  • Actual behavior: n/a
  • mypy version: >=0.770
from luguru import logger

LOG_A = logger.opt(lazy=False)
LOG_B = logger.opt(lazy=True)

LOG_A.info('Test {}', lambda x: x)    # should work
LOG_B.info('Test {}', lambda x: x)    # error

logger.opt(lazy=False).info('Test {c}', c=lambda x: x)  # should work
logger.opt(lazy=True).info('Test {d}', d=lambda x: x)   # error

In short: with loguru you can use Callable[[], Any] for lazy loggers to avoid costly computations. But those have to be non-argument callables. Above you can find non-lazy loggers that will work just fine by doing str(callable). In other words, to rephrase question from above, how can we:

track a variable/object on which behalf a method was called?

This is quite vital because type checking cannot be done solely on a method call level because we need something from another call. There is opt method being called but having call details from it without anything to tie them to will not help too much.

@kornicameister
Copy link
Author

@Delgan I am linking you to this issue. If it comes to it, you will be able to explain runtime details much better 👍

@Delgan
Copy link

Delgan commented Jun 17, 2020

Basically, what we need is a way to customize the returned type of a method based on introspection of the arguments.

foo = logger.opt(lazy=True)   # => foo is of type "LazyLogger"
bar = logger.opt(lazy=False)  # => bar is of type "Logger"

These types needs to be defined by the plugin, and later we need to be able to use them to decide whether foo.info(...) is valid or not.

@JukkaL
Copy link
Collaborator

JukkaL commented Jun 19, 2020

I don't think that you need a plugin for this. Why not use literal types and and overloaded function to vary the return type of logger.opt based on the value of lazy?

@Delgan
Copy link

Delgan commented Jun 21, 2020

@JukkaL Sounds like a promising idea. I was not aware of literal types, thanks!

What do you think @kornicameister? Would that solve the problem if we add this to the loguru type hints file?

@kornicameister
Copy link
Author

@JukkaL this might work. I guess loguru already exports typings so we can of course check it out.

@kornicameister
Copy link
Author

kornicameister commented Jun 24, 2020

@JukkaL I have checked typing in loguru and indeed we can add LazyLogger if lazy=True but then again I am not sure how we can describe a signature of method like info, debug and so on. Indeed a signatures like:

    @overload
    def info(__self, __message: str, *args: Any, **kwargs: Any) -> None: ...
    @overload
    def info(__self, __message: Any) -> None: ...

are quite accurate given dynamic nature of loguru. For one, lazy=True and how it affects callables is just one example.
Another one can be opt(record=True). With that set we can use special record dictionary in message template.
Can we in fact use just typing to do describe all that? I mean perhaps lazy can be done somehow , but we need to know how to differentiate all Callable (that can be passed both as *arg or **kwarg) from other arguments passed to methods of loggers where each of those arguments can also be passed as *arg or **kwarg.

This sounds as some high level problem but if there's way to deal with that, I'd happy to know :D.

@kornicameister
Copy link
Author

@JukkaL Care to check this one out? kornicameister/loguru-mypy#7 ?
I assume that if that's correct it can be an answer to this issue.

@kornicameister
Copy link
Author

FYI: It seems like it is sufficient to keep a state of what we want to track over in an instance of the plugin and pass it to specific handlers via functools.partial or equivalent.

That approach is being used in loguru-mypy already. Wonder if that's correct one as well as if that's an intended usage.

@JukkaL
Copy link
Collaborator

JukkaL commented Aug 14, 2020

Wonder if that's correct one as well as if that's an intended usage.

Can you explain this in more detail? Based on the description it's hard to say.

@kornicameister
Copy link
Author

kornicameister commented Aug 14, 2020

@JukkaL it is actually not just description. I have just forgotten to link appropriate part of the plugin 😿
Here it is for reference:

  • state-ish variable here
  • usages 1 and 2

I just realized, that apart from a question if that is "the" way to implement that, there is just one question related to caching, but let's maybe stick to the original one for the time being.

@AlexWaygood AlexWaygood added question topic-plugins The plugin API and ideas for new plugins labels Mar 29, 2022
@AlexWaygood
Copy link
Member

Hi! Is this still a problem for loguru-mypy, or can this issue now be closed? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question topic-plugins The plugin API and ideas for new plugins
Projects
None yet
Development

No branches or pull requests

4 participants