-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
mypy not recognizing attribute of class created with setattr #5719
Comments
Yes, mypy doesn't run your code, it only reads it, and it only looks at the types of attributes, not at actions like |
I understand the reason here, but I am curious if there is any known, relatively elegant workaround for class decorators. I am using a class decorator that adds structuring/unstructuring methods like so:
Obviously MyPy can't run this decorator to see what it does. But is there a relatively clean way of hinting to MyPy that specific classes do have given, named, function attributes? Obviously I could inherit from a superclass that has 'fake' versions of those methods, and that seems to be the cleanest thing I can come up with for the moment. But it would be ideal to have a method that doesn't introduce anything into the inheritance hierarchy. I certainly understand if this is simply too dynamic for static type checking. :) It's easy to want the best of both worlds, and obviously not all things are technically feasible. |
I'm looking at https://github.com/python/mypy/blob/master/mypy/plugin.py and think that a plugin using |
This ended up being a huge amount of work, but I was able to write a MyPy plugin that adds a static method and a regular method to the class type when it sees a specific decorator. I leaned heavily on what I found in Note that my method here is extremely use-case specific, but it's not too hard to see how this could be usefully generalized. If I can find the time, I think I will try to build out a minimal library of sorts that would allow some relatively simple syntax inside a decorator to spell out the details for a wide variety of possibilities, but there's no question that with some help from the MyPy core developers it would be a lot easier to accomplish. Perhaps someone will see this and provide suggestions for improvement.
My
|
@petergaultney Reasonable understanding of how mypy works under the hood is a prerequisite for writing plugins (simple plugins can be written without it, but as soon as you start writing something non-trivial you will need it). After a brief look at your plugin I didn't spot any obvious bugs (apart from questionable practice to import from other plugin). You can publish this plugin on PyPI (just add a simple setup.py) if you want other people to be able to use it. |
thanks, and yeah, i may publish it as part of a larger effort around typing, though the first thing to do would be to make it sufficiently generic that people could inject their own set of names, etc. I'm wondering, however, whether I took the right approach after all. I'm in the middle of testing a theory, but perhaps you could save me some time, or let me know about a minefield that I'm missing. It seems, now that I take another look at the classes in If it did work, it seems to me that it would not be too difficult to write a "decorator meta-typing plugin", that could effectively be pointed at static code that "shows" the methods, attributes, etc. that a decorator is intended to apply to a class, and applies those wherever it sees the decorator being used. |
Looks like deserializing a serialized SymbolTableNode or a FuncDef gets me an assertion error "De-serialization failure: TypeInfo not fixed." So this isn't quite as straightforward as I hoped. Is there something I can do to make a SymbolTableNode or FuncDef properly deserialize by fixing up the "TypeInfo" afterwards, or is this going to be difficult to do as dynamically as I was hoping? e.g.: |
De-serializing mypy cache is not a safe idea. First of all the cache format is totally a private API and will likely change. Second, mypy supports (mutually) recursive classes, so de-serialization requires an additional fix-up pass, which is no-trivial. You can alternatively try getting the actual AST objects (all things can be found from plugins by their full names), but then you will need to somehow copy them. Although the final goal (write a generic plugin that understands meta-programming source code) looks interesting, this is a non-trivial task and requires deep understanding of how mypy works. |
I really appreciate the feedback! I didn't realize the serialization was primarily intended for the cache. I'll keep thinking about it. :) |
Most of the init arguments in the ``HTML2Text`` class are hardcoded in constants and modifiable only by the cli, not through the library usage. This adds the possibility to pass kwargs through the function call ``html2text`` or class init. Please note that the commit contains syntax that is not recognizable by ``mypy``, but is correct. Note: python/mypy#5719
to address the test falure caused by mypy: ``` mypy run-test: commands[0] | mypy --config-file=../../mypy.ini ansible/module.py cephadm/module.py mgr_module.py mgr_util.py orchestrator.py orchestrator_cli/module.py rook/module.py test_orchestrator/module.py cephadm/module.py: note: In member "_check_for_strays" of class "CephadmOrchestrator": cephadm/module.py:596: error: "CephadmOrchestrator" has no attribute "warn_on_stray_hosts" cephadm/module.py:596: error: "CephadmOrchestrator" has no attribute "warn_on_stray_services" cephadm/module.py:599: error: "CephadmOrchestrator" has no attribute "warn_on_stray_services" Found 3 errors in 1 file (checked 8 source files) ``` see also python/mypy#5719 Signed-off-by: Kefu Chai <kchai@redhat.com>
to address the test falure caused by mypy: ``` mypy run-test: commands[0] | mypy --config-file=../../mypy.ini ansible/module.py cephadm/module.py mgr_module.py mgr_util.py orchestrator.py orchestrator_cli/module.py rook/module.py test_orchestrator/module.py cephadm/module.py: note: In member "_check_for_strays" of class "CephadmOrchestrator": cephadm/module.py:596: error: "CephadmOrchestrator" has no attribute "warn_on_stray_hosts" cephadm/module.py:596: error: "CephadmOrchestrator" has no attribute "warn_on_stray_services" cephadm/module.py:599: error: "CephadmOrchestrator" has no attribute "warn_on_stray_services" Found 3 errors in 1 file (checked 8 source files) ``` see also python/mypy#5719 Signed-off-by: Kefu Chai <kchai@redhat.com>
@petergaultney did you get around to doing more work on this or publishing it? |
I did a little more on it and abandoned it for lack of time. It still seems like it should be theoretically possible to build some sort of helper that would allow plugins to be written dynamically, rather than piece-by-piece, since at the end of the day you're just trying to teach mypy that certain "names" match certain types that are otherwise as easy to write as |
Let's say I have the following code in
example.py
:When I run
mypy example.py
, I get:Is this expected behavior?
The text was updated successfully, but these errors were encountered: