-
Notifications
You must be signed in to change notification settings - Fork 2
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
Teresadev #14
base: main
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.
In general looks fine.
I would recommend moving any code to the src/
directory so it's organized a bit more and can later be grouped into a callable python module.
Left other comments to be addressed as well.
from enum import Enum | ||
|
||
class Commands(Enum): | ||
'''Get power supply unit model. Response: ZXY-6005S''' |
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.
The syntax of '''
qutations in a row are usually reserved for python docstrings.
For inline comments use #
Suggested for line 12 and similar scenarios:
MODEL = 'a' # Get power supply unit model. Response: ZXY-6005S
import serial.tools.list_ports | ||
from enum import Enum | ||
|
||
class Commands(Enum): |
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.
See comment on the power supply class for in-depth detail on docstrings, but for Enums specifically, it looks nicer if the Enum pairs are defined in one doctring like so:
class Commands(Enum):
'''
:param MODEL: Description of param
:type MODEL: str
'''
SET_OUTPUT = 'so' | ||
|
||
|
||
class ZXY6005S: |
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.
Docstrings in general are greatly encouraged for:
- Public Functions (which are by default all functions in python)
- Class Definitions
Suggested add for this class and similar definitions
class ZXY6005S:
'''
A short description of what the class does.
:param MODEL: Get power supply unit model. Response: ZXY-6005S
:param FIRMWARE_VERSION: Get firmware version. Response: R2.7Z
'''
def __some_function__(param1, param2) -> int:
'''
A short description of what the function does.
:param param1: Description of param1
:param param2: Description of param2
:returns: Description of what is returned
:rtype: int
''''
...
STOPBITS = serial.STOPBITS_ONE | ||
TIMEOUT = 1 | ||
|
||
def __init__(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.
Is this class intended to manage the state of all three power supplies at the same time? Or just one supply and have three instances?
Personally, I would recommend the latter of the two because this scopes the purpose of the class and you can use handy things in client code such as:
for p in [supply_1, supply_2, supply_3]:
p.send_command(...)
TIMEOUT = 1 | ||
|
||
def __init__(self): | ||
'''construct objects, using location for X, Y, and Z power supplies''' |
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.
It is also recommended that parameters such as device location/name is a configurable item for the constructor as this could change with different supplies or different environment configurations. It is also acceptable to add defaults to the initializers if they are generic settings that may be the same across environments.
Example:
def __init__(self, dev_1: str = '/dev/TTYUSBS10'):
...
timeout = self.TIMEOUT, | ||
) | ||
|
||
def write_message(self, device_name, msg): |
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.
Since this object seems to be a stateful object It may make sense to store the device name as an attribute on the object so it can be omitted as a parameter here.
Same applies to all similar functions below.
self.write_message(device_name, msg) | ||
return self.read_message(device_name) | ||
|
||
def create_command(self, command): |
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.
This is actually excellent that you've separated the command generation from the command sending.
The core functionality of this class, (i.e. directly communicating with the power supply on a serial channel), is not really unit-testable. However the most important part that we can unit-test is making sure that the commands are being generated correctly per the power-supply spec.
I would recommend making a set of unit tests around this function asserting that this function generates all of the correct things else fails safely in a way that will stop it from being sent to the PSU otherwise.
if reply != msg.decode().strip(): | ||
raise ValueError(f'Invalid reply was {reply}, expected {msg.decode().strip()}') | ||
|
||
def return_amp_hour(self, device_name: str) -> str: |
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.
For getters and setters I would recommend either the verbiage get/set
or if you wanted to get fancy, (and more pythonic), you could also do:
@amp_hour.setter
def amp_hour(self, value) -> None:
<methods to set value>
@amp_hour.getter
def amp_hour() -> str:
return <value>
So that calling code would look like:
supply_1.amp_hour = '1.3'
print(supply_1.amp_hour)
Adding ZXY6005S Powersupply Driver