Implement Python dict to C++ AnyMap conversion#1014
Implement Python dict to C++ AnyMap conversion#1014bryanwweber merged 12 commits intoCantera:mainfrom
Conversation
787133f to
1afcdbe
Compare
Also, add missing case for conversion of list of dictionaries
Codecov Report
@@ Coverage Diff @@
## main #1014 +/- ##
==========================================
+ Coverage 72.39% 72.53% +0.14%
==========================================
Files 364 364
Lines 46433 46750 +317
==========================================
+ Hits 33616 33911 +295
- Misses 12817 12839 +22
Continue to review full report at Codecov.
|
|
Well, I had a good portion of this implemented, as it is the logical extension to #984, but I guess you beat me to opening a PR. I pushed my work-in-progress on this to my set-user-data branch in case it's of any use. |
|
@speth ... I believe some of your ideas made the code simpler (especially using |
Simplify code using: * explicit type conversions * leverage of set properties Co-authored-by: Ray Speth <[email protected]>
Remove tests for unhandled cases that are now handled
|
I updated the implementation on my branch, following on from what you have here. This version achieves a couple of things:
I hope you're willing to take this as a friendly amendment. If so, you can push those commits to this branch and we can continue the review from there (and of course you or @bryanwweber should provide a review of my changes). |
5774c40 to
9e12518
Compare
|
@speth ... I did a hard reset to your branch, so I believe at this point both of our ideas are blended. Overall, I have no objections to adopting the composite implementation, @bryanwweber ... it's up to you to review I guess, as @speth's friendly amendments are an improvement over my initial code, and I'm ok with them (Edit: my comments below are intended to clarify my points above). As an aside: @speth in case any changes come up, feel free to push directly to my branch. |
|
I'll take a look later this week after I finish this round of grading. |
9e12518 to
453ee47
Compare
bryanwweber
left a comment
There was a problem hiding this comment.
Relatively minor changes here, thanks @ischoegl!
| itype = set() | ||
| for i in item: | ||
| if isinstance(i, dict): | ||
| itype.add(dict) | ||
| elif isinstance(i, list) or isinstance(i , tuple): | ||
| itype.add(list) | ||
| elif type(i) == bool: | ||
| itype.add(bool) # otherwise bools will get counted as integers | ||
| elif isinstance(i, numbers.Integral): | ||
| itype.add(numbers.Integral) | ||
| elif isinstance(i, numbers.Real): | ||
| itype.add(numbers.Real) | ||
| else: | ||
| itype.add(type(i)) | ||
|
|
||
| if itype == {numbers.Real, numbers.Integral}: | ||
| itype = {numbers.Real} |
There was a problem hiding this comment.
2 questions here:
- Are the first two conditions needed? It seems as though
itype.add(type(i))would do well enough for those. - For the numbers, could you combine that condition? Since you reduce the set to
numbers.Realat the end anyways. Or is there a use to having justnumbers.Integralas the type?
It might be worth adding comments that answer these questions, for any future readers.
There was a problem hiding this comment.
I can see from code below that the answer to question 2 is, yes there is a use to having numbers.Integral as the type.
There was a problem hiding this comment.
Ad (1) ... I don't believe that the two conditions can be merged. Of course the second one can be simplified to isinstance(i, (list, tuple)).
There was a problem hiding this comment.
@ischoegl is right that list + tuple check can be combined.
The reason for not just using itype.add(type(i)) is that I want to treat any type that inherits from dict as a dict, and likewise any types inheriting from list or tuple are essentially list-like for the purpose of serialization. I added a few comments to this effect.
453ee47 to
69b635b
Compare
|
@bryanwweber ... thanks for the review! I believe I resolved everything, so this should be ready to merge. The two comments where I left responses 'unresolved' pertain to code @speth (re-)wrote, so if there are remaining questions, I'll defer to him. |
* Clarify empty AnyValue * Fix docstrings * Address review comments
69b635b to
87ad140
Compare
|
@bryanwweber ... I hope I was able to clarify the discrepancy between |
|
@bryanwweber ... any additional questions? I am mostly done rebasing #995 to include serialization (i.e. assuming that this would get merged before). |
|
I responded to two of the open threads. I didn't have anything to add to the third -- I think it's all set now, right? |
|
@speth … thank you for your comments! All set from my side too. |
|
🎉 ... thanks, @bryanwweber (and @speth) |
Changes proposed in this pull request
This PR adds the ability to create C++
AnyMapandAnyValueobjects from the Python interface, wheredict_to_anymap/python_to_anyvaluemirrors recently introducedanymap_to_dict/anyvalue_to_python(see PR #984). The following uses are anticipated:--extrafields in YAML serialization, see Serialization of root-level information in YAML #1013The new service functions enable the use of C++ constructors (or other C++ functions) that take
AnyMaporAnyValueas an argument from the Cython layer. Round-trip conversion is covered by unit tests via a hidden helper functioncantera._cantera._py_to_any_to_pyin a newtest_utils.pyjob. Beyond, the functions are not accessible from the Python API, as they are internal service functions that facilitate the transfer of data from Python to the C++ layer.Checklist
scons build&scons test) and unit tests address code coverage