qnty 0.0.9__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 (92) hide show
  1. qnty/__init__.py +2 -3
  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 +1 -1
  12. qnty/equations/equation.py +118 -155
  13. qnty/equations/system.py +68 -65
  14. qnty/expressions/__init__.py +25 -46
  15. qnty/expressions/formatter.py +188 -0
  16. qnty/expressions/functions.py +46 -68
  17. qnty/expressions/nodes.py +539 -384
  18. qnty/expressions/types.py +70 -0
  19. qnty/problems/__init__.py +145 -0
  20. qnty/problems/composition.py +1031 -0
  21. qnty/problems/problem.py +695 -0
  22. qnty/problems/rules.py +145 -0
  23. qnty/problems/solving.py +1216 -0
  24. qnty/problems/validation.py +127 -0
  25. qnty/quantities/__init__.py +28 -5
  26. qnty/quantities/base_qnty.py +677 -0
  27. qnty/quantities/field_converters.py +24004 -0
  28. qnty/quantities/field_qnty.py +1012 -0
  29. qnty/{generated/setters.py → quantities/field_setter.py} +3071 -2961
  30. qnty/{generated/quantities.py → quantities/field_vars.py} +754 -432
  31. qnty/{generated/quantities.pyi → quantities/field_vars.pyi} +1289 -1290
  32. qnty/solving/manager.py +50 -44
  33. qnty/solving/order.py +181 -133
  34. qnty/solving/solvers/__init__.py +2 -9
  35. qnty/solving/solvers/base.py +27 -37
  36. qnty/solving/solvers/iterative.py +115 -135
  37. qnty/solving/solvers/simultaneous.py +93 -165
  38. qnty/units/__init__.py +1 -0
  39. qnty/{generated/units.py → units/field_units.py} +1700 -991
  40. qnty/units/field_units.pyi +2461 -0
  41. qnty/units/prefixes.py +58 -105
  42. qnty/units/registry.py +76 -89
  43. qnty/utils/__init__.py +16 -0
  44. qnty/utils/caching/__init__.py +23 -0
  45. qnty/utils/caching/manager.py +401 -0
  46. qnty/utils/error_handling/__init__.py +66 -0
  47. qnty/utils/error_handling/context.py +39 -0
  48. qnty/utils/error_handling/exceptions.py +96 -0
  49. qnty/utils/error_handling/handlers.py +171 -0
  50. qnty/utils/logging.py +4 -4
  51. qnty/utils/protocols.py +164 -0
  52. qnty/utils/scope_discovery.py +420 -0
  53. {qnty-0.0.9.dist-info → qnty-0.1.0.dist-info}/METADATA +1 -1
  54. qnty-0.1.0.dist-info/RECORD +60 -0
  55. qnty/_backup/problem_original.py +0 -1251
  56. qnty/_backup/quantity.py +0 -63
  57. qnty/codegen/cli.py +0 -125
  58. qnty/codegen/generators/data/unit_data.json +0 -8807
  59. qnty/codegen/generators/data_processor.py +0 -345
  60. qnty/codegen/generators/dimensions_gen.py +0 -434
  61. qnty/codegen/generators/doc_generator.py +0 -141
  62. qnty/codegen/generators/out/dimension_mapping.json +0 -974
  63. qnty/codegen/generators/out/dimension_metadata.json +0 -123
  64. qnty/codegen/generators/out/units_metadata.json +0 -223
  65. qnty/codegen/generators/quantities_gen.py +0 -159
  66. qnty/codegen/generators/setters_gen.py +0 -178
  67. qnty/codegen/generators/stubs_gen.py +0 -167
  68. qnty/codegen/generators/units_gen.py +0 -295
  69. qnty/expressions/cache.py +0 -94
  70. qnty/generated/dimensions.py +0 -514
  71. qnty/problem/__init__.py +0 -91
  72. qnty/problem/base.py +0 -142
  73. qnty/problem/composition.py +0 -385
  74. qnty/problem/composition_mixin.py +0 -382
  75. qnty/problem/equations.py +0 -413
  76. qnty/problem/metaclass.py +0 -302
  77. qnty/problem/reconstruction.py +0 -1016
  78. qnty/problem/solving.py +0 -180
  79. qnty/problem/validation.py +0 -64
  80. qnty/problem/variables.py +0 -239
  81. qnty/quantities/expression_quantity.py +0 -314
  82. qnty/quantities/quantity.py +0 -428
  83. qnty/quantities/typed_quantity.py +0 -215
  84. qnty/validation/__init__.py +0 -0
  85. qnty/validation/registry.py +0 -0
  86. qnty/validation/rules.py +0 -167
  87. qnty-0.0.9.dist-info/RECORD +0 -63
  88. /qnty/{codegen → extensions}/__init__.py +0 -0
  89. /qnty/{codegen/generators → extensions/integration}/__init__.py +0 -0
  90. /qnty/{codegen/generators/utils → extensions/plotting}/__init__.py +0 -0
  91. /qnty/{generated → extensions/reporting}/__init__.py +0 -0
  92. {qnty-0.0.9.dist-info → qnty-0.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,420 @@
1
+ """
2
+ Scope Discovery Service
3
+ =======================
4
+
5
+ Centralized service for automatically discovering variables from the calling scope.
6
+ Consolidates all scope inspection logic used across expressions, equations, and variable solving.
7
+
8
+ This module uses protocol-based design to avoid circular imports and duck typing performance issues.
9
+ """
10
+
11
+ import inspect
12
+ import logging
13
+ from typing import Any
14
+
15
+ from .protocols import TypeRegistry
16
+
17
+ # Setup logging for better debugging
18
+ _logger = logging.getLogger(__name__)
19
+
20
+
21
+ class ScopeDiscoveryService:
22
+ """
23
+ Centralized service for scope discovery operations.
24
+
25
+ Provides optimized variable discovery from calling scopes with caching,
26
+ depth limits, and consistent error handling.
27
+ """
28
+
29
+ # Class-level optimization settings
30
+ _scope_cache = {}
31
+ _frame_cache = {}
32
+ _variable_name_cache = {}
33
+ _max_scope_cache_size = 200 # Increased cache size
34
+ _max_frame_cache_size = 50
35
+ _max_search_depth = 8
36
+ _cache_hit_count = 0
37
+ _cache_miss_count = 0
38
+
39
+ @classmethod
40
+ def discover_variables(cls, required_vars: set[str], enable_caching: bool = True) -> dict[str, Any]:
41
+ """
42
+ Discover variables from the calling scope with enhanced caching.
43
+
44
+ Args:
45
+ required_vars: Set of variable names to find
46
+ enable_caching: Whether to use caching for performance
47
+
48
+ Returns:
49
+ Dictionary mapping variable names to variable instances
50
+ """
51
+ if not required_vars:
52
+ return {}
53
+
54
+ # Check cache first if enabled
55
+ if enable_caching:
56
+ cache_key = frozenset(required_vars)
57
+ if cache_key in cls._scope_cache:
58
+ cls._cache_hit_count += 1
59
+ _logger.debug(f"Cache hit for variables: {required_vars}")
60
+ return cls._scope_cache[cache_key]
61
+
62
+ cls._cache_miss_count += 1
63
+
64
+ # Clean cache if it gets too large (LRU-style)
65
+ if len(cls._scope_cache) >= cls._max_scope_cache_size:
66
+ # Remove oldest 25% of entries
67
+ items_to_remove = len(cls._scope_cache) // 4
68
+ for _ in range(items_to_remove):
69
+ cls._scope_cache.pop(next(iter(cls._scope_cache)))
70
+ _logger.debug(f"Cleaned {items_to_remove} entries from scope cache")
71
+
72
+ # Get the calling frame with caching
73
+ frame = cls._get_cached_user_frame()
74
+ if frame is None:
75
+ _logger.debug("No user frame found")
76
+ return {}
77
+
78
+ try:
79
+ discovered = cls._search_frame_for_variables(frame, required_vars)
80
+
81
+ # Cache the result if caching is enabled and successful
82
+ if enable_caching and required_vars:
83
+ cache_key = frozenset(required_vars)
84
+ cls._scope_cache[cache_key] = discovered
85
+ _logger.debug(f"Cached discovery result for variables: {required_vars}")
86
+
87
+ return discovered
88
+
89
+ except Exception as e:
90
+ _logger.warning(f"Error during variable discovery: {e}")
91
+ return {}
92
+
93
+ @classmethod
94
+ def can_auto_evaluate(cls, expression: Any) -> tuple[bool, dict[str, Any]]:
95
+ """
96
+ Check if expression can be auto-evaluated from scope.
97
+
98
+ Args:
99
+ expression: Expression to check for auto-evaluation
100
+
101
+ Returns:
102
+ Tuple of (can_evaluate, discovered_variables)
103
+ """
104
+ try:
105
+ # Use protocol-based checking instead of duck typing
106
+ if not TypeRegistry.is_expression(expression):
107
+ return False, {}
108
+
109
+ required_vars = expression.get_variables()
110
+ if not required_vars:
111
+ return True, {} # No variables needed, can evaluate
112
+
113
+ discovered = cls.discover_variables(required_vars, enable_caching=True)
114
+
115
+ # Check if all required variables are available and have values
116
+ for var_name in required_vars:
117
+ if var_name not in discovered:
118
+ _logger.debug(f"Variable '{var_name}' not found in scope")
119
+ return False, {}
120
+
121
+ var = discovered[var_name]
122
+ if not hasattr(var, "quantity") or var.quantity is None:
123
+ _logger.debug(f"Variable '{var_name}' has no quantity")
124
+ return False, {}
125
+
126
+ _logger.debug(f"Expression can be auto-evaluated with variables: {list(discovered.keys())}")
127
+ return True, discovered
128
+
129
+ except Exception as e:
130
+ _logger.warning(f"Error during auto-evaluation check: {e}")
131
+ return False, {}
132
+
133
+ @classmethod
134
+ def find_variables_in_scope(cls, filter_func=None) -> dict[str, Any]:
135
+ """
136
+ Find all UnifiedVariable instances in the calling scope.
137
+
138
+ Args:
139
+ filter_func: Optional function to filter variables (var) -> bool
140
+
141
+ Returns:
142
+ Dictionary mapping variable names/symbols to variable instances
143
+ """
144
+ frame = inspect.currentframe()
145
+ if frame is None:
146
+ _logger.warning("Unable to access current frame")
147
+ return {}
148
+
149
+ try:
150
+ frame = cls._find_user_frame(frame)
151
+ if frame is None:
152
+ return {}
153
+
154
+ discovered = {}
155
+
156
+ # Search locals first
157
+ for obj in frame.f_locals.values():
158
+ if TypeRegistry.is_variable(obj):
159
+ if filter_func is None or filter_func(obj):
160
+ var_name = cls._get_variable_name(obj)
161
+ if var_name:
162
+ discovered[var_name] = obj
163
+
164
+ # Search globals for remaining variables
165
+ for obj in frame.f_globals.values():
166
+ if TypeRegistry.is_variable(obj):
167
+ if filter_func is None or filter_func(obj):
168
+ var_name = cls._get_variable_name(obj)
169
+ if var_name and var_name not in discovered:
170
+ discovered[var_name] = obj
171
+
172
+ return discovered
173
+
174
+ finally:
175
+ del frame
176
+
177
+ @classmethod
178
+ def _get_cached_user_frame(cls) -> Any | None:
179
+ """
180
+ Get user frame with caching to reduce repeated frame traversal.
181
+
182
+ Returns:
183
+ User frame or None if not found
184
+ """
185
+ # Get current frame for cache key generation
186
+ current_frame = inspect.currentframe()
187
+ if current_frame is None:
188
+ return None
189
+
190
+ try:
191
+ # Create cache key based on frame signature
192
+ frame_id = id(current_frame)
193
+
194
+ # Check frame cache first
195
+ if frame_id in cls._frame_cache:
196
+ cached_frame = cls._frame_cache[frame_id]
197
+ if cached_frame is not None:
198
+ return cached_frame
199
+
200
+ # Clean frame cache if too large
201
+ if len(cls._frame_cache) >= cls._max_frame_cache_size:
202
+ cls._frame_cache.clear()
203
+
204
+ # Find user frame using optimized search
205
+ user_frame = cls._find_user_frame_optimized(current_frame)
206
+
207
+ # Cache the result
208
+ cls._frame_cache[frame_id] = user_frame
209
+ return user_frame
210
+
211
+ finally:
212
+ del current_frame
213
+
214
+ @classmethod
215
+ def _find_user_frame_optimized(cls, current_frame: Any) -> Any | None:
216
+ """
217
+ Optimized frame search with precompiled patterns.
218
+
219
+ Args:
220
+ current_frame: Starting frame
221
+
222
+ Returns:
223
+ User frame or None if not found within depth limit
224
+ """
225
+ frame = current_frame
226
+ depth = 0
227
+
228
+ # Pre-compiled sets for faster lookups
229
+ internal_file_endings = frozenset(["expression.py", "equation.py", "nodes.py", "scope_discovery.py", "expression_quantity.py", "unified_variable.py", "field_qnty.py"])
230
+ internal_function_names = frozenset(["__str__", "__repr__", "_can_auto_evaluate", "_discover_variables_from_scope", "solve_from", "evaluate"])
231
+
232
+ while frame and depth < cls._max_search_depth:
233
+ code = frame.f_code
234
+ filename = code.co_filename
235
+ function_name = code.co_name
236
+
237
+ # Fast check: is this frame internal?
238
+ is_internal = any(filename.endswith(ending) for ending in internal_file_endings) or function_name in internal_function_names
239
+
240
+ if not is_internal:
241
+ _logger.debug(f"Found user frame at depth {depth}: {filename}:{function_name}")
242
+ return frame
243
+
244
+ frame = frame.f_back
245
+ depth += 1
246
+
247
+ _logger.debug(f"No user frame found within {cls._max_search_depth} levels")
248
+ return None
249
+
250
+ @classmethod
251
+ def _find_user_frame(cls, current_frame: Any) -> Any | None:
252
+ """
253
+ Legacy method for backward compatibility.
254
+ """
255
+ return cls._find_user_frame_optimized(current_frame)
256
+
257
+ @classmethod
258
+ def _search_frame_for_variables(cls, frame: Any, required_vars: set[str]) -> dict[str, Any]:
259
+ """
260
+ Search a specific frame for required variables.
261
+
262
+ Args:
263
+ frame: Frame to search
264
+ required_vars: Set of variable names to find
265
+
266
+ Returns:
267
+ Dictionary of found variables
268
+ """
269
+ discovered = {}
270
+
271
+ # Search locals first (most common case)
272
+ local_vars = frame.f_locals
273
+ for var_name in required_vars:
274
+ # Direct lookup first (fastest)
275
+ if var_name in local_vars:
276
+ obj = local_vars[var_name]
277
+ if TypeRegistry.is_variable(obj):
278
+ discovered[var_name] = obj
279
+ continue
280
+
281
+ # Get globals once for reuse
282
+ global_vars = frame.f_globals
283
+
284
+ # Search globals only for remaining variables
285
+ if len(discovered) < len(required_vars):
286
+ remaining_vars = required_vars - discovered.keys()
287
+ for var_name in remaining_vars:
288
+ if var_name in global_vars:
289
+ obj = global_vars[var_name]
290
+ if TypeRegistry.is_variable(obj):
291
+ discovered[var_name] = obj
292
+
293
+ # Search by symbol/name for remaining variables (optimized)
294
+ if len(discovered) < len(required_vars):
295
+ remaining_vars = required_vars - discovered.keys()
296
+ cls._search_by_symbol_name_optimized(local_vars, global_vars, remaining_vars, discovered)
297
+
298
+ _logger.debug(f"Found {len(discovered)} of {len(required_vars)} required variables")
299
+ return discovered
300
+
301
+ @classmethod
302
+ def _search_by_symbol_name_optimized(cls, local_vars: dict, global_vars: dict, remaining_vars: set[str], discovered: dict[str, Any]) -> None:
303
+ """Optimized search for variables by their symbol/name attribute."""
304
+ # Convert to list once to avoid repeated set operations
305
+ remaining_list = list(remaining_vars)
306
+
307
+ # Search locals by symbol/name with early termination
308
+ for obj in local_vars.values():
309
+ if not remaining_list: # Check list instead of set
310
+ break
311
+ if TypeRegistry.is_variable(obj):
312
+ obj_name = cls._get_variable_name(obj)
313
+ if obj_name in remaining_vars: # Still check set for O(1) lookup
314
+ discovered[obj_name] = obj
315
+ remaining_list.remove(obj_name)
316
+ remaining_vars.remove(obj_name)
317
+
318
+ # Search globals by symbol/name if still needed
319
+ if remaining_list:
320
+ for obj in global_vars.values():
321
+ if not remaining_list:
322
+ break
323
+ if TypeRegistry.is_variable(obj):
324
+ obj_name = cls._get_variable_name(obj)
325
+ if obj_name in remaining_vars:
326
+ discovered[obj_name] = obj
327
+ remaining_list.remove(obj_name)
328
+ remaining_vars.remove(obj_name)
329
+
330
+ @classmethod
331
+ def _search_by_symbol_name(cls, local_vars: dict, global_vars: dict, remaining_vars: set[str], discovered: dict[str, Any]) -> None:
332
+ """Legacy method for backward compatibility."""
333
+ cls._search_by_symbol_name_optimized(local_vars, global_vars, remaining_vars, discovered)
334
+
335
+ @classmethod
336
+ def _get_variable_name(cls, var) -> str | None:
337
+ """
338
+ Get the name/symbol to use for a variable with caching.
339
+
340
+ Args:
341
+ var: Variable instance
342
+
343
+ Returns:
344
+ Variable name/symbol or None if not available
345
+ """
346
+ var_id = id(var)
347
+
348
+ # Check cache first
349
+ if var_id in cls._variable_name_cache:
350
+ return cls._variable_name_cache[var_id]
351
+
352
+ try:
353
+ # Prefer symbol over name for equation solving
354
+ name = var.symbol if var.symbol else var.name
355
+
356
+ # Cache the result
357
+ cls._variable_name_cache[var_id] = name
358
+ return name
359
+ except (AttributeError, TypeError):
360
+ cls._variable_name_cache[var_id] = None
361
+ return None
362
+
363
+ @classmethod
364
+ def clear_cache(cls) -> None:
365
+ """Clear all caches for testing or memory management."""
366
+ cls._scope_cache.clear()
367
+ cls._frame_cache.clear()
368
+ cls._variable_name_cache.clear()
369
+ cls._cache_hit_count = 0
370
+ cls._cache_miss_count = 0
371
+ TypeRegistry.clear_cache()
372
+ _logger.debug("Cleared all scope discovery caches")
373
+
374
+ @classmethod
375
+ def get_cache_stats(cls) -> dict[str, Any]:
376
+ """Get cache performance statistics."""
377
+ total_requests = cls._cache_hit_count + cls._cache_miss_count
378
+ hit_rate = (cls._cache_hit_count / total_requests * 100) if total_requests > 0 else 0
379
+
380
+ return {
381
+ "scope_cache_size": len(cls._scope_cache),
382
+ "frame_cache_size": len(cls._frame_cache),
383
+ "variable_name_cache_size": len(cls._variable_name_cache),
384
+ "cache_hits": cls._cache_hit_count,
385
+ "cache_misses": cls._cache_miss_count,
386
+ "hit_rate_percent": round(hit_rate, 2),
387
+ }
388
+
389
+ @classmethod
390
+ def set_max_depth(cls, depth: int) -> None:
391
+ """Set maximum search depth for scope discovery."""
392
+ if depth > 0:
393
+ cls._max_search_depth = depth
394
+ _logger.debug(f"Set max search depth to {depth}")
395
+ else:
396
+ raise ValueError("Depth must be positive")
397
+
398
+ @classmethod
399
+ def enable_debug_logging(cls) -> None:
400
+ """Enable debug logging for scope discovery operations."""
401
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
402
+
403
+ @classmethod
404
+ def disable_debug_logging(cls) -> None:
405
+ """Disable debug logging for scope discovery operations."""
406
+ logging.getLogger(__name__).setLevel(logging.WARNING)
407
+
408
+
409
+ # Convenience function for backward compatibility
410
+ def discover_variables_from_scope(required_vars: set[str]) -> dict[str, Any]:
411
+ """
412
+ Convenience function to discover variables from scope.
413
+
414
+ Args:
415
+ required_vars: Set of variable names to find
416
+
417
+ Returns:
418
+ Dictionary mapping variable names to variable instances
419
+ """
420
+ return ScopeDiscoveryService.discover_variables(required_vars)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: qnty
3
- Version: 0.0.9
3
+ Version: 0.1.0
4
4
  Summary: High-performance unit system library for Python with dimensional safety and fast unit conversions
5
5
  License: Apache-2.0
6
6
  Keywords: units,dimensional analysis,engineering,physics,quantities,measurements
@@ -0,0 +1,60 @@
1
+ qnty/__init__.py,sha256=JlMYdpcYFD8agf9nJrxnBw-MXKzGxcqCO4wFxTICQaA,5564
2
+ qnty/constants/__init__.py,sha256=-ADevTOA1tgi5OebYDFzP5ov8jq7Bwy66BCZqiXmGJk,267
3
+ qnty/constants/numerical.py,sha256=zs1OaSV5NDnxHLELzHz_G3NcetuF7JEO0Lih4BGUz60,679
4
+ qnty/constants/solvers.py,sha256=f9bMxxSu99Bg0laWBnLkWbbD5-N02rHiLqlTmO-VSik,212
5
+ qnty/constants/tests.py,sha256=viGxxGBDIu0uA2nJtK20liJ1_ZjqkC20XghxwDaXRv8,218
6
+ qnty/dimensions/__init__.py,sha256=MtHz9Auvpv2xJ4jxRTT7mL1EFk5fuBLJlhxhSRRfSRc,672
7
+ qnty/dimensions/base.py,sha256=YkEn0fvXKq2Utruh2lGAdIT1mVrhu24QXfDl0CMUEG4,2604
8
+ qnty/dimensions/field_dims.py,sha256=bcPu1xxPhjoNjc7TxyP_B4xKDLHKGdtNne-sCB9hz-8,5300
9
+ qnty/dimensions/field_dims.pyi,sha256=lk3YrH3Ovs3CJCZe5MfX334kdpmsfEql4D3fLKjuYDs,4575
10
+ qnty/dimensions/signature.py,sha256=yk7QGejAV-TEPTqWE1Q5yV2sZA-RWGiK_rHiMT0Q2yU,4173
11
+ qnty/equations/__init__.py,sha256=Ou5H6tTFXgVw16JYan_a4653NxroBxcnTY6YWt380Qo,108
12
+ qnty/equations/equation.py,sha256=6Ot3-XhSFyxdv3hUwJvdTvB2BGZlAoXX46uok_6q-14,9041
13
+ qnty/equations/system.py,sha256=vMoD1iTUrAHnVFVvCUKeyNfSBfMiqpwQbfDx46kN9N8,5155
14
+ qnty/expressions/__init__.py,sha256=DA2s7DBhVCmdUgsYSTJWObsp2DbbpFn492yr1nUTg2g,930
15
+ qnty/expressions/formatter.py,sha256=yLGLwLYjhBvVi2Q6rfkg8pbyH0-a1Ko0AYLsqJTJf50,7806
16
+ qnty/expressions/functions.py,sha256=ek43udfUDpThKo38rVPBYPvKfZNc9Bbs8RuL-CvQc_A,2729
17
+ qnty/expressions/nodes.py,sha256=7JxHzhqZNrNUqShIBsIyuLmHQyeC14m4RxPCwxKvmrE,28431
18
+ qnty/expressions/types.py,sha256=eoM-IqY-k-IypRHAlRwjEtMmB6DiwX7YGot8t_vGw3o,1729
19
+ qnty/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ qnty/extensions/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ qnty/extensions/plotting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ qnty/extensions/reporting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ qnty/problems/__init__.py,sha256=g7zuml2IecoSwgzX6r1zZ5SlmBKFc8qqTR_cao037pc,4808
24
+ qnty/problems/composition.py,sha256=JUOu3IksLRJEJ2OvPyarxkuzvcrnYI9fNeov2Lj7ynk,41937
25
+ qnty/problems/problem.py,sha256=Yh7wLo7RyZcR9fie6niJqcnP81rZhDKtNTgd5KQr1XE,28279
26
+ qnty/problems/rules.py,sha256=NwIStAa8bocVtvzAsnPmRdC_0ENTJWyXLOoYBnkvpPA,5176
27
+ qnty/problems/solving.py,sha256=LTI8F9ujDiSqXE9Aiz8sOgaGJNX9p7oaR5CQIZHpCY8,44315
28
+ qnty/problems/validation.py,sha256=SmFEsgHx5XwRNlR2suOhxO-WNsOwPZhCP8wyVKYo1EE,4826
29
+ qnty/quantities/__init__.py,sha256=K_h5v6X6-OyITSXOhbIZTDAJe6-y_7iMMDEIQ4O3luc,809
30
+ qnty/quantities/base_qnty.py,sha256=QasOR4-a7gwPBvc6cLJ3ooQHmOcWbYexgtNQ9I6bXI8,32516
31
+ qnty/quantities/field_converters.py,sha256=rDWttIE0lwF1doGlLG5RJTcTikYEYruMrRBMlr8fvBI,1008701
32
+ qnty/quantities/field_qnty.py,sha256=9A-KP8DyO5oOfmxw41HKJq48dUF0LP9M_YYqvdbVvRM,42562
33
+ qnty/quantities/field_setter.py,sha256=JCvRom4qvCYvgRNgFLZEuwb1PCmz0qrKzxDv0-h4RMo,449348
34
+ qnty/quantities/field_vars.py,sha256=mo-kh3WFx6h_dfROUIXAyhdDAoEDEgGN_TlaLwu_o1U,264561
35
+ qnty/quantities/field_vars.pyi,sha256=DJtLmxXJ9MrphAqSSOkMYNlLrq7-mAzvclp6bufT4RY,154868
36
+ qnty/solving/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ qnty/solving/manager.py,sha256=LQBMhWD3ajRYMBXkwRpkVzdo7qVEDviBAoHpjAzS-0U,3945
38
+ qnty/solving/order.py,sha256=q1G3fMWamhmBK6vN0L2BuTqWl0aa94ZJPCWusrntcXo,15488
39
+ qnty/solving/solvers/__init__.py,sha256=7hM2Fz4jCS8xf5Kd3qDqkEmvtT1PO72jXguoQA_Fvqo,475
40
+ qnty/solving/solvers/base.py,sha256=UgXRhnx9m331Hn2P3U-0qTfSQIkfOhEw_MfqcLhxxBM,2839
41
+ qnty/solving/solvers/iterative.py,sha256=dZw66VRz0ScnkPsJl2miKgH7VVcGJQw1zq-5wzU0CZU,7557
42
+ qnty/solving/solvers/simultaneous.py,sha256=hLZ8878BqiI5NQd8eeRG5Sy9ztS43BBX4mk3BDMVs_4,21609
43
+ qnty/units/__init__.py,sha256=WgH6t1obC5i2ioEykO8H3z_csoRL6fP6xjzXn2_EB80,27
44
+ qnty/units/field_units.py,sha256=juW8qzt7UaL4lIMl5p_GVcfH6h6gQz7bFuOUOKRX7rY,283034
45
+ qnty/units/field_units.pyi,sha256=1iW_yWF2PWQ8wZ1vSp2SbHk4A6eiG-Hfw-9VdSBf7s0,77949
46
+ qnty/units/prefixes.py,sha256=tSD8CIPjFtCuwl2Og1a1pmqLoTvfeTljxMqPuHBC_dE,6667
47
+ qnty/units/registry.py,sha256=bfnD4kWkaEnX0Vkb7Dxa1K-YGhtjMNQjevLpcMc7KCQ,6728
48
+ qnty/utils/__init__.py,sha256=r9sYK7anOF5KoDqw6rK0O1dCVXV4MKAtt_4gab7PZIk,533
49
+ qnty/utils/caching/__init__.py,sha256=vgR18cUhDnOkB-3Qv-Kcj0l9lSZ_cD48MSfjaAHKjpA,456
50
+ qnty/utils/caching/manager.py,sha256=B9-p9eD57SjBTZwfa8LqfAwK7arhy0zH7faoE_lQt8M,16893
51
+ qnty/utils/error_handling/__init__.py,sha256=6J8a1NdaeQGtGa6r6Rc-x8FcIc5adJZ6ngm21bZXbFI,1571
52
+ qnty/utils/error_handling/context.py,sha256=hTwQst5sFWKo2UrpH6768ERwqcFfbwVQz8aNuO0fveo,1353
53
+ qnty/utils/error_handling/exceptions.py,sha256=8O0gzoTJqz1Gw9h8sdN16DKIf_ZBn2Lzsu9gyLHknXU,3608
54
+ qnty/utils/error_handling/handlers.py,sha256=_q12co-jr4YSktRoCPpGBbh6WXEDw9MbmWxUge0YWU8,8007
55
+ qnty/utils/logging.py,sha256=2H6_gSOQjxdK5024XTY3E1jGIQPE8WdalVhVBFw51OA,1143
56
+ qnty/utils/protocols.py,sha256=c_Ya_epCm7qenAADRMZiwiQ0PdD-Z4T85b1z1YQNXAk,5247
57
+ qnty/utils/scope_discovery.py,sha256=mQc-FHJ5-VNBzqQwiFofV-hqeF3GpLRaLlTjYDRnOqs,15184
58
+ qnty-0.1.0.dist-info/METADATA,sha256=IEWbkj_Ll1dkIkr50avhKUlChVE6rrAnSy5Bv9y4Ma0,6761
59
+ qnty-0.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
60
+ qnty-0.1.0.dist-info/RECORD,,