Memorized DOMAIN ObjectType for a proper export#655
Memorized DOMAIN ObjectType for a proper export#655friederschueler merged 2 commits intocanopen-python:masterfrom
Conversation
Changed to save whether a Variable has ObjectType==DOMAIN while importing an EDS, so that it is possible to export it unchanged.
bizfsc
left a comment
There was a problem hiding this comment.
Looking good. As far as I can check it, no new problems introduced for mypy.
friederschueler
left a comment
There was a problem hiding this comment.
Good fix for a real round-trip data-loss bug. The overall approach — adding is_domain on import and using it on export — is clean and well-tested.
A few small points:
- Two places in
eds.pyhave missing spaces around==inside a keyword argument (see inline comments). - The new boolean assertions in the tests would be more idiomatic as
assertFalse/assertTrue. - Worth considering storing the full
object_typeinteger instead of just a boolean, but that is a larger API change and not required for this fix.
|
|
||
| if object_type in (objectcodes.VAR, objectcodes.DOMAIN): | ||
| var = build_variable(eds, section, node_id, index) | ||
| var = build_variable(eds, section, node_id, index, is_domain=object_type==objectcodes.DOMAIN) |
There was a problem hiding this comment.
PEP 8: missing spaces around the == comparison inside the keyword argument.
| var = build_variable(eds, section, node_id, index, is_domain=object_type==objectcodes.DOMAIN) | |
| var = build_variable(eds, section, node_id, index, is_domain=object_type == objectcodes.DOMAIN) |
There was a problem hiding this comment.
I've changed it, but for me, it is incredibly misleading: you are giving "priority" to the assignment instead of the operation that is performed before.
A possible solution would be is_domain=(object_type == objectcodes.DOMAIN), but Pylint complains about the unnecessary parentheses.
For me, the proper way to write it would be is_domain = object_type==objectcodes.DOMAIN.
I've never understood why PEP 8 requires no spaces for "=" in function invocations...
| object_type = int(eds.get(section, "ObjectType"), 0) | ||
| except NoOptionError: | ||
| object_type = objectcodes.VAR | ||
| var = build_variable(eds, section, node_id, index, subindex, is_domain=object_type==objectcodes.DOMAIN) |
There was a problem hiding this comment.
Same PEP 8 spacing issue as above.
| var = build_variable(eds, section, node_id, index, subindex, is_domain=object_type==objectcodes.DOMAIN) | |
| var = build_variable(eds, section, node_id, index, subindex, is_domain=object_type == objectcodes.DOMAIN) |
| self.assertEqual(var.name, 'Producer heartbeat time') | ||
| self.assertEqual(var.data_type, canopen.objectdictionary.UNSIGNED16) | ||
| self.assertEqual(var.access_type, 'rw') | ||
| self.assertEqual(var.is_domain, False) |
There was a problem hiding this comment.
Nit: for boolean checks the unittest idiom is assertFalse/assertTrue rather than assertEqual(..., False/True). Same pattern applies to the other four analogous assertions added in this PR.
| self.assertEqual(var.is_domain, False) | |
| self.assertFalse(var.is_domain) |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
@friederschueler please use the "Squash and merge" GitHub function for PRs, with a sensible, hand-checked commit message. In this case, I hadn't even got around to looking at the PR contents, so I'd like a bit more time before you merge future contributions. Thank you! 🙂 |
|
@acolomb I am sorry, this was muscle memory from work. I forgot we use hand-crafted messages. I personally think that the automated PR merge messages are just fine, because the PR should be named in a good way. Also isn't squash commit the default? I will also give you more time to review. |
| object_type = int(eds.get(section, "ObjectType"), 0) | ||
| except NoOptionError: | ||
| object_type = objectcodes.VAR | ||
| var = build_variable(eds, section, node_id, index, subindex, is_domain=object_type == objectcodes.DOMAIN) |
There was a problem hiding this comment.
This is certainly beyond a sensible line length limit. ;-)
I've codified 96 chars as a guideline in #660, please try to stick to that in future contributions.
|
|
||
| if object_type in (objectcodes.VAR, objectcodes.DOMAIN): | ||
| var = build_variable(eds, section, node_id, index) | ||
| var = build_variable(eds, section, node_id, index, is_domain=object_type == objectcodes.DOMAIN) |
|
|
||
|
|
||
| def build_variable(eds, section, node_id, index, subindex=0): | ||
| def build_variable(eds, section, node_id, index, subindex=0, is_domain=False): |
There was a problem hiding this comment.
Frankly I don't particularly like this function signature. The is_domain attribute could be set directly on the resulting object instead of adding a new call parameter.
Or even better, pass the whole object_code value and have the logic for the boolean attribute here in this function. That's why we have this function with centralized logic.
While working with an EDS that had DOMAIN objects, I've noted that when imported and exported using this library, all DOMAIN Objects were converted to normal Variables.
While importing an EDS, I've changed to save whether a Variable was created from an object with
ObjectType==DOMAIN. In this way, it is possible to export it unchanged with the proper ObjectType value.