Giter Club home page Giter Club logo

Comments (4)

nazrulworld avatar nazrulworld commented on July 20, 2024

First of all, thank you so much for your nice question and welcome.
AddressType is derived from AbstractType (derived from dict). Yes theoretically we can say that AddressType is looked like a plain dict wrapper, but the behavior is completely different. The AddressType is pydantic field type which is evaluating and validating input data and return Address object!
In your case if you did
address_pydantic = Address(**patient.address[0].dict())

Would you mind expanding on this design decision to have the AbstractType annotations on each of the pydantic type's fields, instead of the actual pydantic type that is seen at runtime?

Can you please make more elaborate your suggestions with example. It seems interesting to me.

from fhir.resources.

sambarnes avatar sambarnes commented on July 20, 2024

I really appreciate the prompt response!

After posting the question, I did a little more reading of the internals and found what you described above. I now see that it's the AddressType performing the validation and returning a new Address. I think I have a better idea of how it works now.

In the code that you've posted above address_pydantic = Address(**patient.address[0].dict()), mypy raises the following error:

$ mypy --config-file mypy.ini .
error: "AddressType" has no attribute "dict"
Found 1 error in 1 file (checked 50 source files)

Due to the fact that Patient.address is type-annotated as a List[AddressType] rather than List[Address]. As far as using the returned Address model, that seems to work great so far! The only issue is with type checking. For example, say I want to print the state the patient lives in:

print(patient.address[0].state)

mypy then complains with:

$ mypy --config-file mypy.ini .
error: "AddressType" has no attribute "state"
Found 1 error in 1 file (checked 50 source files)

This means I have to put casts in the code instead of offloading all typing guarantees to pydantic:

from typing import cast

address_pydantic = cast(patient.address[0])
print(address_pydantic.state)

(No mypy issues with the above)

My question (and again this may be naive as I'm not a pydantic expert at this point) is why you've chosen to separate the validators from the returned model? It seems to me that if the AddressType's validator function def __get_validators__(cls) -> "CallableGenerator": was implemented on the actual class Address(element.Element): we would be able to have type hints that are accurate to the field's type at runtime. Thus, removing the need to perform casts to satisfy mypy.

In the pydantic docs they show an example of __get_validators__(cls) being implemented on the actual type returned (similar to what I'm trying to describe above). Was there some limitation of that pattern that motivated the decision to have an AbstractType do validation instead of the returned type doing it's own validation?

I hope this clears up my question a bit, but if not no worries! Happy to clarify more if needed :)

from fhir.resources.

nazrulworld avatar nazrulworld commented on July 20, 2024

Thanks a lot for your clarification! 💯
The short answer to your question is that to avoid the python circular dependency import problem.

Honestly speaking I had also thoughts like you, but cannot find a good solution than the current one. FHIR resources relationships are a little bit complex and two-way (kind of circular) in some cases.
One example I can give you https://github.com/nazrulworld/fhir.resources/blob/master/fhir/resources/element.py and https://github.com/nazrulworld/fhir.resources/blob/master/fhir/resources/extension.py
You see that Extension class derived from Element class but Element class has field list Extension!

from fhir.resources.

sambarnes avatar sambarnes commented on July 20, 2024

Ahh that makes total sense! I had a suspicion that the complex relationships might create circular dependencies.

Appreciate the insight you've been able to provide! We'll just continue to cast for now, and maybe investigate if a small mypy plugin can be written to automatically cast to the right type during typechecks

Closing :)

from fhir.resources.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.