-
Notifications
You must be signed in to change notification settings - Fork 5
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
Migrate to Pydantic v2 #64
Conversation
Uses string literals instead
Just discovered an issue with merging hosts using Pydantic V2. 89ae85d (origin/master)
f653bc3 (pederhan/pydantic-v2)
Seems potentially like an issue with zabbix-auto-config/zabbix_auto_config/processing.py Lines 436 to 446 in f653bc3
Where in Pydantic V1 the models would match, but in V2 they don't for whatever reason. Need to attach a debugger and investigate which models are affected. The number of models affected each merge iteration is very similar, so we should expect to see the same models affected each time. What do they have in common? |
This happens due to a host modifier assigning a new interface to the hosts in the form of a dict, not as an instance of from zabbix_auto_config.models import Host, Interface
host1 = Host(
enabled=False,
hostname='foo.example.com',
interfaces=[],
# ...
)
host1.append(
{
'details': {'version': 2, 'community': '{$SNMP_COMMUNITY}'},
'endpoint': 'foo.example.com',
'port': '161',
'type': 2,
}
)
host2 = Host(
enabled=False,
hostname='foo.example.com',
interfaces=[
{
'details': {'version': 2, 'community': '{$SNMP_COMMUNITY}'},
'endpoint': 'foo.example.com',
'port': '161',
'type': 2,
}
],
)
assert host1 == host2 But in Pydantic V2, the list of dicts in |
After some more testing, it seems the only way to rebuild a model where submodels are re-validated in Pydantic V2 is to add class Host(BaseModel):
# ...
model_config = ConfigDict(validate_assignment=True, revalidate_instances="always") Source: https://docs.pydantic.dev/latest/usage/model_config/#revalidate-instances While that is a decent workaround, it ignores the fact that appending the wrong data type to a field is marked as an error by type checkers such as mypy, so it shouldn't even happen in the first place: Without modifying the code to accommodate this erroneous use of the library, this PR would introduce a breaking change, but largely in the form of being less lenient with existing erroneous code. We are not introducing some arcane set of requirements or changing the "best practice" way of interacting with the models. We could have a transition period to Pydantic V2 where do in fact re-validate each modification, but announce that we will eventually stop doing it? I'll add re-validation of Hosts for each modifier for now. But seeing as this problem is caught by static type checkers and we have to enable optional functionality ( |
DataV1 (See #63)
V2 Revalidation
V2 No Revalidation (pederhan/zabbix-auto-config@408a9c3)
ConclusionWe see a ~40% speedup when doing revalidation with Pydantic V2 compared to the existing V1 implementation, while removing the revalidation puts this number up at ~44%. There aren't a lot of data points used to benchmark, so these are just rough estimates, but it gives us a good impression of the overall performance increase that Pydantic V2 provides as well as the cost of performing revalidation of hosts after each modification. The increase in range is likely due to external factors such as DB latency combined with few data points for the V1 benchmark. In conclusion, the overhead incurred from revalidation is trivial when compared to other actions such as DB reads/writes. The repeat validation lets us maintain backwards compatibility with "improper" host modifiers while giving us more granular diagnostics in case a host modifier modifies a Host to be invalid, which we did not previously have. |
Pydantic v2 brings with it much higher performance (5-50x times faster than Pydantic v1), as well as improved APIs for validation and (de)serialization.
This PR bumps the minimum Pydantic version of ZAC to 2.0.0. Code changes have been made to accommodate the new APIs introduced in 2.0.0. Most of the code changes were made using the migration tool Bump Pydantic as outlined in the Pydantic V2 Migration Guide.
The use of
BaseSettings
has been substituted withBaseModel
since we didn't use any of the features offered byBaseSettings
. Furthermore, theBaseSettings
class has been moved to the pydantic-settings package, which we shouldn't include if we don't need to.