Skip to content

Commit 9ee4f2a

Browse files
interval: validate limits
Before this patch, any value was allowed for interval attributes. Now we use the same rules as in Tarantool. A couple of issues were met while developing this patch, follow [1, 2] for core updates. 1. tarantool/tarantool#8878 2. tarantool/tarantool#8887
1 parent a668059 commit 9ee4f2a

File tree

3 files changed

+398
-0
lines changed

3 files changed

+398
-0
lines changed

Diff for: CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## Unreleased
88

9+
### Changed
10+
- Validate `tarantool.Interval` limits with the same ruels as in Tarantool.
11+
912
### Fixed
1013
- `tarantool.Interval` arithmetic with weeks
1114
- `tarantool.Interval` weeks display in `str()` and `repr()`

Diff for: tarantool/msgpack_ext/types/interval.py

+58
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,60 @@
1616
8: 'adjust',
1717
}
1818

19+
# https://github.com/tarantool/tarantool/blob/ff57f990f359f6d7866c1947174d8ba0e97b1ea6/src/lua/datetime.lua#L112-L146
20+
SECS_PER_DAY = 86400
21+
22+
MIN_DATE_YEAR = -5879610
23+
MIN_DATE_MONTH = 6
24+
MIN_DATE_DAY = 22
25+
MAX_DATE_YEAR = 5879611
26+
MAX_DATE_MONTH = 7
27+
MAX_DATE_DAY = 11
28+
29+
AVERAGE_DAYS_YEAR = 365.25
30+
AVERAGE_WEEK_YEAR = AVERAGE_DAYS_YEAR / 7
31+
INT_MAX = 2147483647
32+
MAX_YEAR_RANGE = MAX_DATE_YEAR - MIN_DATE_YEAR
33+
MAX_MONTH_RANGE = MAX_YEAR_RANGE * 12
34+
MAX_WEEK_RANGE = MAX_YEAR_RANGE * AVERAGE_WEEK_YEAR
35+
MAX_DAY_RANGE = MAX_YEAR_RANGE * AVERAGE_DAYS_YEAR
36+
MAX_HOUR_RANGE = MAX_DAY_RANGE * 24
37+
MAX_MIN_RANGE = MAX_HOUR_RANGE * 60
38+
MAX_SEC_RANGE = MAX_DAY_RANGE * SECS_PER_DAY
39+
MAX_NSEC_RANGE = INT_MAX
40+
41+
max_val = {
42+
'year': MAX_YEAR_RANGE,
43+
'month': MAX_MONTH_RANGE,
44+
'week': MAX_WEEK_RANGE,
45+
'day': MAX_DAY_RANGE,
46+
'hour': MAX_HOUR_RANGE,
47+
'minute': MAX_MIN_RANGE,
48+
'sec': MAX_SEC_RANGE,
49+
'nsec': MAX_NSEC_RANGE,
50+
}
51+
52+
53+
def verify_range(intv):
54+
"""
55+
Check allowed values. Approach is the same as in tarantool/tarantool.
56+
57+
:param intv: Raw interval to verify.
58+
:type intv: :class:`~tarantool.Interval`
59+
60+
:raise: :exc:`ValueError`
61+
62+
:meta private:
63+
"""
64+
65+
for field_name, range_max in max_val.items():
66+
val = getattr(intv, field_name)
67+
# Tarantool implementation has a bug
68+
# https://github.com/tarantool/tarantool/issues/8878
69+
if (val > range_max) or (val < -range_max):
70+
raise ValueError(f"value {val} of {field_name} is out of "
71+
f"allowed range [{-range_max}, {range_max}]")
72+
1973

2074
# https://github.com/tarantool/c-dt/blob/cec6acebb54d9e73ea0b99c63898732abd7683a6/dt_arithmetic.h#L34
2175
class Adjust(Enum):
@@ -92,6 +146,8 @@ def __init__(self, *, year=0, month=0, week=0,
92146
:param adjust: Interval adjustment rule. Refer to
93147
:meth:`~tarantool.Datetime.__add__`.
94148
:type adjust: :class:`~tarantool.IntervalAdjust`, optional
149+
150+
:raise: :exc:`ValueError`
95151
"""
96152

97153
self.year = year
@@ -104,6 +160,8 @@ def __init__(self, *, year=0, month=0, week=0,
104160
self.nsec = nsec
105161
self.adjust = adjust
106162

163+
verify_range(self)
164+
107165
def __add__(self, other):
108166
"""
109167
Valid operations:

0 commit comments

Comments
 (0)