Can I use mypy plugins to type-check functions created at runtime? #1430
Replies: 4 comments
-
I don't see why you would need a plugin for this, unless you want to type check the generated code internally, I don't see the point. You can infer what the signature of the mapper function looks like from the types being passed into the generator function statically i.e. Or is the problem that you loop through a list of type names to generate the mapper function, rather than having explicit calls to Sure it adds a little mental overhead where you have to now run that build script every time you change code that requires new mappers, but you could just add a pre-commit step to do it for you, before the type checker is run. |
Beta Was this translation helpful? Give feedback.
-
My goal is to type check the source code (implementation) of the generated functions, to catch invalid assignments (e.g., assigning a If I generate the source code via a separate command, yes, mypy checks come "for free", though it's another step that needs doing, and then there's questions like:
Doing it on-demand, at runtime, happens pretty much transparently (despite the startup penalty), however, that's why I decided to go with this approach. Mind you, I am not at all familiar with code generation in Python, this is something I'm exploring as I go, so suggestions and/or state-of-the-art are welcome. |
Beta Was this translation helpful? Give feedback.
-
That's fair enough. I have some limited experience with mypy plugins and it's probably possible you can get this done with a mypy plugin, but it would be pretty annoying to write and would probably end up being quite fragile, on top of the challenges of reporting the errors in a way where they would be easy to trace back to their origin. I would personally recommend against it. How about a pragmatic compromise? You could add ascript to the module which exports all the generated code into a file/string that can then be passed into mypy and type checked against the full module/package. You could add comments to the file to indicate where each function was generated, so you get more granular error reporting, i.e. you can see exactly which generated statement is faulty, but from the comment you can still trace back the function to its origin. |
Beta Was this translation helpful? Give feedback.
-
If I had to do something like this with mypy I would not recommend a mypy plugin and instead recommend calling mypy in a subprocess after code is generated and just pass generated code ast/string to mypy dumped to some temp file. Mypy plugins are more for enhancing mypy when used statically not for using mypy at runtime. Alternatively I'd recommend explore runtime type checking libraries like typeguard/beartype to add type assertions. |
Beta Was this translation helpful? Give feedback.
-
First, an explanation: I have two kinds of types in my project, for representing a data model:
It allows decoupling between the two. However, I need functions that map between the two. Usually the types are the same, but sometimes some conversions are required.
I can write the mappings myself, but creating mappings for ~100 types, back and forth, means ~200 functions, mostly with code like this:
Which is tedious, so, because most of the mappings are simple (or simple enough to compose), I started by creating something like this:
This works fine, but it has non-negligible overhead, performance-wise (about 20-40% vs. a hand-written function). So, I decided to take a code generation approach, where I would inspect the types
T1
andT2
at runtime, build the source code for the function at runtime, and thenexec()
it to get the function object out. The function is then created something like this:This works well, and it doesn't have the overhead of the dynamic version shown above, but I would like to have mypy type-check this generated code. I think I can use a mypy plugin for this, but I'm not sure if it is possible, or where I should start.
Ideally, what I want is to have the mypy plugin generate the same source code that the
create_mapper
function does, pass it to mypy, and propagate such errors to the overall error report, for every call tocreate_mapper
.Beta Was this translation helpful? Give feedback.
All reactions