-
Notifications
You must be signed in to change notification settings - Fork 65
FXC-4111-Enable Tidy3dBaseModel.from_file() for various subclasses #2990
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
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the class loading mechanism by consolidating type-to-class mapping logic from individual classes (like Expression and stub classes) into the base Tidy3dBaseModel class. This allows various simulation and data types to be loaded directly using Tidy3dBaseModel.from_file() without requiring class-specific implementations.
Key changes:
- Moved
TYPE_TO_CLASS_MAPdictionary andparse_objmethod fromExpressiontoTidy3dBaseModel - Simplified
Tidy3dStub.from_file()andTidy3dStubData.from_file()to delegate to base class - Updated documentation strings to use generic type references
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| tidy3d/components/base.py | Added global TYPE_TO_CLASS_MAP and parse_obj method to enable polymorphic loading of all subclasses |
| tidy3d/plugins/expressions/base.py | Removed duplicate TYPE_TO_CLASS_MAP and parse_obj implementation now handled by base class |
| tidy3d/web/api/tidy3d_stub.py | Simplified stub loading methods to delegate to Tidy3dBaseModel.from_file() and updated docstrings |
| CHANGELOG.md | Added entry documenting the new functionality |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 files reviewed, 2 comments
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
|
@marcorudolphflex could you have a look at the failing lazy loading test 🙏 |
I have this print statement about the types currently. In both develop and this branch I get |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5 files reviewed, 2 comments
tidy3d/components/base.py
Outdated
| def parse_obj(cls, obj: dict[str, Any]) -> Tidy3dBaseModel: | ||
| """Specialized parse_obj to handle any Tidy3D component, but only if called from | ||
| ``Tidy3dBaseModel``. Otherwise, call the regular pyadantic parse_obj.""" | ||
| if cls.__fields__.get(TYPE_TAG_STR) == "Tidy3dBaseModel": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: This condition is always False. cls.__fields__.get(TYPE_TAG_STR) returns a ModelField object, not a string. Should be cls.__name__ == "Tidy3dBaseModel" instead.
| if cls.__fields__.get(TYPE_TAG_STR) == "Tidy3dBaseModel": | |
| if cls.__name__ == "Tidy3dBaseModel": |
Prompt To Fix With AI
This is a comment left during a code review.
Path: tidy3d/components/base.py
Line: 219:219
Comment:
**logic:** This condition is always False. `cls.__fields__.get(TYPE_TAG_STR)` returns a `ModelField` object, not a string. Should be `cls.__name__ == "Tidy3dBaseModel"` instead.
```suggestion
if cls.__name__ == "Tidy3dBaseModel":
```
How can I resolve this? If you propose a fix, please make it concise.
tests/test_web/test_webapi.py
Outdated
|
|
||
| assert isinstance(data, list) and len(data) == 3 | ||
|
|
||
| print([type(d) for d in data]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Remove debug print statement before merging
| print([type(d) for d in data]) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/test_web/test_webapi.py
Line: 964:964
Comment:
**style:** Remove debug print statement before merging
```suggestion
```
How can I resolve this? If you propose a fix, please make it concise.|
I guess because of this change the data[0].class.name is now |
|
If I catch that correctly, the fundamental issue is that it tries to create a |
|
Sorry @marcorudolphflex there was a bug in that state you tried. Now the test failures are exclusively due to lazy loading. |
No problem. So the issue with lazy loading is the following: In the current state of Now the question is if we want to support So I see 2 alternative solutions:
What do you think? |
|
Edit:
this option just does not work in general. The object would still be a Tidy3DBaseModel after materialization such that it would be not usable. I would prefer the other option which seems more stable. |
|
Yes if the first option works it sounds better, are you going to give it a try? |
|
I can try to do that, but actually it would be better to do that on the pydantic v2 branch as we already observed varied behavior there. |
|
Thanks, sounds good, this is not exactly urgent it's just a nice cleanup. |
| raise ValueError(f'Missing "{TYPE_TAG_STR}" in data') from exc | ||
| if not isinstance(type_value, str) or not type_value: | ||
| raise ValueError(f'Invalid "{TYPE_TAG_STR}" value: {type_value!r}') | ||
| return type_value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need all these protections LLM's like to put...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha i guess this is more of a fundamental question on error handling and how afraid we are of more verbose code 😉
Greptile Overview
Greptile Summary
This PR refactors polymorphic deserialization by centralizing type registry and parsing logic in
Tidy3dBaseModel, enabling automatic type resolution when loading files.Key changes:
TYPE_TO_CLASS_MAPfrom Expression plugin to base class__init_subclass__()parse_obj()override to dispatch to correct subclass based ontypefieldCritical issue found:
tidy3d/components/base.pyhas a logical error that breaks the intended behavior. The condition compares aModelFieldobject to a string, which will always be False, causingparse_obj()to never use the polymorphic dispatch logic.Minor issues:
Confidence Score: 1/5
tidy3d/components/base.pycontains a logic error that compares aModelFieldobject to a string literal "Tidy3dBaseModel", which will always evaluate to False. This means the polymorphicparse_obj()behavior will never be triggered when callingTidy3dBaseModel.parse_obj(), breaking the core feature this PR is intended to add. The fix is simple (change tocls.__name__ == "Tidy3dBaseModel"), but this is a critical functional bug that needs to be resolved before merging.Important Files Changed
File Analysis
TYPE_TO_CLASS_MAPregistry andparse_obj()override with critical bug in line 219 condition checkTidy3dBaseModel.from_file(). Clean refactoring with minor variable naming issueSequence Diagram
sequenceDiagram participant User participant Tidy3dBaseModel participant TYPE_TO_CLASS_MAP participant Subclass as Simulation/HeatSimulation/etc Note over Tidy3dBaseModel,Subclass: Registration Phase (at import time) Subclass->>Tidy3dBaseModel: __init_subclass__() Tidy3dBaseModel->>Tidy3dBaseModel: add_type_field() Tidy3dBaseModel->>Tidy3dBaseModel: generate_docstring() Tidy3dBaseModel->>TYPE_TO_CLASS_MAP: Register type -> class mapping Note over TYPE_TO_CLASS_MAP: {"Simulation": Simulation,<br/>"HeatSimulation": HeatSimulation, ...} Note over User,Subclass: Loading Phase (from_file) User->>Tidy3dBaseModel: from_file("sim.json") Tidy3dBaseModel->>Tidy3dBaseModel: dict_from_file("sim.json") Tidy3dBaseModel->>Tidy3dBaseModel: parse_obj({"type": "HeatSimulation", ...}) Note over Tidy3dBaseModel: BUG: Line 219 condition always False Tidy3dBaseModel->>TYPE_TO_CLASS_MAP: Get class for "HeatSimulation" TYPE_TO_CLASS_MAP-->>Tidy3dBaseModel: HeatSimulation class Tidy3dBaseModel->>Subclass: HeatSimulation(**obj) Subclass-->>User: HeatSimulation instance