|
1 | 1 | import warnings
|
| 2 | +from functools import wraps |
| 3 | + |
2 | 4 | import numpy as np
|
3 | 5 | import pytest
|
4 | 6 |
|
|
8 | 10 | convert_bytes,
|
9 | 11 | make_dict,
|
10 | 12 | )
|
11 |
| -from redisvl.utils.utils import deprecated_argument |
| 13 | +from redisvl.utils.utils import assert_no_warnings, deprecated_argument |
12 | 14 |
|
13 | 15 |
|
14 | 16 | def test_even_number_of_elements():
|
@@ -149,104 +151,252 @@ def test_conversion_with_invalid_floats():
|
149 | 151 | assert len(result) > 0 # Simple check to ensure it returns anything
|
150 | 152 |
|
151 | 153 |
|
| 154 | +def decorator(func): |
| 155 | + @wraps(func) |
| 156 | + def wrapper(*args, **kwargs): |
| 157 | + print("boop") |
| 158 | + return func(*args, **kwargs) |
| 159 | + |
| 160 | + return wrapper |
| 161 | + |
| 162 | + |
152 | 163 | class TestDeprecatedArgument:
|
153 | 164 | def test_deprecation_warning_text_with_replacement(self):
|
154 |
| - @deprecated_argument("dtype", "vectorizer") |
155 |
| - def test_func(dtype=None, vectorizer=None): |
| 165 | + @deprecated_argument("old_arg", "new_arg") |
| 166 | + def test_func(old_arg=None, new_arg=None, neutral_arg=None): |
156 | 167 | pass
|
157 | 168 |
|
| 169 | + # Test that passing the deprecated argument as a keyword triggers the warning. |
158 | 170 | with pytest.warns(DeprecationWarning) as record:
|
159 |
| - test_func(dtype="float32") |
| 171 | + test_func(old_arg="float32") |
160 | 172 |
|
161 | 173 | assert len(record) == 1
|
162 | 174 | assert str(record[0].message) == (
|
163 |
| - "Argument dtype is deprecated and will be removed" |
164 |
| - " in the next major release. Use vectorizer instead." |
| 175 | + "Argument old_arg is deprecated and will be removed in the next major release. Use new_arg instead." |
165 | 176 | )
|
166 | 177 |
|
| 178 | + # Test that passing the deprecated argument as a positional argument also triggers the warning. |
| 179 | + with pytest.warns(DeprecationWarning) as record: |
| 180 | + test_func("float32", neutral_arg="test_vector") |
| 181 | + |
| 182 | + assert len(record) == 1 |
| 183 | + assert str(record[0].message) == ( |
| 184 | + "Argument old_arg is deprecated and will be removed in the next major release. Use new_arg instead." |
| 185 | + ) |
| 186 | + |
| 187 | + with assert_no_warnings(): |
| 188 | + test_func(new_arg="float32") |
| 189 | + test_func(new_arg="float32", neutral_arg="test_vector") |
| 190 | + |
167 | 191 | def test_deprecation_warning_text_without_replacement(self):
|
168 |
| - @deprecated_argument("dtype") |
169 |
| - def test_func(dtype=None): |
| 192 | + @deprecated_argument("old_arg") |
| 193 | + def test_func(old_arg=None, neutral_arg=None): |
170 | 194 | pass
|
171 | 195 |
|
| 196 | + # As a kwarg |
172 | 197 | with pytest.warns(DeprecationWarning) as record:
|
173 |
| - test_func(dtype="float32") |
| 198 | + test_func(old_arg="float32") |
174 | 199 |
|
175 | 200 | assert len(record) == 1
|
176 | 201 | assert str(record[0].message) == (
|
177 |
| - "Argument dtype is deprecated and will be removed" |
| 202 | + "Argument old_arg is deprecated and will be removed" |
178 | 203 | " in the next major release."
|
179 | 204 | )
|
180 | 205 |
|
181 |
| - def test_function_argument(self): |
182 |
| - @deprecated_argument("dtype", "vectorizer") |
183 |
| - def test_func(dtype=None, vectorizer=None): |
| 206 | + # As a positional arg |
| 207 | + with pytest.warns(DeprecationWarning): |
| 208 | + test_func("float32", neutral_arg="test_vector") |
| 209 | + |
| 210 | + assert len(record) == 1 |
| 211 | + assert str(record[0].message) == ( |
| 212 | + "Argument old_arg is deprecated and will be removed" |
| 213 | + " in the next major release." |
| 214 | + ) |
| 215 | + |
| 216 | + with assert_no_warnings(): |
| 217 | + test_func(neutral_arg="test_vector") |
| 218 | + |
| 219 | + def test_function_positional_argument_required(self): |
| 220 | + """ |
| 221 | + NOTE: In this situation, it's not possible to avoid a deprecation |
| 222 | + warning because the argument is currently required. |
| 223 | + """ |
| 224 | + |
| 225 | + @deprecated_argument("old_arg") |
| 226 | + def test_func(old_arg, neutral_arg): |
| 227 | + pass |
| 228 | + |
| 229 | + with pytest.warns(DeprecationWarning): |
| 230 | + test_func("float32", "bob") |
| 231 | + |
| 232 | + def test_function_positional_argument_optional(self): |
| 233 | + @deprecated_argument("old_arg") |
| 234 | + def test_func(neutral_arg, old_arg=None): |
184 | 235 | pass
|
185 | 236 |
|
186 | 237 | with pytest.warns(DeprecationWarning):
|
187 |
| - test_func(dtype="float32") |
| 238 | + test_func("bob", "float32") |
| 239 | + |
| 240 | + with assert_no_warnings(): |
| 241 | + test_func("bob") |
188 | 242 |
|
189 | 243 | def test_function_keyword_argument(self):
|
190 |
| - @deprecated_argument("dtype", "vectorizer") |
191 |
| - def test_func(dtype=None, vectorizer=None): |
| 244 | + @deprecated_argument("old_arg", "new_arg") |
| 245 | + def test_func(old_arg=None, new_arg=None): |
192 | 246 | pass
|
193 | 247 |
|
194 | 248 | with pytest.warns(DeprecationWarning):
|
195 |
| - test_func(vectorizer="float32") |
| 249 | + test_func(old_arg="float32") |
| 250 | + |
| 251 | + with assert_no_warnings(): |
| 252 | + test_func(new_arg="float32") |
| 253 | + |
| 254 | + def test_function_keyword_argument_multiple_decorators(self): |
| 255 | + @deprecated_argument("old_arg", "new_arg") |
| 256 | + @decorator |
| 257 | + def test_func(old_arg=None, new_arg=None): |
| 258 | + pass |
| 259 | + |
| 260 | + with pytest.warns(DeprecationWarning): |
| 261 | + test_func(old_arg="float32") |
| 262 | + |
| 263 | + with assert_no_warnings(): |
| 264 | + test_func(new_arg="float32") |
| 265 | + |
| 266 | + def test_method_positional_argument_optional(self): |
| 267 | + class TestClass: |
| 268 | + @deprecated_argument("old_arg", "new_arg") |
| 269 | + def test_method(self, new_arg=None, old_arg=None): |
| 270 | + pass |
| 271 | + |
| 272 | + with pytest.warns(DeprecationWarning): |
| 273 | + TestClass().test_method("float32", "bob") |
| 274 | + |
| 275 | + with assert_no_warnings(): |
| 276 | + TestClass().test_method("float32") |
| 277 | + |
| 278 | + def test_method_positional_argument_required(self): |
| 279 | + """ |
| 280 | + NOTE: In this situation, it's not possible to avoid a deprecation |
| 281 | + warning because the argument is currently required. |
| 282 | + """ |
| 283 | + |
| 284 | + class TestClass: |
| 285 | + @deprecated_argument("old_arg", "new_arg") |
| 286 | + def test_method(self, old_arg, new_arg): |
| 287 | + pass |
| 288 | + |
| 289 | + with pytest.warns(DeprecationWarning): |
| 290 | + TestClass().test_method("float32", new_arg="bob") |
| 291 | + |
| 292 | + def test_method_keyword_argument(self): |
| 293 | + class TestClass: |
| 294 | + @deprecated_argument("old_arg", "new_arg") |
| 295 | + def test_method(self, old_arg=None, new_arg=None): |
| 296 | + pass |
| 297 | + |
| 298 | + with pytest.warns(DeprecationWarning): |
| 299 | + TestClass().test_method(old_arg="float32") |
| 300 | + |
| 301 | + with assert_no_warnings(): |
| 302 | + TestClass().test_method(new_arg="float32") |
| 303 | + |
| 304 | + def test_classmethod_positional_argument_required(self): |
| 305 | + """ |
| 306 | + NOTE: In this situation, it's impossible to avoid a deprecation |
| 307 | + warning because the argument is currently required. |
| 308 | + """ |
196 | 309 |
|
197 |
| - def test_class_method_argument(self): |
198 | 310 | class TestClass:
|
199 |
| - @deprecated_argument("dtype", "vectorizer") |
200 |
| - def test_method(self, dtype=None, vectorizer=None): |
| 311 | + @deprecated_argument("old_arg", "new_arg") |
| 312 | + @classmethod |
| 313 | + def test_method(cls, old_arg, new_arg): |
201 | 314 | pass
|
202 | 315 |
|
203 | 316 | with pytest.warns(DeprecationWarning):
|
204 |
| - TestClass().test_method(dtype="float32") |
| 317 | + TestClass.test_method("float32", new_arg="bob") |
205 | 318 |
|
206 |
| - def test_class_method_keyword_argument(self): |
| 319 | + def test_classmethod_positional_argument_optional(self): |
207 | 320 | class TestClass:
|
208 |
| - @deprecated_argument("dtype", "vectorizer") |
209 |
| - def test_method(self, dtype=None, vectorizer=None): |
| 321 | + @deprecated_argument("old_arg", "new_arg") |
| 322 | + @classmethod |
| 323 | + def test_method(cls, new_arg=None, old_arg=None): |
210 | 324 | pass
|
211 | 325 |
|
212 | 326 | with pytest.warns(DeprecationWarning):
|
213 |
| - TestClass().test_method(vectorizer="float32") |
| 327 | + TestClass.test_method("float32", "bob") |
| 328 | + |
| 329 | + with assert_no_warnings(): |
| 330 | + TestClass.test_method("float32") |
| 331 | + |
| 332 | + def test_classmethod_keyword_argument(self): |
| 333 | + class TestClass: |
| 334 | + @deprecated_argument("old_arg", "new_arg") |
| 335 | + @classmethod |
| 336 | + def test_method(cls, old_arg=None, new_arg=None): |
| 337 | + pass |
| 338 | + |
| 339 | + with pytest.warns(DeprecationWarning): |
| 340 | + TestClass.test_method(old_arg="float32") |
| 341 | + |
| 342 | + with assert_no_warnings(): |
| 343 | + TestClass.test_method(new_arg="float32") |
| 344 | + |
| 345 | + def test_classmethod_keyword_argument_multiple_decorators(self): |
| 346 | + """ |
| 347 | + NOTE: The @deprecated_argument decorator should come between @classmethod |
| 348 | + and the method definition. |
| 349 | + """ |
| 350 | + |
| 351 | + class TestClass: |
| 352 | + @classmethod |
| 353 | + @deprecated_argument("old_arg", "new_arg") |
| 354 | + @decorator |
| 355 | + def test_method(cls, old_arg=None, new_arg=None): |
| 356 | + pass |
| 357 | + |
| 358 | + with pytest.warns(DeprecationWarning): |
| 359 | + TestClass.test_method(old_arg="float32") |
| 360 | + |
| 361 | + with assert_no_warnings(): |
| 362 | + TestClass.test_method(new_arg="float32") |
214 | 363 |
|
215 | 364 | def test_class_init_argument(self):
|
216 | 365 | class TestClass:
|
217 |
| - @deprecated_argument("dtype", "vectorizer") |
218 |
| - def __init__(self, dtype=None, vectorizer=None): |
| 366 | + @deprecated_argument("old_arg", "new_arg") |
| 367 | + def __init__(self, old_arg=None, new_arg=None): |
219 | 368 | pass
|
220 | 369 |
|
221 | 370 | with pytest.warns(DeprecationWarning):
|
222 |
| - TestClass(dtype="float32") |
| 371 | + TestClass(old_arg="float32") |
223 | 372 |
|
224 | 373 | def test_class_init_keyword_argument(self):
|
225 | 374 | class TestClass:
|
226 |
| - @deprecated_argument("dtype", "vectorizer") |
227 |
| - def __init__(self, dtype=None, vectorizer=None): |
| 375 | + @deprecated_argument("old_arg", "new_arg") |
| 376 | + def __init__(self, old_arg=None, new_arg=None): |
228 | 377 | pass
|
229 | 378 |
|
230 | 379 | with pytest.warns(DeprecationWarning):
|
231 |
| - TestClass(dtype="float32") |
| 380 | + TestClass(old_arg="float32") |
| 381 | + |
| 382 | + with assert_no_warnings(): |
| 383 | + TestClass(new_arg="float32") |
232 | 384 |
|
233 | 385 | async def test_async_function_argument(self):
|
234 |
| - @deprecated_argument("dtype", "vectorizer") |
235 |
| - async def test_func(dtype=None, vectorizer=None): |
| 386 | + @deprecated_argument("old_arg", "new_arg") |
| 387 | + async def test_func(old_arg=None, new_arg=None): |
236 | 388 | return 1
|
237 | 389 |
|
238 | 390 | with pytest.warns(DeprecationWarning):
|
239 |
| - result = await test_func(dtype="float32") |
| 391 | + result = await test_func(old_arg="float32") |
240 | 392 | assert result == 1
|
241 |
| - |
| 393 | + |
242 | 394 | async def test_ignores_local_variable(self):
|
243 |
| - @deprecated_argument("dtype") |
244 |
| - async def test_func(vectorizer=None): |
| 395 | + @deprecated_argument("old_arg", "new_arg") |
| 396 | + async def test_func(old_arg=None, new_arg=None): |
245 | 397 | # The presence of this variable should not trigger a warning
|
246 |
| - dtype = "float32" |
| 398 | + old_arg = "float32" |
247 | 399 | return 1
|
248 | 400 |
|
249 |
| - # This will raise an error if any warning is emitted |
250 |
| - with warnings.catch_warnings(): |
251 |
| - warnings.simplefilter("error") |
| 401 | + with assert_no_warnings(): |
252 | 402 | await test_func()
|
0 commit comments