Custom Options for EDS file#615
Conversation
Allowed to Read/Write options not defined by the EDS Standard.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
Thanks for adding custom options support! I reviewed the changes and have a few observations: 1. Duplicate For
The second call overwrites the first. One of them should be removed. Since 2. The list is missing at least:
Any standard option not in this list will incorrectly end up in 3. No tests It would be great to add a test that:
4. Typo fix should be a separate commit The |
|
Hi, |
|
@FedericoSpada no problem at all, I created a new PR (#653) because I can not edit your fork. |
|
Sorry for not reacting earlier, there is definitely interest in your work @FedericoSpada. Just not enough spare time on my side to work on the backlog regarding this library. I'm planning on it though in the next few days. Good to see @bizfsc picking it up and pushing it forward. |
- Resolved double function invocation - Added forgotten standard options and made the check case-insensitive - Reverted minor changes not related to the main focus of the PR
|
I've implemented the requested changes. |
acolomb
left a comment
There was a problem hiding this comment.
Thank you very much for this contribution. Structurally, I think it's alright and a useful addition. There are some issues regarding code style though, especially the missing type hints. While that could be easily fixed, I think #653 and #654 are already more extensive and a bit cleaner, so let's continue on those instead.
Still added some comments here as guidance, mostly also relevant for the other PRs.
| self.subindices = {} | ||
| self.names = {} | ||
| #: Key-Value pairs not defined by the standard | ||
| self.custom_options = {} |
There was a problem hiding this comment.
For new code, we require proper typing hints now, to avoid an ever-growing error list from the mypy checker. (Same thing below.)
| self.custom_options = {} | |
| self.custom_options: dict[str, str] = {} |
There was a problem hiding this comment.
I always copy the format of existing code.
Maybe it is worth the effort to type-hint the whole library.
| _STANDARD_OPTIONS = ["objecttype" , "parametername" , "datatype" , "accesstype" , | ||
| "pdomapping" , "lowlimit" , "highlimit" , "defaultvalue" , | ||
| "parametervalue" , "factor" , "description" , "unit" , | ||
| "storagelocation" , "compactsubobj" , "nrofentries" , "subnumber" , | ||
| "objflags" , "denotation" ] | ||
|
|
There was a problem hiding this comment.
This is definitely funky formatting. We mostly follow "black" style, though not strictly enforded. A simple list, one item per row, would be fine here, however. Makes it easier to insert grouping comments.
As for the name, I think KNOWN_OBJECT_OPTIONS would be a better fit, as some of these are not strictly standard. And we don't strictly need to mark them "internal", thus moving toward the top of the file and removing the underscore seems appropriate.
This would be my approach, sorted as in CiA 306:
| _STANDARD_OPTIONS = ["objecttype" , "parametername" , "datatype" , "accesstype" , | |
| "pdomapping" , "lowlimit" , "highlimit" , "defaultvalue" , | |
| "parametervalue" , "factor" , "description" , "unit" , | |
| "storagelocation" , "compactsubobj" , "nrofentries" , "subnumber" , | |
| "objflags" , "denotation" ] | |
| KNOWN_OBJECT_OPTIONS = [ | |
| # EDS generic: | |
| "parametername", | |
| "objecttype", | |
| "datatype", | |
| "accesstype", | |
| "defaultvalue", | |
| "pdomapping", | |
| "subnumber", | |
| "lowlimit", | |
| "highlimit", | |
| "objflags", | |
| "compactsubobj", | |
| "nrofentries", | |
| # DCF only: | |
| "parametervalue", | |
| "uploadfile", | |
| "downloadfile", | |
| "denotation", | |
| # nonstandard extensions: | |
| "factor", | |
| "unit", | |
| "description", | |
| "storagelocation", | |
| ] |
| "storagelocation" , "compactsubobj" , "nrofentries" , "subnumber" , | ||
| "objflags" , "denotation" ] | ||
|
|
||
| def _get_custom_options(eds, section): |
There was a problem hiding this comment.
Type hints, please, for new code.
| def _get_custom_options(eds, section): | ||
| custom_options = {} | ||
| for option, value in eds.items(section): | ||
| if not (option.lower() in _STANDARD_OPTIONS or option.isdigit()) : |
There was a problem hiding this comment.
Please pay attention to code formatting. The space before : violates PEP-8 for example. Having some linters running in the background really helps to catch these problems early, so I recommend it (flake8 and black --diff for example).
Same thing with the number of blank lines between top-level definitions, btw.
| self.storage_location = None | ||
| self.subindices = {} | ||
| self.names = {} | ||
| #: Key-Value pairs not defined by the standard |
There was a problem hiding this comment.
The library already uses some nonstandard options, so the description is a bit misleading. We should call them "not handled explicitly" instead.
| custom_options = {} | ||
| for option, value in eds.items(section): | ||
| if not (option.lower() in _STANDARD_OPTIONS or option.isdigit()) : | ||
| custom_options[option] = value |
There was a problem hiding this comment.
This whole function would be a good candidate for a dict comprehension instead of an explicit loop.
There was a problem hiding this comment.
I think it would be too complicated/long:
{option: value for option, value in eds.items(section) if not (option.lower() in _STANDARD_OPTIONS or option.isdigit())}
Vector CANeds tool groups all unknown options contained in an EDS File in a dedicated section called "Unknown Entries".
We use that section to save additional information that is not considered by the CANopen specifications (for example: unit, factor, offset, category, etc.), and so I had to modify this library to read and write those options.
If you open a file that contains unknown option names, they will be grouped in the "custom_options" dictionary.
If you desire to save a value with a specific option name, you can update the "custom_options" dictionary accordingly.
P.S.: In the meantime, I've improved some of the bad code.