qnty 0.0.8__py3-none-any.whl → 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 (74) hide show
  1. qnty/__init__.py +140 -59
  2. qnty/constants/__init__.py +10 -0
  3. qnty/constants/numerical.py +18 -0
  4. qnty/constants/solvers.py +6 -0
  5. qnty/constants/tests.py +6 -0
  6. qnty/dimensions/__init__.py +23 -0
  7. qnty/dimensions/base.py +97 -0
  8. qnty/dimensions/field_dims.py +126 -0
  9. qnty/dimensions/field_dims.pyi +128 -0
  10. qnty/dimensions/signature.py +111 -0
  11. qnty/equations/__init__.py +4 -0
  12. qnty/equations/equation.py +220 -0
  13. qnty/equations/system.py +130 -0
  14. qnty/expressions/__init__.py +40 -0
  15. qnty/expressions/formatter.py +188 -0
  16. qnty/expressions/functions.py +74 -0
  17. qnty/expressions/nodes.py +701 -0
  18. qnty/expressions/types.py +70 -0
  19. qnty/extensions/plotting/__init__.py +0 -0
  20. qnty/extensions/reporting/__init__.py +0 -0
  21. qnty/problems/__init__.py +145 -0
  22. qnty/problems/composition.py +1031 -0
  23. qnty/problems/problem.py +695 -0
  24. qnty/problems/rules.py +145 -0
  25. qnty/problems/solving.py +1216 -0
  26. qnty/problems/validation.py +127 -0
  27. qnty/quantities/__init__.py +29 -0
  28. qnty/quantities/base_qnty.py +677 -0
  29. qnty/quantities/field_converters.py +24004 -0
  30. qnty/quantities/field_qnty.py +1012 -0
  31. qnty/quantities/field_setter.py +12320 -0
  32. qnty/quantities/field_vars.py +6325 -0
  33. qnty/quantities/field_vars.pyi +4191 -0
  34. qnty/solving/__init__.py +0 -0
  35. qnty/solving/manager.py +96 -0
  36. qnty/solving/order.py +403 -0
  37. qnty/solving/solvers/__init__.py +13 -0
  38. qnty/solving/solvers/base.py +82 -0
  39. qnty/solving/solvers/iterative.py +165 -0
  40. qnty/solving/solvers/simultaneous.py +475 -0
  41. qnty/units/__init__.py +1 -0
  42. qnty/units/field_units.py +10507 -0
  43. qnty/units/field_units.pyi +2461 -0
  44. qnty/units/prefixes.py +203 -0
  45. qnty/{unit.py → units/registry.py} +89 -61
  46. qnty/utils/__init__.py +16 -0
  47. qnty/utils/caching/__init__.py +23 -0
  48. qnty/utils/caching/manager.py +401 -0
  49. qnty/utils/error_handling/__init__.py +66 -0
  50. qnty/utils/error_handling/context.py +39 -0
  51. qnty/utils/error_handling/exceptions.py +96 -0
  52. qnty/utils/error_handling/handlers.py +171 -0
  53. qnty/utils/logging.py +40 -0
  54. qnty/utils/protocols.py +164 -0
  55. qnty/utils/scope_discovery.py +420 -0
  56. qnty-0.1.0.dist-info/METADATA +199 -0
  57. qnty-0.1.0.dist-info/RECORD +60 -0
  58. qnty/dimension.py +0 -186
  59. qnty/equation.py +0 -297
  60. qnty/expression.py +0 -553
  61. qnty/prefixes.py +0 -229
  62. qnty/unit_types/base.py +0 -47
  63. qnty/units.py +0 -8113
  64. qnty/variable.py +0 -300
  65. qnty/variable_types/base.py +0 -58
  66. qnty/variable_types/expression_variable.py +0 -106
  67. qnty/variable_types/typed_variable.py +0 -87
  68. qnty/variables.py +0 -2298
  69. qnty/variables.pyi +0 -6148
  70. qnty-0.0.8.dist-info/METADATA +0 -355
  71. qnty-0.0.8.dist-info/RECORD +0 -19
  72. /qnty/{unit_types → extensions}/__init__.py +0 -0
  73. /qnty/{variable_types → extensions/integration}/__init__.py +0 -0
  74. {qnty-0.0.8.dist-info → qnty-0.1.0.dist-info}/WHEEL +0 -0
qnty/problems/rules.py ADDED
@@ -0,0 +1,145 @@
1
+ """
2
+ Engineering problem checks and validation system.
3
+
4
+ This module provides a clean API for defining engineering code compliance checks,
5
+ warnings, and validation rules at the problem level rather than variable level.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import traceback
11
+ from dataclasses import dataclass
12
+ from typing import Any, Literal
13
+
14
+ from ..expressions import Expression
15
+ from ..quantities import FieldQnty, Quantity
16
+
17
+
18
+ @dataclass
19
+ class Rules:
20
+ """
21
+ Represents an engineering problem check (code compliance, validation, etc.).
22
+
23
+ Checks are defined at the EngineeringProblem class level and evaluated after solving.
24
+ They can represent code compliance rules, engineering judgment warnings, or
25
+ validation conditions.
26
+ """
27
+
28
+ condition: Expression
29
+ message: str
30
+ warning_type: str = "VALIDATION"
31
+ severity: Literal["INFO", "WARNING", "ERROR"] = "WARNING"
32
+ name: str | None = None
33
+
34
+ def __post_init__(self):
35
+ """Generate a name if not provided."""
36
+ if self.name is None:
37
+ self.name = f"{self.warning_type}_{self.severity}"
38
+
39
+ def evaluate(self, variables: dict[str, FieldQnty]) -> dict[str, Any] | None:
40
+ """
41
+ Evaluate the check condition and return a warning dict if condition is True.
42
+
43
+ Args:
44
+ variables: Dictionary of variable name -> FieldQnty object mappings
45
+
46
+ Returns:
47
+ Warning dictionary if condition is met, None otherwise
48
+ """
49
+ try:
50
+ # Evaluate the condition expression using qnty's evaluation system
51
+ result = self._evaluate_expression(self.condition, variables)
52
+
53
+ if result:
54
+ return {"type": self.warning_type, "severity": self.severity, "message": self.message, "check_name": self.name, "condition": str(self.condition)}
55
+
56
+ except Exception as e:
57
+ # If evaluation fails, return an error warning
58
+
59
+ return {
60
+ "type": "EVALUATION_ERROR",
61
+ "severity": "ERROR",
62
+ "message": f"Failed to evaluate check '{self.name}': {str(e)}",
63
+ "check_name": self.name,
64
+ "condition": str(self.condition),
65
+ "debug_info": f"Expression type: {type(self.condition)}, Variables: {list(variables.keys())}",
66
+ "traceback": traceback.format_exc(),
67
+ }
68
+
69
+ return None
70
+
71
+ def _evaluate_expression(self, expr: Expression, variables: dict[str, FieldQnty]) -> bool:
72
+ """
73
+ Evaluate a qnty expression with current variable values.
74
+
75
+ Args:
76
+ expr: The expression to evaluate
77
+ variables: Dictionary of variable name -> FieldQnty object mappings
78
+
79
+ Returns:
80
+ Boolean result of the expression evaluation
81
+ """
82
+ # Evaluate the expression using the qnty evaluation system
83
+ result = expr.evaluate(variables)
84
+
85
+ # Convert result to boolean based on type
86
+ return self._convert_result_to_bool(result)
87
+
88
+ def _convert_result_to_bool(self, result: Quantity) -> bool:
89
+ """
90
+ Convert an evaluation result to a boolean.
91
+
92
+ Args:
93
+ result: The result from expression evaluation
94
+
95
+ Returns:
96
+ Boolean interpretation of the result
97
+ """
98
+ # For qnty Quantity objects, check the value
99
+ if isinstance(result, Quantity) and result.value is not None:
100
+ return bool(result.value > 0.5)
101
+
102
+ # Fallback for any numeric types
103
+ try:
104
+ return bool(float(result) > 0.5) # type: ignore[arg-type]
105
+ except (TypeError, ValueError) as e:
106
+ raise ValueError(f"Cannot convert expression result to boolean: {result}") from e
107
+
108
+
109
+ def add_rule(condition: Expression, message: str, warning_type: str = "VALIDATION", severity: Literal["INFO", "WARNING", "ERROR"] = "WARNING", name: str | None = None) -> Rules:
110
+ """
111
+ Create a new engineering problem check.
112
+
113
+ This function is intended to be called at the class level when defining
114
+ EngineeringProblem subclasses. It creates Check objects that will be
115
+ automatically collected by the metaclass.
116
+
117
+ Args:
118
+ condition: A qnty Expression that evaluates to True when the check should trigger
119
+ message: Descriptive message explaining what the check means
120
+ warning_type: Category of check (e.g., "CODE_COMPLIANCE", "VALIDATION")
121
+ severity: Severity level of the check
122
+ name: Optional name for the check
123
+
124
+ Returns:
125
+ Check object that can be assigned to a class attribute
126
+
127
+ Example:
128
+ class MyProblem(EngineeringProblem):
129
+ # Variables...
130
+ P = Pressure(90, "psi")
131
+ t = Length(0.1, "inch")
132
+ D = Length(1.0, "inch")
133
+
134
+ # Checks defined at class level
135
+ thick_wall_check = add_check(
136
+ t.geq(D / 6),
137
+ "Thick wall condition detected - requires special consideration",
138
+ warning_type="CODE_COMPLIANCE",
139
+ severity="WARNING"
140
+ )
141
+ """
142
+ return Rules(condition=condition, message=message, warning_type=warning_type, severity=severity, name=name)
143
+
144
+
145
+ __all__ = ["add_rule"]