Skip to content
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

Runtime type checking, Pydantic, SQLModel #6544

Open
rdimaio opened this issue Mar 11, 2024 · 1 comment
Open

Runtime type checking, Pydantic, SQLModel #6544

rdimaio opened this issue Mar 11, 2024 · 1 comment

Comments

@rdimaio
Copy link
Contributor

rdimaio commented Mar 11, 2024

Description

Right now, we only perform static type checking, using pyright in the CI. However, there are cases where type inconsistencies might only be detected at runtime, for example:

#!/usr/bin/env python3
from typing import Any, cast
from pydantic import BaseModel, ConfigDict

class IncompatibleModel(BaseModel):
    foo: int
    bar: int

def print_class(in_dict: dict[str, Any]) -> IncompatibleModel:
    return(IncompatibleModel(foo=in_dict['name'], bar=in_dict['version']))

test_dict = {
    "name": "test",
    "version": 3
}

l = print_class(test_dict)

In this case, both mypy and pyright (static type checkers) do not notice any issues:

❯ python3 -m mypy lib/rucio/core/test.py                                                                                                          ─╯
Success: no issues found in 1 source file
❯ python3 -m pyright lib/rucio/core/test.py                                                                                                       ─╯
0 errors, 0 warnings, 0 informations 

But pydantic (runtime type checker) detects the inconsistency in the input to IncompatibleModel, and raises a ValidationError:

❯ python3 lib/rucio/core/test.py                                                                                                                  ─╯
Traceback (most recent call last):
  File "/home/rdm/tech/rucio/rucio/lib/rucio/core/test.py", line 18, in <module>
    l = print_class(test_dict)
  File "/home/rdm/tech/rucio/rucio/lib/rucio/core/test.py", line 11, in print_class
    return(IncompatibleModel(foo=in_dict['name'], bar=in_dict['version']))
  File "/home/rdm/.local/lib/python3.9/site-packages/pydantic/main.py", line 171, in __init__
    self.__pydantic_validator__.validate_python(data, self_instance=self)
pydantic_core._pydantic_core.ValidationError: 1 validation error for IncompatibleModel
foo
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='test', input_type=str]
    For further information visit https://errors.pydantic.dev/2.6/v/int_parsing

The biggest use case for this is API validation, which AFAIK exists in Rucio but it's currently disabled.

I would initially suggest that we could enable something like pydantic and just logging the ValidationErrors raised (e.g. see the try/except logic here: https://docs.pydantic.dev/latest/concepts/models/#extra-fields) - nothing would change functionally, but we would be able to detect any runtime type inconsistencies.

Motivation

No response

Change

No response

@rdimaio rdimaio changed the title Typing: consider runtime type checking for Rucio Runtime type checking, Pydantic, SQLModel Mar 18, 2024
@rdimaio
Copy link
Contributor Author

rdimaio commented Mar 18, 2024

Found this library called SQLModel: https://sqlmodel.tiangolo.com/, by the same creator of FastAPI, aimed exactly for the usage of FastAPI, Pydantic and SQLAlchemy together. Will test around with this on a feature branch on my local fork.

Edit: might be best to avoid this one for now as it seems to not be production-ready (and latest release is 0.0.16) - it doesn't add any functionality on top of using pydantic+sqlalchemy, it would just have been for the convenience of not having to write separate pydantic and SQLA models (but I think that in our use case we will want to write them separately anyway). If it ever becomes production-ready, it seems simple enough to convert from SQLA+Pydantic to SQLModel, so this is something we can think about later on

@rdimaio rdimaio self-assigned this Mar 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants