-
-
Notifications
You must be signed in to change notification settings - Fork 3
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
Leverage mypy to check str.format expressions #43
Leverage mypy to check str.format expressions #43
Conversation
@kornicameister How do you track which versions of mypy are compatible? Since I am tapping into mypy's internals I am worried it will break with upcoming versions, so I think we should have a way of making that visible. |
0652770
to
f076f9f
Compare
@ThibaultLemaire thx for pull request. It looks really nice, I'd like to hear more about that Anyway,I really like your job on error messages although I wonder if having them more accurate wasn't better. Could you elaborate why did you change those? PS. sorry for being so lazy about reviewing, I had my evenings filed with either micro-management on 2 children or overtime from work :/ |
Well, I probably don't understand half of the magic of |
Hey, looks like it's my turn to apologize for the delay, last week was crazy at work. Thank you @Delgan, I have been focusing precisely on keeping the magic on mypy's side with this PR and not having to understand it 😉 Hopefully we can make that work in a satisfying way |
```py from loguru import logger class Foo: bar = "baz" foo = Foo() logger.debug('The bar is "{my_foo.bar}"', my_foo=foo) logger.debug('The bar is "{my_foo.bar}"', my_foo="not foo") # error: "str" has no attribute "bar" ``` Let's not reinvent the wheel :)
f076f9f
to
305ef28
Compare
@ThibaultLemaire would you mind checking #31 ? Would you change invalid that PR? |
Hm, I can imagine why my work would conflict with this PR, but I'm not sure how exactly the two would interact. Also, what exactly do you mean by "invalid[ate]" ? If you mean make obsolete, I don't think so: my changes have no way of knowing if I only glanced at it though, so I'll take the time to investigate properly. |
Okay, so, after further investigation, I reckon you could adapt your work on #31 to make it work side by side, but then you'd have a bit of an overlap. To take your example code from #18, and compare the (theoretical) results of #31 and #43 (this PR): logger.info('{record["msg"]}') # loguru -> ❌, #31 -> ❌, #43 -> ❌
logger.opt(record=True).info('{record["msg"]}') # loguru -> ✔, #31 -> ✔, #43 -> ❌ As you can see, there would be duplicate error messages, as well as contradicting messages where my work has shortcomings and can't understand that The issue is that I rely entirely on mypy's internals and have no control over them, so I couldn't silence that error even if I wanted to. What we could do, though, -- and, to me, that would be the best solution -- would be to pass the logger.opt(record=True).info('{record["msg"]}') as if it were something like logger.info('{record["msg"]}'.format(record={})) Unfortunately, I don't know how much of your work we could reuse if we go down that path. |
Also related to that, I have noticed that you store the loggers the plugin has previously encountered in the
I wonder if we could rather play on the type we return from the plugin to store that configuration, which should save us a lot of trouble in the future as well. To illustrate, I was wondering if we could make things work a bit like this: from loguru import logger # type is inferred by mypy to be Logger
with_record: LoggerWithRecord = logger.opt(record=True)
# Those would be custom types that we return, in order to know what to do next time we encounter it
lazy: LazyLogger = logger.opt(lazy=True)
with_ip: BoundLogger = logger.bind(ip="192.168.0.1")
with_ip_in_record: BoundLoggerWithRecord = with_ip.opt(record=True)
# And here mypy should pass us all the info we need to validate it properly
with_ip_in_record.info("Your local ip is {record["ip"]}") |
@ThibaultLemaire for the global state, I was not aware of that. If could drop the issue for that matter, I'd appreciate. Just put a link to your comment. As for the #31 I think I'd prefer to have mypy deal with string formatting if possible. I imagine them doing far better job. Unless, we can get our hands on @Delgan do you have any interesting cases we could use to challenge this PR? If you do, please put a comment :) |
I tried hard but could not generate a error specific to the However, some tests led me to open #49. :p |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, lets proceed with it.
As I said before, for me it is better to reuse mypy because it might help with both making it work more predictable and more compliant with different mypy versions.
Also, given that @Delgan did not exactly raise incompatibility between logoru
and this PR on runtime, I don't see anything that would prevent us from doing so.
Errors reported earlier are actually related to us using StrExpr
all the time.
@ThibaultLemaire I am merging this. Thanks a lot for patience and waiting for me here :) |
* origin/master: Leverage mypy to check str.format expressions (#43)
For the record, this has been developed and tested against
mypy==0.782
.Closes #42