simplibs-validate 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. simplibs/validate/__init__.py +46 -0
  2. simplibs/validate/exceptions/ParamError.py +31 -0
  3. simplibs/validate/exceptions/ValidateError.py +44 -0
  4. simplibs/validate/exceptions/ValidationError.py +30 -0
  5. simplibs/validate/exceptions/__init__.py +31 -0
  6. simplibs/validate/exceptions/build_validation_error.py +52 -0
  7. simplibs/validate/raise_invalid.py +84 -0
  8. simplibs/validate/rules/__init__.py +855 -0
  9. simplibs/validate/rules/base_class/Rule.py +280 -0
  10. simplibs/validate/rules/base_class/__init__.py +17 -0
  11. simplibs/validate/rules/containers/AllOf.py +147 -0
  12. simplibs/validate/rules/containers/AnyOf.py +146 -0
  13. simplibs/validate/rules/containers/Compose.py +148 -0
  14. simplibs/validate/rules/containers/ForEach.py +120 -0
  15. simplibs/validate/rules/containers/NoneOf.py +112 -0
  16. simplibs/validate/rules/containers/Not.py +97 -0
  17. simplibs/validate/rules/containers/__init__.py +28 -0
  18. simplibs/validate/rules/containers/_helpers/__init__.py +22 -0
  19. simplibs/validate/rules/containers/_helpers/as_predicate.py +78 -0
  20. simplibs/validate/rules/containers/_helpers/build_child_exception.py +39 -0
  21. simplibs/validate/rules/containers/_helpers/describe_rule.py +72 -0
  22. simplibs/validate/rules/containers/_init_validators/__init__.py +23 -0
  23. simplibs/validate/rules/containers/_init_validators/raise_container_param_not_type_error.py +53 -0
  24. simplibs/validate/rules/containers/_init_validators/raise_requires_at_least_one_rule_error.py +38 -0
  25. simplibs/validate/rules/containers/_init_validators/raise_rule_param_not_callable.py +55 -0
  26. simplibs/validate/rules/containers/_init_validators/validate_compose_param_is_callable.py +73 -0
  27. simplibs/validate/rules/predicates/__init__.py +87 -0
  28. simplibs/validate/rules/predicates/_helpers/__init__.py +18 -0
  29. simplibs/validate/rules/predicates/_helpers/accepts_one_positional_argument.py +127 -0
  30. simplibs/validate/rules/predicates/_helpers/format_container.py +50 -0
  31. simplibs/validate/rules/predicates/_init_validators/__init__.py +40 -0
  32. simplibs/validate/rules/predicates/_init_validators/rule_errors/__init__.py +21 -0
  33. simplibs/validate/rules/predicates/_init_validators/rule_errors/raise_has_length_param_conflict_error.py +54 -0
  34. simplibs/validate/rules/predicates/_init_validators/rule_errors/raise_regex_param_invalid_pattern_error.py +44 -0
  35. simplibs/validate/rules/predicates/_init_validators/rule_errors/raise_user_rule_param_wrong_arity.py +54 -0
  36. simplibs/validate/rules/predicates/_init_validators/shared_errors/__init__.py +32 -0
  37. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_min_max_bounds_inverted_error.py +79 -0
  38. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_min_max_incomparable_error.py +66 -0
  39. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_missing_error.py +78 -0
  40. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_not_callable_error.py +52 -0
  41. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_not_container_error.py +76 -0
  42. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_not_non_negative_integer_error.py +89 -0
  43. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_not_string_error.py +78 -0
  44. simplibs/validate/rules/predicates/_init_validators/shared_errors/raise_param_not_type_error.py +66 -0
  45. simplibs/validate/rules/predicates/_init_validators/shared_validators/__init__.py +24 -0
  46. simplibs/validate/rules/predicates/_init_validators/shared_validators/validate_param_is_integer.py +74 -0
  47. simplibs/validate/rules/predicates/_init_validators/shared_validators/validate_param_is_not_zero.py +70 -0
  48. simplibs/validate/rules/predicates/_init_validators/shared_validators/validate_param_is_primitive_number.py +77 -0
  49. simplibs/validate/rules/predicates/_init_validators/shared_validators/validate_param_remainder_in_range.py +59 -0
  50. simplibs/validate/rules/predicates/arithmetic/CloseTo.py +149 -0
  51. simplibs/validate/rules/predicates/arithmetic/DivisibleBy.py +120 -0
  52. simplibs/validate/rules/predicates/arithmetic/HasRemainder.py +137 -0
  53. simplibs/validate/rules/predicates/arithmetic/__init__.py +21 -0
  54. simplibs/validate/rules/predicates/checkers/IsEmpty.py +101 -0
  55. simplibs/validate/rules/predicates/checkers/IsFalse.py +81 -0
  56. simplibs/validate/rules/predicates/checkers/IsNone.py +81 -0
  57. simplibs/validate/rules/predicates/checkers/IsTrue.py +80 -0
  58. simplibs/validate/rules/predicates/checkers/NotEmpty.py +100 -0
  59. simplibs/validate/rules/predicates/checkers/__init__.py +25 -0
  60. simplibs/validate/rules/predicates/collections/AllUnique.py +124 -0
  61. simplibs/validate/rules/predicates/collections/HasItem.py +132 -0
  62. simplibs/validate/rules/predicates/collections/HasKey.py +104 -0
  63. simplibs/validate/rules/predicates/collections/HasKeys.py +115 -0
  64. simplibs/validate/rules/predicates/collections/IsContainer.py +99 -0
  65. simplibs/validate/rules/predicates/collections/IsSubsetOf.py +139 -0
  66. simplibs/validate/rules/predicates/collections/IsSupersetOf.py +138 -0
  67. simplibs/validate/rules/predicates/collections/__init__.py +29 -0
  68. simplibs/validate/rules/predicates/comparisons/Equals.py +87 -0
  69. simplibs/validate/rules/predicates/comparisons/GreaterOrEqual.py +106 -0
  70. simplibs/validate/rules/predicates/comparisons/GreaterThan.py +106 -0
  71. simplibs/validate/rules/predicates/comparisons/InRange.py +166 -0
  72. simplibs/validate/rules/predicates/comparisons/LessOrEqual.py +106 -0
  73. simplibs/validate/rules/predicates/comparisons/LessThan.py +106 -0
  74. simplibs/validate/rules/predicates/comparisons/NotEquals.py +88 -0
  75. simplibs/validate/rules/predicates/comparisons/__init__.py +29 -0
  76. simplibs/validate/rules/predicates/introspection/HasAttribute.py +95 -0
  77. simplibs/validate/rules/predicates/introspection/HasLength.py +177 -0
  78. simplibs/validate/rules/predicates/introspection/IsCallable.py +81 -0
  79. simplibs/validate/rules/predicates/introspection/IsDataclass.py +84 -0
  80. simplibs/validate/rules/predicates/introspection/IsHashable.py +91 -0
  81. simplibs/validate/rules/predicates/introspection/IsInstance.py +105 -0
  82. simplibs/validate/rules/predicates/introspection/IsIterable.py +90 -0
  83. simplibs/validate/rules/predicates/introspection/IsSubclass.py +122 -0
  84. simplibs/validate/rules/predicates/introspection/IsType.py +82 -0
  85. simplibs/validate/rules/predicates/introspection/__init__.py +34 -0
  86. simplibs/validate/rules/predicates/logic/Is.py +88 -0
  87. simplibs/validate/rules/predicates/logic/IsIn.py +145 -0
  88. simplibs/validate/rules/predicates/logic/IsNot.py +89 -0
  89. simplibs/validate/rules/predicates/logic/NotIn.py +145 -0
  90. simplibs/validate/rules/predicates/logic/UserRule.py +118 -0
  91. simplibs/validate/rules/predicates/logic/__init__.py +24 -0
  92. simplibs/validate/rules/predicates/numeric/IsBool.py +96 -0
  93. simplibs/validate/rules/predicates/numeric/IsDecimal.py +83 -0
  94. simplibs/validate/rules/predicates/numeric/IsFloat.py +75 -0
  95. simplibs/validate/rules/predicates/numeric/IsInfinity.py +97 -0
  96. simplibs/validate/rules/predicates/numeric/IsInteger.py +118 -0
  97. simplibs/validate/rules/predicates/numeric/IsNan.py +98 -0
  98. simplibs/validate/rules/predicates/numeric/IsNumber.py +96 -0
  99. simplibs/validate/rules/predicates/numeric/IsPi.py +138 -0
  100. simplibs/validate/rules/predicates/numeric/IsPrimitiveNumber.py +87 -0
  101. simplibs/validate/rules/predicates/numeric/IsZero.py +109 -0
  102. simplibs/validate/rules/predicates/numeric/__init__.py +36 -0
  103. simplibs/validate/rules/predicates/strings/Contains.py +114 -0
  104. simplibs/validate/rules/predicates/strings/EndsWith.py +114 -0
  105. simplibs/validate/rules/predicates/strings/IsBlank.py +98 -0
  106. simplibs/validate/rules/predicates/strings/IsString.py +104 -0
  107. simplibs/validate/rules/predicates/strings/IsSubstringOf.py +114 -0
  108. simplibs/validate/rules/predicates/strings/NotBlank.py +98 -0
  109. simplibs/validate/rules/predicates/strings/Regex.py +126 -0
  110. simplibs/validate/rules/predicates/strings/StartsWith.py +114 -0
  111. simplibs/validate/rules/predicates/strings/__init__.py +30 -0
  112. simplibs/validate/rules/typing/IsAny.py +114 -0
  113. simplibs/validate/rules/typing/IsTyping.py +100 -0
  114. simplibs/validate/rules/typing/__init__.py +26 -0
  115. simplibs/validate/rules/typing/_builders/ORIGIN_TABLE.py +112 -0
  116. simplibs/validate/rules/typing/_builders/__init__.py +35 -0
  117. simplibs/validate/rules/typing/_builders/build_annotated_rule.py +106 -0
  118. simplibs/validate/rules/typing/_builders/build_any_of_rule.py +73 -0
  119. simplibs/validate/rules/typing/_builders/build_callable_rule.py +63 -0
  120. simplibs/validate/rules/typing/_builders/build_elements_rule.py +109 -0
  121. simplibs/validate/rules/typing/_builders/build_key_value_rule.py +65 -0
  122. simplibs/validate/rules/typing/_builders/build_literal_rule.py +60 -0
  123. simplibs/validate/rules/typing/_builders/build_tuple_rule.py +111 -0
  124. simplibs/validate/rules/typing/_builders/build_type_rule.py +114 -0
  125. simplibs/validate/rules/typing/_validations/__init__.py +16 -0
  126. simplibs/validate/rules/typing/_validations/raise_unsupported_annotation_error.py +64 -0
  127. simplibs/validate/rules/typing/build_typing_rule.py +131 -0
  128. simplibs/validate/rules/typing/tools/__init__.py +20 -0
  129. simplibs/validate/rules/typing/tools/get_supported_origins.py +42 -0
  130. simplibs/validate/rules/typing/tools/is_supported_annotation.py +60 -0
  131. simplibs/validate/testing/__init__.py +43 -0
  132. simplibs/validate/testing/assert_rule_contract.py +198 -0
  133. simplibs/validate/testing/assert_validate_wrapper.py +81 -0
  134. simplibs/validate/testing/asserts/__init__.py +27 -0
  135. simplibs/validate/testing/asserts/assert_rule_build_exception.py +149 -0
  136. simplibs/validate/testing/asserts/assert_rule_is_valid.py +90 -0
  137. simplibs/validate/testing/asserts/assert_rule_param_error.py +78 -0
  138. simplibs/validate/testing/asserts/assert_rule_raise_invalid.py +91 -0
  139. simplibs/validate/testing/asserts/assert_rule_validate.py +107 -0
  140. simplibs/validate/tools/__init__.py +33 -0
  141. simplibs/validate/tools/log_this/__init__.py +16 -0
  142. simplibs/validate/tools/log_this/_helpers/__init__.py +24 -0
  143. simplibs/validate/tools/log_this/_helpers/format_bound_arguments.py +65 -0
  144. simplibs/validate/tools/log_this/_helpers/get_context_info.py +34 -0
  145. simplibs/validate/tools/log_this/_helpers/log_exception.py +68 -0
  146. simplibs/validate/tools/log_this/_helpers/log_start.py +40 -0
  147. simplibs/validate/tools/log_this/_helpers/log_success.py +74 -0
  148. simplibs/validate/tools/log_this/log_this.py +232 -0
  149. simplibs/validate/tools/override_rules/__init__.py +15 -0
  150. simplibs/validate/tools/override_rules/_validations/__init__.py +14 -0
  151. simplibs/validate/tools/override_rules/_validations/raise_override_rules_invalid_error.py +51 -0
  152. simplibs/validate/tools/override_rules/override_rules.py +97 -0
  153. simplibs/validate/tools/validate_call/__init__.py +16 -0
  154. simplibs/validate/tools/validate_call/_helpers/__init__.py +24 -0
  155. simplibs/validate/tools/validate_call/_helpers/compile_parameter_rules.py +133 -0
  156. simplibs/validate/tools/validate_call/_helpers/compile_return_rule.py +75 -0
  157. simplibs/validate/tools/validate_call/_helpers/get_context_string.py +29 -0
  158. simplibs/validate/tools/validate_call/_helpers/is_bypass_parameter.py +68 -0
  159. simplibs/validate/tools/validate_call/_helpers/should_validate.py +68 -0
  160. simplibs/validate/tools/validate_call/_validations/__init__.py +19 -0
  161. simplibs/validate/tools/validate_call/_validations/raise_no_rule_for_checked_param.py +47 -0
  162. simplibs/validate/tools/validate_call/_validations/raise_no_rule_for_return.py +43 -0
  163. simplibs/validate/tools/validate_call/validate_call.py +335 -0
  164. simplibs/validate/tools/validate_dataclass/__init__.py +16 -0
  165. simplibs/validate/tools/validate_dataclass/_helpers/__init__.py +16 -0
  166. simplibs/validate/tools/validate_dataclass/_helpers/get_dataclass_context_string.py +30 -0
  167. simplibs/validate/tools/validate_dataclass/_validations/__init__.py +16 -0
  168. simplibs/validate/tools/validate_dataclass/_validations/raise_not_a_dataclass_error.py +44 -0
  169. simplibs/validate/tools/validate_dataclass/validate_dataclass.py +206 -0
  170. simplibs/validate/tools/validated_type/__init__.py +15 -0
  171. simplibs/validate/tools/validated_type/_validations/__init__.py +17 -0
  172. simplibs/validate/tools/validated_type/_validations/raise_validated_type_missing_rule_error.py +46 -0
  173. simplibs/validate/tools/validated_type/_validations/raise_validated_type_rule_invalid_error.py +47 -0
  174. simplibs/validate/tools/validated_type/validated_type.py +147 -0
  175. simplibs/validate/validate.py +145 -0
  176. simplibs/validate/validators/__init__.py +67 -0
  177. simplibs/validate/validators/rules/__init__.py +30 -0
  178. simplibs/validate/validators/rules/boolean_rule.py +88 -0
  179. simplibs/validate/validators/rules/container_rule.py +141 -0
  180. simplibs/validate/validators/rules/float_rule.py +172 -0
  181. simplibs/validate/validators/rules/integer_rule.py +161 -0
  182. simplibs/validate/validators/rules/mapping_rule.py +123 -0
  183. simplibs/validate/validators/rules/number_rule.py +136 -0
  184. simplibs/validate/validators/rules/string_rule.py +193 -0
  185. simplibs/validate/validators/rules/type_rule.py +104 -0
  186. simplibs/validate/validators/validate_bool.py +59 -0
  187. simplibs/validate/validators/validate_container.py +87 -0
  188. simplibs/validate/validators/validate_float.py +102 -0
  189. simplibs/validate/validators/validate_int.py +96 -0
  190. simplibs/validate/validators/validate_mapping.py +75 -0
  191. simplibs/validate/validators/validate_number.py +89 -0
  192. simplibs/validate/validators/validate_str.py +123 -0
  193. simplibs/validate/validators/validate_type.py +73 -0
  194. simplibs_validate-0.1.0.dist-info/METADATA +659 -0
  195. simplibs_validate-0.1.0.dist-info/RECORD +198 -0
  196. simplibs_validate-0.1.0.dist-info/WHEEL +5 -0
  197. simplibs_validate-0.1.0.dist-info/licenses/LICENSE +21 -0
  198. simplibs_validate-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,46 @@
1
+ """Root package for simplibs-validate."""
2
+
3
+ # 1. Direct core module imports
4
+ from .raise_invalid import raise_invalid
5
+ from .validate import validate
6
+
7
+ # 2. Extract __all__ lists BEFORE star-imports (prevents SimpleNamespace shadow overriding)
8
+ from .exceptions import __all__ as _exceptions_all
9
+ from .rules import __all__ as _rules_all
10
+ from .tools import __all__ as _tools_all
11
+ from .validators import __all__ as _validators_all
12
+
13
+ # 3. Re-export public members into root namespace
14
+ from .exceptions import *
15
+ from .rules import *
16
+ from .tools import *
17
+ from .validators import *
18
+
19
+ # 4. Assemble root __all__
20
+ __all__ = (
21
+ ["validate", "raise_invalid"]
22
+ + _exceptions_all
23
+ + _rules_all
24
+ + _tools_all
25
+ + _validators_all
26
+ )
27
+
28
+
29
+ _DESIGN_NOTES = r"""
30
+ # simplibs-validate — Root Package API Facade
31
+
32
+ ## Purpose
33
+ The root `simplibs.validate` package acts as a unified top-level facade. It re-exports
34
+ all primary public components across exceptions, rule shortcuts/classes, decorators,
35
+ and high-level type validators for maximum developer convenience.
36
+
37
+ ## Sub-Packages Architecture Registry
38
+
39
+ | Sub-Package | Primary Focus | Re-exported at Root | Description |
40
+ | :---------------------------- | :------------ | :------------------ | :-------------------------------------------------------------------------- |
41
+ | `simplibs.validate.exceptions` | Exceptions | Yes | Exception hierarchy (`ValidateError`, `ValidationError`, `ParamError`). |
42
+ | `simplibs.validate.rules` | Rules Engine | Yes | Validation rules, rule shortcuts, and operator compositions (`&`, `\|`, `~`).|
43
+ | `simplibs.validate.tools` | Decorators | Yes | Core decorators (`validate_call`, `validate_dataclass`, `log_this`). |
44
+ | `simplibs.validate.validators` | Function API | Yes | Type-specific functions (`validate_int`, `validate_str`, etc.). |
45
+ | `simplibs.validate.testing` | Test Suite | No | Assertion contracts and test utilities (excluded from root wildcard). |
46
+ """
@@ -0,0 +1,31 @@
1
+ from .ValidateError import ValidateError
2
+
3
+
4
+ class ParamError(ValidateError):
5
+ """Exception raised for invalid parameter or decorator configuration.
6
+
7
+ Signals a developer error made while constructing validation rules or configuring
8
+ decorators, as opposed to a `ValidationError`, which signals invalid input data.
9
+ """
10
+
11
+ pass
12
+
13
+
14
+ _DESIGN_NOTES = """
15
+ # ParamError — Developer Configuration Exception
16
+
17
+ ## Purpose
18
+ The `ParamError` class is used to catch and format errors that arise from
19
+ invalid decorator configuration or passing invalid parameters into rule constructors.
20
+ It inherits directly from `ValidateError`.
21
+
22
+ ---
23
+
24
+ ## 1. Architectural Role
25
+
26
+ * **Inheritance from `ValidateError`:**
27
+ Inherits stack-frame filtering and diagnostic card generation from `ValidateError`.
28
+ * **Semantic Distinction:**
29
+ Lets users catch configuration errors (`except ParamError`) separately from data
30
+ validation errors (`except ValidationError`).
31
+ """
@@ -0,0 +1,44 @@
1
+ from simplibs.exception import SimpleException
2
+
3
+
4
+ class ValidateError(SimpleException):
5
+ """Root exception class for all errors originating from simplibs-validate.
6
+
7
+ Serves as the single common ancestor (root exception) for every error raised
8
+ within the library. Lets users catch any error from the library with a single
9
+ except block:
10
+
11
+ try:
12
+ ...
13
+ except ValidateError as e:
14
+ ...
15
+ """
16
+
17
+ # Skips the library's internal frames when resolving the error's origin
18
+ # location. This way, the diagnostic message points directly to the
19
+ # user's own code, not to the library's internals.
20
+ skip_locations = ("simplibs/validate",)
21
+
22
+
23
+ _DESIGN_NOTES = """
24
+ # ValidateError — Root Library Exception
25
+
26
+ ## Purpose
27
+ The `ValidateError` class forms the single, unified root exception type for the
28
+ entire `simplibs-validate` library. It inherits directly from `SimpleException`.
29
+
30
+ ---
31
+
32
+ ## 1. Architectural Role & Design
33
+
34
+ ### Root Exception
35
+ * Serves purely as the abstract root exception for the library hierarchy.
36
+ * Specific subtypes (`ValidationError` for input data failures, `ParamError` for
37
+ developer configuration errors) inherit directly from this class.
38
+ * Catching `ValidateError` catches any error originating from the library.
39
+
40
+ ### Stack Trace Filtering (`skip_locations`)
41
+ * Setting `skip_locations = ("simplibs/validate",)` ensures that the
42
+ diagnostic report from `simplibs-exception` marks the origin of the error
43
+ as the line in the user's own codebase that triggered the failure.
44
+ """
@@ -0,0 +1,30 @@
1
+ from .ValidateError import ValidateError
2
+
3
+
4
+ class ValidationError(ValidateError):
5
+ """Exception raised when input data fails validation against a Rule.
6
+
7
+ Signals an invalid data value supplied at runtime (e.g., invalid function
8
+ arguments or invalid dataclass field values).
9
+ """
10
+
11
+ pass
12
+
13
+
14
+ _DESIGN_NOTES = """
15
+ # ValidationError — Data Validation Exception
16
+
17
+ ## Purpose
18
+ The `ValidationError` class is raised whenever runtime data fails to satisfy a
19
+ `Rule`. It inherits directly from `ValidateError`.
20
+
21
+ ---
22
+
23
+ ## 1. Architectural Role
24
+
25
+ * **Inheritance from `ValidateError`:**
26
+ Inherits stack-frame filtering and diagnostic card generation from `ValidateError`.
27
+ * **Semantic Distinction:**
28
+ Allows users to catch runtime input failures (`except ValidationError`) separately
29
+ from developer configuration mistakes (`except ParamError`).
30
+ """
@@ -0,0 +1,31 @@
1
+ from .build_validation_error import build_validation_error
2
+ from .ParamError import ParamError
3
+ from .ValidateError import ValidateError
4
+ from .ValidationError import ValidationError
5
+
6
+ __all__ = [
7
+ "ValidateError",
8
+ "ValidationError",
9
+ "ParamError",
10
+ "build_validation_error",
11
+ ]
12
+
13
+
14
+ _DESIGN_NOTES = """
15
+ # Validation Exceptions Sub-Package
16
+
17
+ ## Purpose
18
+ Defines the exception hierarchy for the entire `simplibs-validate` library:
19
+ the root exception type (`ValidateError`), specialized subtypes for data failures
20
+ (`ValidationError`) and configuration errors (`ParamError`), and the exception builder
21
+ factory.
22
+
23
+ ## Internal Components Registry
24
+
25
+ | Component | Type | Description |
26
+ | :------------------------ | :------- | :-------------------------------------------------------------------------- |
27
+ | `ValidateError` | Class | Abstract root exception for all errors raised by the library. |
28
+ | `ValidationError` | Class | Subclass of `ValidateError` raised when runtime input data fails validation. |
29
+ | `ParamError` | Class | Subclass of `ValidateError` raised for invalid rule/decorator setup. |
30
+ | `build_validation_error` | Function | Builds an exception instance for user-supplied callables/lambdas. |
31
+ """
@@ -0,0 +1,52 @@
1
+ from typing import Any, Callable
2
+ # Inners
3
+ from .ValidationError import ValidationError
4
+
5
+
6
+ def build_validation_error(
7
+ rule: Callable[[Any], bool],
8
+ value: Any,
9
+ value_name: str | None = None,
10
+ context: str | None = None,
11
+ ) -> Exception:
12
+ """Build a structured `ValidationError` exception for a failed user function or lambda."""
13
+ rule_name = getattr(rule, "__name__", str(rule))
14
+
15
+ return ValidationError(
16
+ error_name="VALIDATION_ERROR",
17
+ label=value_name,
18
+ expected=f"value satisfying callable condition '{rule_name}'",
19
+ value=value,
20
+ problem=f"Value failed validation check executed by callable '{rule_name}'.",
21
+ context=context,
22
+ how_to_fix=(
23
+ f"Provide a value that evaluates to True when passed to '{rule_name}'.",
24
+ ),
25
+ exception=ValueError,
26
+ )
27
+
28
+
29
+ _DESIGN_NOTES = """
30
+ # build_validation_error — Exception Factory for User-Defined Rules
31
+
32
+ ## Purpose
33
+ This function exists solely to build a structured `ValidationError` exception
34
+ for cases where validation runs through a user-supplied ad-hoc rule (one that
35
+ does not inherit from the `Rule` class). This covers any callable object —
36
+ an anonymous function (`lambda`), a plain function, or an object with a
37
+ `__call__` method — that returns a `bool`.
38
+
39
+ ---
40
+
41
+ ## 1. Rationale
42
+
43
+ * **Built-in vs. User Rules:**
44
+ Internal built-in rules (derived from `Rule`) have their own
45
+ `build_exception()` methods, where they define precise, rule-specific
46
+ `expected`, `problem`, and `how_to_fix` messages.
47
+ * **Fallback for Ad-Hoc Functions:**
48
+ If the user passes a rule such as `lambda x: x > 0`, the system has no
49
+ access to any class with a predefined error message. `build_validation_error`
50
+ extracts the function/lambda name and generates a consistent diagnostic
51
+ card on its behalf.
52
+ """
@@ -0,0 +1,84 @@
1
+ from typing import Any, Callable, NoReturn
2
+ # Inners
3
+ from .rules.base_class import Rule
4
+ from .exceptions import build_validation_error
5
+
6
+
7
+ def raise_invalid(
8
+ value: Any,
9
+ rule: Rule | Callable[[Any], bool],
10
+ *,
11
+ value_name: str | None = None,
12
+ context: str | None = None,
13
+ ) -> NoReturn:
14
+ """Unconditionally raise a validation exception associated with the given rule.
15
+
16
+ This function does not evaluate the truthiness of the rule (`is_valid` / callable is not called).
17
+ It serves as a direct shortcut for scenarios where conditional code has already verified a failure,
18
+ and the sole objective is to construct and raise the corresponding `ValidationError`.
19
+
20
+ Args:
21
+ value: The value that failed validation.
22
+ rule: A rule instance (`Rule`) or callable object used to construct the exception.
23
+ value_name: The name of the validated parameter/variable for diagnostic reporting.
24
+ context: Additional context describing the validation failure.
25
+
26
+ Raises:
27
+ ValidationError: Always raises the exception constructed by the rule or fallback factory.
28
+ """
29
+
30
+ # 1. Rule instance handling
31
+ if isinstance(rule, Rule):
32
+ raise rule.build_exception(
33
+ value,
34
+ value_name=value_name,
35
+ context=context,
36
+ )
37
+
38
+ # 2. Callable handling (plain function / lambda)
39
+ raise build_validation_error(
40
+ rule,
41
+ value,
42
+ value_name=value_name,
43
+ context=context,
44
+ )
45
+
46
+
47
+ _DESIGN_NOTES = """
48
+ # raise_invalid — Unconditional Validation Exception Trigger
49
+
50
+ ## Purpose
51
+ The `raise_invalid()` function provides a direct shortcut for raising
52
+ structured validation exceptions without re-evaluating conditions. It is
53
+ designed for the "happy path" pattern where control flow guards have already
54
+ detected a failure condition inline.
55
+
56
+ ---
57
+
58
+ ## 1. Execution Pipeline
59
+
60
+ 1. **Bypassing Evaluation Logic:**
61
+ * Unlike `validate()`, this function **never calls** `rule(value)` or
62
+ `rule.is_valid(value)`.
63
+ * It assumes the calling context has already determined validation
64
+ failure.
65
+
66
+ 2. **Exception Construction & Dispatch:**
67
+ * **`isinstance(rule, Rule)`:** Delegates exception construction to
68
+ `rule.build_exception()`.
69
+ * **Callable / Lambda:** Delegates construction to the universal fallback
70
+ factory `build_validation_error()`.
71
+ * The resulting exception is raised immediately (`NoReturn`).
72
+
73
+ ---
74
+
75
+ ## 2. Design Choices & Rationale
76
+
77
+ ### Semantic Distinction from `validate()`
78
+ * Using `validate()` makes sense when the developer wants the library to
79
+ evaluate the condition and trigger errors automatically.
80
+ * Using `raise_invalid()` is ideal under an `if not condition:` block,
81
+ explicitly communicating intent: *"The condition has already been checked;
82
+ now assemble and raise the diagnostic error card."*
83
+ * Avoids double-executing potentially expensive rule logic.
84
+ """