|
4 | 4 | from unittest import TestCase |
5 | 5 | from typing import Union, Optional, List, Type, Callable, Any |
6 | 6 | from dataclasses import dataclass |
| 7 | +from osbot_utils.type_safe.primitives.core.Safe_UInt import Safe_UInt |
7 | 8 | from osbot_utils.type_safe.primitives.domains.identifiers.Obj_Id import Obj_Id |
8 | 9 | from osbot_utils.type_safe.primitives.domains.cryptography.safe_str.Safe_Str__Hash import Safe_Str__Hash |
9 | 10 | from osbot_utils.type_safe.primitives.domains.files.safe_str.Safe_Str__File__Name import Safe_Str__File__Name |
@@ -371,20 +372,20 @@ def return_wrong_type() -> int: |
371 | 372 | with pytest.raises(TypeError, match="return type validation failed"): |
372 | 373 | return_wrong_type() |
373 | 374 |
|
374 | | - def test_return_type_validation__type_safe_primitives(self): |
375 | | - """Test return type validation with Type_Safe primitives""" |
| 375 | + def test_return_type_validation__type_safe_primitives(self): # Test return type validation with Type_Safe primitives |
376 | 376 |
|
377 | 377 | @type_safe |
378 | 378 | def return_safe_id() -> Safe_Id: |
379 | 379 | return Safe_Id("test") |
380 | 380 |
|
381 | 381 | @type_safe |
382 | 382 | def return_wrong_primitive() -> Safe_Id: |
383 | | - return "not a safe_id" |
| 383 | + return "not a safe_id" * 50 # breaks Safe max size of 512 |
384 | 384 |
|
385 | 385 | assert type(return_safe_id()) is Safe_Id |
386 | 386 |
|
387 | | - with pytest.raises(TypeError, match="return type validation failed"): |
| 387 | + error_message = "Invalid ID: The ID must not exceed 512 characters (was 650)." |
| 388 | + with pytest.raises(ValueError, match=re.escape(error_message)): |
388 | 389 | return_wrong_primitive() |
389 | 390 |
|
390 | 391 | def test_return_type_validation__optional(self): |
@@ -533,6 +534,44 @@ def process_wrong(value: int) -> str: |
533 | 534 | with pytest.raises(ValueError, match="Parameter 'value' expected type"): |
534 | 535 | process("not an int") |
535 | 536 |
|
| 537 | + def test__type_safe_decorator__converts_return_primitives(self): # Test that return values are converted to Type_Safe__Primitive types |
| 538 | + |
| 539 | + @type_safe |
| 540 | + def returns_safe_uint() -> Safe_UInt: |
| 541 | + return 42 # int should convert to Safe_UInt |
| 542 | + |
| 543 | + result = returns_safe_uint() |
| 544 | + assert isinstance(result, Safe_UInt) |
| 545 | + assert result == 42 |
| 546 | + |
| 547 | + @type_safe |
| 548 | + def returns_safe_str() -> Safe_Str: |
| 549 | + return "hello" # str should convert to Safe_Str |
| 550 | + |
| 551 | + result = returns_safe_str() |
| 552 | + assert isinstance(result, Safe_Str) |
| 553 | + assert result == "hello" |
| 554 | + |
| 555 | + |
| 556 | + def test__type_safe_decorator__validates_converted_return_values(self): # Test that converted values are still validated against constraints |
| 557 | + |
| 558 | + @type_safe |
| 559 | + def returns_constrained_uint() -> Safe_UInt: |
| 560 | + return -1 # Should fail Safe_UInt's min_value=0 constraint |
| 561 | + |
| 562 | + error_message = 'Safe_UInt must be >= 0, got -1' |
| 563 | + with pytest.raises(ValueError, match=re.escape(error_message)): |
| 564 | + returns_constrained_uint() |
| 565 | + |
| 566 | + |
| 567 | + def test__type_safe_decorator__return_none_with_optional(self): # Test that None is valid for Optional return types |
| 568 | + |
| 569 | + @type_safe |
| 570 | + def maybe_returns_uint() -> Optional[Safe_UInt]: |
| 571 | + return None |
| 572 | + |
| 573 | + result = maybe_returns_uint() |
| 574 | + assert result is None |
536 | 575 |
|
537 | 576 |
|
538 | 577 |
|
|
0 commit comments