17
17
import hashlib
18
18
import operator
19
19
import os
20
+ import re
20
21
import sys
21
22
import zipfile
22
23
from pathlib import Path
23
- from typing import Any , Callable , Dict , List , Optional , Set , Tuple , Union
24
+ from typing import Any , Callable , Dict , List , Optional , Set , Union
24
25
25
26
import requests
26
27
from tqdm import tqdm
27
28
28
29
BASE_URL = "https://storage.googleapis.com/peekingduck/models"
29
30
PEEKINGDUCK_WEIGHTS_SUBDIR = "peekingduck_weights"
30
31
31
- Number = Union [float , int ]
32
-
33
32
34
33
class ThresholdCheckerMixin :
35
34
"""Mixin class providing utility methods for checking validity of config
36
35
values, typically thresholds.
37
36
"""
38
37
39
- def check_bounds (
40
- self ,
41
- key : Union [str , List [str ]],
42
- value : Union [Number , Tuple [Number , Number ]],
43
- method : str ,
44
- include : Optional [str ] = "both" ,
45
- ) -> None :
46
- """Checks if the configuration value(s) specified by `key` satisties
38
+ interval_pattern = re .compile (
39
+ r"^[\[\(]\s*[-+]?(inf|\d*\.?\d+)\s*,\s*[-+]?(inf|\d*\.?\d+)\s*[\]\)]$"
40
+ )
41
+
42
+ def check_bounds (self , key : Union [str , List [str ]], interval : str ) -> None :
43
+ """Checks if the configuration value(s) specified by `key` satisfies
47
44
the specified bounds.
48
45
49
46
Args:
50
47
key (Union[str, List[str]]): The specified key or list of keys.
51
- value (Union[Number, Tuple[Number, Number]]): Either a single
52
- number to specify the upper or lower bound or a tuple of
53
- numbers to specify both the upper and lower bounds.
54
- method (str): The bounds checking methods, one of
55
- {"above", "below", "both"}. If "above", checks if the
56
- configuration value is above the specified `value`. If "below",
57
- checks if the configuration value is below the specified
58
- `value`. If "both", checks if the configuration value is above
59
- `value[0]` and below `value[1]`.
60
- include (Optional[str]): Indicates if the `value` itself should be
61
- included in the bound, one of {"lower", "upper", "both", None}.
62
- Please see Technotes for details.
48
+ interval (str): An mathematical interval representing the range of
49
+ valid values. The syntax of the `interval` string is:
50
+
51
+ <value> = <number> | "-inf" | "+inf"
52
+ <left_bracket> = "(" | "["
53
+ <right_bracket> = ")" | "]"
54
+ <interval> = <left_bracket> <value> "," <value> <right_bracket>
55
+
56
+ See Technotes for more details.
63
57
64
58
Raises:
65
59
TypeError: `key` type is not in (List[str], str).
66
- TypeError: If `value` is not a tuple of only float/int.
67
- TypeError: If `value` is not a tuple with 2 elements.
68
- TypeError: If `value` is not a float, int, or tuple.
69
- TypeError: If `value` type is not a tuple when `method` is
70
- "within".
71
- TypeError: If `value` type is a tuple when `method` is
72
- "above"/"below".
73
- ValueError: If `method` is not one of {"above", "below", "within"}.
60
+ ValueError: If `interval` does not match the specified format.
61
+ ValueError: If the lower bound is larger than the upper bound.
74
62
ValueError: If the configuration value fails the bounds comparison.
75
63
76
64
Technotes:
77
- The behavior of `include` depends on the specified `method`. The
78
- table below shows the comparison done for various argument
79
- combinations.
80
-
81
- +-----------+---------+-------------------------------------+
82
- | method | include | comparison |
83
- +===========+=========+=====================================+
84
- | | "lower" | config[key] >= value |
85
- + +---------+-------------------------------------+
86
- | | "upper" | config[key] > value |
87
- + +---------+-------------------------------------+
88
- | | "both" | config[key] >= value |
89
- + +---------+-------------------------------------+
90
- | "above" | None | config[key] > value |
91
- +-----------+---------+-------------------------------------+
92
- | | "lower" | config[key] < value |
93
- + +---------+-------------------------------------+
94
- | | "upper" | config[key] <= value |
95
- + +---------+-------------------------------------+
96
- | | "both" | config[key] <= value |
97
- + +---------+-------------------------------------+
98
- | "below" | None | config[key] < value |
99
- +-----------+---------+-------------------------------------+
100
- | | "lower" | value[0] <= config[key] < value[1] |
101
- + +---------+-------------------------------------+
102
- | | "upper" | value[0] < config[key] <= value[1] |
103
- + +---------+-------------------------------------+
104
- | | "both" | value[0] <= config[key] <= value[1] |
105
- + +---------+-------------------------------------+
106
- | "within" | None | value[0] < config[key] < value[1] |
107
- +-----------+---------+-------------------------------------+
65
+ The table below shows the comparison done for various interval
66
+ expressions.
67
+
68
+ +---------------------+-------------------------------------+
69
+ | interval | comparison |
70
+ +=====================+=====================================+
71
+ | [lower, +inf] | |
72
+ +---------------------+ |
73
+ | [lower, +inf) | config[key] >= lower |
74
+ +---------------------+-------------------------------------+
75
+ | (lower, +inf] | |
76
+ +---------------------+ |
77
+ | (lower, +inf) | config[key] > lower |
78
+ +---------------------+-------------------------------------+
79
+ | [-inf, upper] | |
80
+ +---------------------+ |
81
+ | (-inf, upper] | config[key] <= upper |
82
+ +---------------------+-------------------------------------+
83
+ | [-inf, upper) | |
84
+ +---------------------+ |
85
+ | (-inf, upper) | config[key] < upper |
86
+ +---------------------+-------------------------------------+
87
+ | [lower, upper] | lower <= config[key] <= upper |
88
+ +---------------------+-------------------------------------+
89
+ | (lower, upper] | lower < config[key] <= upper |
90
+ +---------------------+-------------------------------------+
91
+ | [lower, upper) | lower <= config[key] < upper |
92
+ +---------------------+-------------------------------------+
93
+ | (lower, upper) | lower < config[key] < upper |
94
+ +---------------------+-------------------------------------+
108
95
"""
109
- # available checking methods
110
- methods = {"above" , "below" , "within" }
111
- # available options of lower/upper bound inclusion
112
- lower_includes = {"lower" , "both" }
113
- upper_includes = {"upper" , "both" }
114
-
115
- if method not in methods :
116
- raise ValueError (f"`method` must be one of { methods } " )
117
-
118
- if isinstance (value , tuple ):
119
- if not all (isinstance (val , (float , int )) for val in value ):
120
- raise TypeError (
121
- "When using tuple for `value`, it must be a tuple of float/int"
122
- )
123
- if len (value ) != 2 :
124
- raise ValueError (
125
- "When using tuple for `value`, it must contain only 2 elements"
126
- )
127
- elif isinstance (value , (float , int )):
128
- pass
129
- else :
130
- raise TypeError (
131
- "`value` must be a float/int or tuple, but you passed a "
132
- f"{ type (value ).__name__ } "
133
- )
134
-
135
- if method == "within" :
136
- if not isinstance (value , tuple ):
137
- raise TypeError ("`value` must be a tuple when `method` is 'within'" )
138
- self ._check_within_bounds (
139
- key , value , (include in lower_includes , include in upper_includes )
140
- )
141
- else :
142
- if isinstance (value , tuple ):
143
- raise TypeError (
144
- "`value` must be a float/int when `method` is 'above'/'below'"
145
- )
146
- if method == "above" :
147
- self ._check_above_value (key , value , include in lower_includes )
148
- elif method == "below" :
149
- self ._check_below_value (key , value , include in upper_includes )
96
+ if self .interval_pattern .match (interval ) is None :
97
+ raise ValueError ("Badly formatted interval" )
98
+
99
+ left_bracket = interval [0 ]
100
+ right_bracket = interval [- 1 ]
101
+ lower , upper = [float (value .strip ()) for value in interval [1 :- 1 ].split ("," )]
102
+
103
+ if lower > upper :
104
+ raise ValueError ("Lower bound cannot be larger than upper bound" )
105
+
106
+ self ._check_within_bounds (key , lower , upper , left_bracket , right_bracket )
150
107
151
108
def check_valid_choice (
152
109
self , key : str , choices : Set [Union [int , float , str ]]
@@ -167,78 +124,36 @@ def check_valid_choice(
167
124
if self .config [key ] not in choices :
168
125
raise ValueError (f"{ key } must be one of { choices } " )
169
126
170
- def _check_above_value (
171
- self , key : Union [str , List [str ]], value : Number , inclusive : bool
172
- ) -> None :
173
- """Checks that configuration values specified by `key` is more than
174
- (or equal to) the specified `value`.
175
-
176
- Args:
177
- key (Union[str, List[str]]): The specified key or list of keys.
178
- value (Number): The specified value.
179
- inclusive (bool): If `True`, compares `config[key] >= value`. If
180
- `False`, compares `config[key] > value`.
181
-
182
- Raises:
183
- TypeError: `key` type is not in (List[str], str).
184
- ValueError: If the configuration value is less than (or equal to)
185
- `value`.
186
- """
187
- method = operator .ge if inclusive else operator .gt
188
- extra_reason = " or equal to" if inclusive else ""
189
- self ._compare (key , value , method , reason = f"more than{ extra_reason } { value } " )
190
-
191
- def _check_below_value (
192
- self , key : Union [str , List [str ]], value : Number , inclusive : bool
193
- ) -> None :
194
- """Checks that configuration values specified by `key` is more than
195
- (or equal to) the specified `value`.
196
-
197
- Args:
198
- key (Union[str, List[str]]): The specified key or list of keys.
199
- value (Number): The specified value.
200
- inclusive (bool): If `True`, compares `config[key] <= value`. If
201
- `False`, compares `config[key] < value`.
202
-
203
- Raises:
204
- TypeError: `key` type is not in (List[str], str).
205
- ValueError: If the configuration value is less than (or equal to)
206
- `value`.
207
- """
208
- method = operator .le if inclusive else operator .lt
209
- extra_reason = " or equal to" if inclusive else ""
210
- self ._compare (key , value , method , reason = f"less than{ extra_reason } { value } " )
211
-
212
- def _check_within_bounds (
127
+ def _check_within_bounds ( # pylint: disable=too-many-arguments
213
128
self ,
214
129
key : Union [str , List [str ]],
215
- bounds : Tuple [Number , Number ],
216
- includes : Tuple [bool , bool ],
130
+ lower : float ,
131
+ upper : float ,
132
+ left_bracket : str ,
133
+ right_bracket : str ,
217
134
) -> None :
218
135
"""Checks that configuration values specified by `key` is within the
219
136
specified bounds between `lower` and `upper`.
220
137
221
138
Args:
222
139
key (Union[str, List[str]]): The specified key or list of keys.
223
- (Union[ float, int] ): The lower bound.
224
- bounds (Tuple[Number, Number] ): The lower and upper bounds .
225
- includes (Tuple[bool, bool] ): If `True`, compares `config[key] >= value`.
226
- If `False`, compares `config[key] > value` .
227
- inclusive_upper (bool ): If `True`, compares `config[key] <= value`.
228
- If `False`, compares `config[key] < value` .
140
+ lower ( float): The lower bound.
141
+ upper (float ): The upper bound .
142
+ left_bracket (str ): Either a "(" for an open lower bound or a "["
143
+ for a closed lower bound .
144
+ right_bracket (str ): Either a ")" for an open upper bound or a "]"
145
+ for a closed upper bound .
229
146
230
147
Raises:
231
148
TypeError: `key` type is not in (List[str], str).
232
149
ValueError: If the configuration value is not between `lower` and
233
150
`upper`.
234
151
"""
235
- method_lower = operator .ge if includes [0 ] else operator .gt
236
- method_upper = operator .le if includes [1 ] else operator .lt
237
- reason_lower = "[" if includes [0 ] else "("
238
- reason_upper = "]" if includes [1 ] else ")"
239
- reason = f"between { reason_lower } { bounds [0 ]} , { bounds [1 ]} { reason_upper } "
240
- self ._compare (key , bounds [0 ], method_lower , reason )
241
- self ._compare (key , bounds [1 ], method_upper , reason )
152
+ method_lower = operator .ge if left_bracket == "[" else operator .gt
153
+ method_upper = operator .le if right_bracket == "]" else operator .lt
154
+ reason = f"between { left_bracket } { lower } , { upper } { right_bracket } "
155
+ self ._compare (key , lower , method_lower , reason )
156
+ self ._compare (key , upper , method_upper , reason )
242
157
243
158
def _compare (
244
159
self ,
0 commit comments