I am new to python so tips to any part of the code are welcome.
My main problem is how to "overload" the function properly. Is this how supposed to be done with parameters that gets passed exculsivly? It is intended that only Bytes, Words or a DWord will get passed in the corresponding parameter. (If multiple are passed the longest one is prefered. Sidenote: The naming is based on an old 16bit processor thats why word is 16 bit and Dword is 32)
I also wanted to make the range check of the optional arguments in the beginning but as I default them to None, I had to check for None in the first place before I can check the range and this would make the None check redundant.
I had something like max(Word1,Word2) >= 2**16
in mind, because I hoped in python the max would yield None and the larger would give false, but > is not implemented for None. So to get it to work I used the check for None first. But this seems not elegant.
Afterwards I assign the bigger datachunks to Bytes and raise Errors if the data didn't fit in the range of the type. If nothing is passed the Data is set to 0 to fill up the array in the end.
If no length was given the length calculated by the checks is used.
In the end all the data gets packed into a bytearray (the Message to be sent later). Because bytearray() checks if the elements are in range, the Bytes are not checked seperatly.
Is there a more pythonic way to do it?
def packMessage(DeviceID, Offset, dataLength=None,
Byte0=None, Byte1=None, Byte2=None, Byte3=None,
Word0=None, Word1=None, DWord0=None):
Bytes = [Byte0, Byte1, Byte2, Byte3]
length = 0
# check if the values to be used are in range
if Offset >= 2**16:
raise ValueError
else:
Offset_low = Offset & 0x00FF
Offset_high = (Offset & 0xFF00) >> 8
if dataLength is not None and not 1 <= dataLength <= 4:
raise ValueError
# split bigger data to bytes and check the data length
if DWord0 is not None:
if 0 <= DWord0 <= 2**32:
Bytes[0] = DWord0 & 0xFF
Bytes[1] = (DWord0 & 0xFF00) >> 8
Bytes[2] = (DWord0 & 0xFF0000) >> 16
Bytes[3] = (DWord0 & 0xFF000000) >> 24
length = 4
else:
raise ValueError
elif Word0 is not None:
if 0 <= Word0 <= 2**16:
Bytes[0] = Word0 & 0xFF
Bytes[1] = (Word0 & 0xFF00) >> 8
else:
raise ValueError
if Word1 is not None:
if 0 <= Word1 <= 2**16:
Bytes[2] = Word1 & 0xFF
Bytes[3] = (Word1 & 0xFF00) >> 8
length = 4
else:
raise ValueError
else:
Word1 = 0
Bytes[2] = Bytes[3] = 0
length = 2
else:
for i in range(len(Bytes)):
if Bytes[i] is not None:
length = i
else:
Bytes[i] = 0
# if no length given take calculated length
if dataLength is None:
dataLength = length
# return the Message
return bytearray([DeviceID, dataLength, Offset_low,
Offset_high, Bytes[0], Bytes[1], Bytes[2], Bytes[3]])
Side note: I decided that the compare order of the Bytes doesn't matter that much so I ditched it for now and replaced it with a loop for now.
It looked like this before:
if Byte0 is not None:
if Byte1 is not None:
if Byte2 is not None:
if Byte3 is not None:
length = 4
else:
Byte3 = 0
else:
length = 3
Byte2 = 0
Byte3 = 0
else:
length = 2
Byte1 = 0
Byte2 = 0
Byte3 = 0
else:
length = 1
Byte0 = 0
Byte1 = 0
Byte2 = 0
Byte3 = 0
I don't see a nice way to wrap this up. So If there is a beautiful solution for this let me know, otherwise feel free to ignore it.