Skip to content
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

modification of TIME data type #311

Merged
merged 11 commits into from
Sep 15, 2021
Merged

Conversation

Yingliangzhe
Copy link
Contributor

I have modified the code little bit and added some tests to solve #310

snap7/util.py Outdated
>>> snap7.util.set_dint(data, 0, '-22:3:57:28.192')

>>> snap7.util.set_time(data, 0, '-22:3:57:28.192')

>>> data
bytearray(b'\x8d\xda\xaf\x00')
"""
import re
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import statement is still not needed, since it is already imported at the top of the file.

@Yingliangzhe
Copy link
Contributor Author

Could the errors from Mypy be ignored? :)
I could not understand, the marked position is wrong.

@Yingliangzhe
Copy link
Contributor Author

@gijzelaerr Could you please merge the new version to master? Thank you!

snap7/util.py Outdated Show resolved Hide resolved
snap7/util.py Outdated
minutes: int = int(data_list[2])
seconds: int = int(data_list[3])
milli_seconds: int = int(data_list[4])
if re.split(r'(\d+)$', days)[0:2][0] == '-':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same, but a little more readable, imho.

Suggested change
if re.split(r'(\d+)$', days)[0:2][0] == '-':
if re.match('^-\d{1,2}$', days):

snap7/util.py Outdated
Comment on lines 663 to 668
if abs(int(days)) <= 24 and hours <= 23 and minutes <= 59 and seconds <= 59 and milli_seconds <= 999:
if int(days) * sign == 24 and hours > 20 and minutes > 31 and seconds > 23 and milli_seconds > 647 or \
int(days) * sign == -24 and hours > 20 and minutes > 31 and seconds > 23 and milli_seconds > 648:
raise ValueError('time value out of range, please check the value interval')

time_int = ((int(days) * sign * 3600 * 24 + (hours % 24) * 3600 + (minutes % 60) * 60 + seconds % 60) * 1000 + milli_seconds) * sign
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good bulletproof check, but this code is not easy to read (at least for me). It may be better to calculate the result first and then check the range. It is less efficient, but more readable.

Suggested change
if abs(int(days)) <= 24 and hours <= 23 and minutes <= 59 and seconds <= 59 and milli_seconds <= 999:
if int(days) * sign == 24 and hours > 20 and minutes > 31 and seconds > 23 and milli_seconds > 647 or \
int(days) * sign == -24 and hours > 20 and minutes > 31 and seconds > 23 and milli_seconds > 648:
raise ValueError('time value out of range, please check the value interval')
time_int = ((int(days) * sign * 3600 * 24 + (hours % 24) * 3600 + (minutes % 60) * 60 + seconds % 60) * 1000 + milli_seconds) * sign
time_int = ((int(days) * sign * 3600 * 24 + (hours % 24) * 3600 + (minutes % 60) * 60 + seconds % 60) * 1000 + milli_seconds) * sign
if time_int < -2147483648 or time_int > 2147483647:
raise ValueError('time value out of range, please check the value interval')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wouldn't solve problems like "negative seconds".

time_string must match with a strict pattern, before stuff is splitted. Otherwise stuff will break.
There could be other advantages, if the string was checked properly first, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@swamper123 Yes, as I wrote this function, I also thought, in which format the time_string should be.
I just use the format as the return value from get_time().

Copy link
Contributor

@swamper123 swamper123 Sep 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Yingliangzhe The format is totally fine and I would have made the same way, if machines return it like that.
But unfortunatly, the Dr. Evils and "DAU"s (like germans say 😉 ) like to break things. So inputs should be bulletproof. ^^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nikteliy this piece of code, you suggested, cannot cover the case, if I write '-24:25:30:23:193' to time_string.
As intermediate result of time_int, it would be -2079023193 and still inside of the interval [-2147483648, 2147483647], but this time format should not be acceptable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, my mistake. I give up then :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re.fullmatch(r"-?([2][0-4]|[1]\d|\d):([2][0-3]|[1]\d|\d):([1-5]\d|\d):([1-5]\d|\d):\d{1,3}.\d{1,3}", time_str)

This should check all legit patterns (I needed a while to get in), but not if min/max is reached (because if the day is 24, hours shouldn't be greater than 20 .... well it's my first thought, but I got an idea. ^^

Copy link
Contributor

@swamper123 swamper123 Sep 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Yingliangzhe Could you verify if this is legit, even with min/max values?

if re.fullmatch(r"(-?(2[0-3]|1?\d):(2[0-3]|1?\d|\d):([1-5]?\d):[1-5]?\d.\d{1,3})|"
                 r"(-24:(20|1?\d):(3[0-1]|[0-2]?\d):(2[0-3]|1?\d).(64[0-7]|6[0-3]\d|[0-5]\d{1,2}))|"
                 r"(24:(20|1?\d):(3[0-1]|[0-2]?\d):(2[0-3]|1?\d).(64[0-8]|6[0-3]\d|[0-5]\d{1,2}))"

Copy link
Contributor

@swamper123 swamper123 Sep 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clear this thing a bit up, each line is a case (normal, min, max):

  1. (-)0-23 days : 0-23hours : 0-59minutes : 0-59seconds . 0-999 miliseconds
  2. -24 days : 0-20hours: 0-31 minutes: 0-23 seconds. 0-647 milliseconds
  3. 24 days : 0-20hours: 0-31 minutes: 0-23 seconds. 0-648 milliseconds

(at least I hope it matches, which would be great)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @swamper123,
sorry for the late answer, I have checked the solution you suggested.
I don't think, it has no problem by interpreting the TIME data type.
But, as far as I remember, the max value of TIME, the milliseconds should be 0 - 647, and the min value should be 0 - 648. I have changed the corresponding position.

snap7/util.py Outdated
Comment on lines 669 to 671
if sign < 0:
time_int = (1 << bits) + time_int
bytes_array = time_int.to_bytes(4, byteorder='big')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sign check can be replaced by passing a parameter signed=True to the method .to_bytes().

Suggested change
if sign < 0:
time_int = (1 << bits) + time_int
bytes_array = time_int.to_bytes(4, byteorder='big')
bytes_array = time_int.to_bytes(4, byteorder='big', signed=True)

Yingliangzhe and others added 3 commits September 9, 2021 11:42
@Yingliangzhe
Copy link
Contributor Author

Hello @gijzelaerr,
this version should fix the #310. Could you please check and merge it to master?
Thank you.

@gijzelaerr gijzelaerr merged commit dc53f4a into gijzelaerr:master Sep 15, 2021
@gijzelaerr gijzelaerr added this to the 1.2 milestone Oct 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants