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
KeyError
in GenericModel.__parameterized_bases__.build_base_model
#4131
Comments
KeyError
in GenericModel.__parameterized_bases__.build_base_modelKeyError
in GenericModel.__parameterized_bases__.build_base_model
I was not able to create a short example for reproducibility, but I managed to identify the changes that "broke" our testsuite: #4083 If I revert both changes to pydantic/generics.py, the errors in our testsuite disappear. That might explain, why it's not easy to create a simple snippet for reproducibility, right? One needs to manage to exceed the limit... |
Sorry for slow reply, yes makes sense. I don't want to change the limits, but we should fail in a more transparent way. |
I also added some debug messages in I noticed for my case, that the caches The testsuite fixture defines a limited number of distinct models (including static and dynamic ones, in total 23), but whenever the application is rebuilt for the next test case, the models get rebuilt and added to the cache as the keys do not match. To be exact, To the best of my knowledge, this cache problem (maybe the reason for the leak mentioned in #3829?) was also true for v1.9.0, but for some reasonit did not cause a
Yes, if my understanding of the observed problem is correct, changing the limit makes no difference.
Given the specific error I observed, I'm wondering if it would make more sense to allow a margin of error when comparing two different But that would probably only count as a workaround. Maybe I should raise an issue with the developers of fastapi_pagination to not use
|
Hello! We are also getting hit by this issue. Im not sure is it related to from typing import Generic, TypeVar
from weakref import WeakKeyDictionary, WeakValueDictionary
import pydantic
from pydantic import create_model
from pydantic.generics import GenericModel
# Uncomment to fix the issue
# pydantic.generics._generic_types_cache = WeakValueDictionary(pydantic.generics._generic_types_cache)
# pydantic.generics._assigned_parameters = WeakKeyDictionary(pydantic.generics._assigned_parameters)
T = TypeVar("T")
C = TypeVar("C")
class A(GenericModel, Generic[T, C]): pass
class B(A[int, C], GenericModel, Generic[C]): pass
models = [create_model(f"M{i}") for i in range(350)]
for m in models:
B[m] # Will crash with "KeyError: ~T" So essentially generics with parametrized bases are broken due to the PR changing to use LimitedDicts by @samuelcolvin. As far as I understand, it seems using The example I gave is actually not something we use. Its just to repro the issue. The count of models there can be actually much lower depending on complexity of the application and usage of generics and parametrized bases. I also gave a fix proposal above so moving to use weak dictionaries to handle any leakage with dynamic model usage. We actually need to now apply the above fix to our code as otherwise it can crash with We are using Pydantic |
Thanks for your detailed explanation @MarkusSintonen, we'll review your PR. |
Great thanks! The PR should be now ready for review |
THere's been several PRs addressing memory leaks with generics (including the one above, which is merged). I believe this is no longer an issue, especially for Pydantic V2. Please re-open if it still is. |
When I last checked with v1.10.4, the problem still existed, but when I checked today with v1.10.8 the problem seems to be fixed. Thank you 👍 |
The constraint was introduced in SUSE#74 due to pydantic/pydantic#4131. The fix for pydantic has been released and the constraint is now superfluous.
@crazyscientist BTW, I'd still recommend using a constraint |
The constraint was introduced in SUSE#74 due to pydantic/pydantic#4131. The fix for pydantic has been released and the constraint is now superfluous. This version constraint implicitly limited `fastapi-pagination` to v0.9.3, which now also gets updated (to v0.12.4). However, it's behavior has changed slightly, which required an adjustment to the test suite.
The constraint was introduced in #74 due to pydantic/pydantic#4131. The fix for pydantic has been released and the constraint is now superfluous. This version constraint implicitly limited `fastapi-pagination` to v0.9.3, which now also gets updated (to v0.11.4). However, it cannot be upgraded to the latest v0.12 series, due to #146.
Bug
Output of
python -c "import pydantic.utils; print(pydantic.utils.version_info())"
:I'm afraid reproduction of this issue is a bit tricky as I was not able to reproduce it in a production scenario nor with a small code snippet. So far, I only noticed this in the test suite of this project, which contains multiple sub-modules for tests; but only tests in two can fail, i.e. when the entire testsuite runs, they fail; if I explicitly only run tests from these modules, they pass.
This behavior probably also indicates a problem within the testsuite, which I intend to look for, but the problem does not occur with version 1.9.0 of pydantic. So, I figured it's worth sharing.
In the project, we dynamically define API routes for FastAPI for dynamically generated models (i.e. model definitions are stored in DB), i.e. the models and routes get generated/updated at start-up or when something changes in the DB. The callback function used for this looks something like this:
The exception raised in the testsuite looks like this:
I checked the contents of
mapped_types
andbase_model.__parameters__
in the line where the exception gets raised:It looks like the
TypeVar
s, which are expected to be identical, no longer are. 🤔The text was updated successfully, but these errors were encountered: