-
Notifications
You must be signed in to change notification settings - Fork 78
Add cross-platform LocalTarget with macOS and Linux support #729
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: master
Are you sure you want to change the base?
Conversation
marcbonnici
left a comment
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.
Hi,
Thank you very much for the pull request. I had some initial high level design questions with regards to the new Target.
Thanks
devlib/target.py
Outdated
| self.working_directory = '/tmp/devlib-target' | ||
|
|
||
|
|
||
| class LocalTarget(Target): |
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.
I noticed that LocalTarget is subclassing Target directly rather than LinuxTarget or LocalLinuxTarget and was curious for the rationale?
It seems that with the current approach we have a lot of code duplication from the existing targets and if we were to subclass, for example LocalLinxTarget, then we'd be able to reuse the existing Linux implementations when we're running on a Linux platform (or the Mac implementation is the same) and we could maintain a single source for common operations.
For example in the os_version method of LocalTarget we have a different implementation than what we have in LinuxTarget [1].
Similarly for system_id[2][3], host_id[4] etc. we now have have more than one implementations attempting to achieve the same functionality (some times with differing results) rather than just calling into the parent class and handling the mac specific scenario separately.
[1]
Line 1794 in 9c4f09b
| def os_version(self): |
[2]
Line 1806 in 9c4f09b
| def system_id(self): |
[3]
devlib/devlib/bin/scripts/shutils.in
Line 331 in 9c4f09b
| get_linux_system_id() { |
[4]
Line 192 in 9c4f09b
| def hostid(self): |
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.
I made a commit now trying to resolve all your feedbacks
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.
also, feel free to make commits if you find something that can be fixed (I don't have much knowledge of the code base so I might have made a mistake, I'm just trying to help)
devlib/target.py
Outdated
|
|
||
|
|
||
| # Keep LocalMacTarget as an alias for backward compatibility | ||
| LocalMacTarget = LocalTarget |
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.
Additionally I see previously this was split out from a LocalMacTarget.
I'm curious if there is a specific benefit for merging these two Linux/Mac targets together?
It seems from a code readability aspect it would be cleaner to keep separate LocalMacTarget and LocalLinuxTarget's and let a user choose the appropriate target based on their chosen system?
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.
I agree with you. keeping LocalMacTarget and LocalLinuxTarget separate would indeed make the code more readable and give users a clearer choice depending on their system.
|
This sort of thing is a common failure mode for OO approaches:
AFAICT this is implementing that aspect:
This is really not in the benefits category. If all target classes were merged into a single class like this one with a bunch of This could be replaced by having a class that instantiate another class chosen dynamically and redirects all method attribute lookup to that internal one using e.g. Once this is done, a This way we keep the fundamental design property of devlib that each target class is specialized in a single OS, with the exception of a "dispatch" target that just redirects to an actual implementation. Note that this design is what we implemented in LISA, where there is a single user-facing If there is any code that makes sense to actually share, it can be split out in separate private standalone functions called by both Linux and Mac targets. EDIT: adding to that, the dispatching class would probably benefit from having a metaclass that implements |
|
Additionally if we start supporting OSes that are not based on the Linux kernel, there needs to be a way to fence the code that makes this assumption:
The module problem is actually 2-fold:
|
douglas-raillard-arm
left a comment
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.
Some generic comments that would likely stay relevant regardless of future refactoring. It's more things to keep in mind while reworking the code than something to address on the current PR version.
devlib/target.py
Outdated
| else: | ||
| return 'unknown' | ||
| except TargetStableError: | ||
| return 'unknown' |
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.
Would be best to just raise an exception here. Otherwise, an update of devlib that brings support for another OS will become a breaking change, as code running on that OS will go from working with "unknown" to working with "foobar". If an exception is raised, either the calling code genuinely has a fallback that is just a fallback, or the exception would bubble and the code would simply not work, until the day devlib supports that platform.
devlib/target.py
Outdated
| return {} | ||
| else: | ||
| # Use parent implementation for Linux and other systems | ||
| return super(LocalTarget, self).os_version |
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.
super(LocalTarget, self) is just super() in this context. Arguments are only needed when:
- The parser does not provide the interpreter enough context (e.g. in a nested function).
- When trying to achieve something unusual (not following the normal MRO)
- When trying to be compatible with Python 2 (official eol in 2020, devlib has dropped support for it a long time ago)
devlib/target.py
Outdated
|
|
||
| cpuinfo_text.append('\n'.join(section)) | ||
|
|
||
| return Cpuinfo('\n\n'.join(cpuinfo_text)) |
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.
A new class that allows passing the various components explicitly is needed here. This would be a base class of the current Cpuinfo, and the latter could simply parse the text format in its __init__. That base class would be used directly here, or we can make a subclass that does essentially nothing to keep the base private.
The only issue with that scheme is that isinstance(x, Cpuinfo) would now be inaccurate, but I don't think anyone relies on that as there is only a single Cpuinfo class currently.
| value = str(value) | ||
|
|
||
| if verify: | ||
| # Use the same verification logic as the parent class but with native commands |
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.
but with native commands
What is the advantage for that ? The main reason we use busybox everywhere in devlib is so that we know what behaviour to expect. While a mac target has to deal with only one OS rather than multiple for linux-based code, there may still be changes from one version to another as we have painfully learnt with android over the years.
This PR introduces the new
LocalTargetclass, which unifies local target handling across macOS and Linux. Fix #728.Key changes include:
Benefits:
Let me know your thoughts. Happy to help.