tnfr 4.5.2__py3-none-any.whl → 6.0.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 (161) hide show
  1. tnfr/__init__.py +228 -49
  2. tnfr/__init__.pyi +40 -0
  3. tnfr/_compat.py +11 -0
  4. tnfr/_version.py +7 -0
  5. tnfr/_version.pyi +7 -0
  6. tnfr/alias.py +106 -21
  7. tnfr/alias.pyi +140 -0
  8. tnfr/cache.py +666 -512
  9. tnfr/cache.pyi +232 -0
  10. tnfr/callback_utils.py +2 -9
  11. tnfr/callback_utils.pyi +105 -0
  12. tnfr/cli/__init__.py +21 -7
  13. tnfr/cli/__init__.pyi +47 -0
  14. tnfr/cli/arguments.py +42 -20
  15. tnfr/cli/arguments.pyi +33 -0
  16. tnfr/cli/execution.py +54 -20
  17. tnfr/cli/execution.pyi +80 -0
  18. tnfr/cli/utils.py +0 -2
  19. tnfr/cli/utils.pyi +8 -0
  20. tnfr/config/__init__.py +12 -0
  21. tnfr/config/__init__.pyi +8 -0
  22. tnfr/config/constants.py +104 -0
  23. tnfr/config/constants.pyi +12 -0
  24. tnfr/{config.py → config/init.py} +11 -7
  25. tnfr/config/init.pyi +8 -0
  26. tnfr/config/operator_names.py +106 -0
  27. tnfr/config/operator_names.pyi +28 -0
  28. tnfr/config/presets.py +104 -0
  29. tnfr/config/presets.pyi +7 -0
  30. tnfr/constants/__init__.py +78 -24
  31. tnfr/constants/__init__.pyi +104 -0
  32. tnfr/constants/core.py +1 -2
  33. tnfr/constants/core.pyi +17 -0
  34. tnfr/constants/init.pyi +12 -0
  35. tnfr/constants/metric.py +4 -12
  36. tnfr/constants/metric.pyi +19 -0
  37. tnfr/constants_glyphs.py +9 -91
  38. tnfr/constants_glyphs.pyi +12 -0
  39. tnfr/dynamics/__init__.py +112 -634
  40. tnfr/dynamics/__init__.pyi +83 -0
  41. tnfr/dynamics/adaptation.py +201 -0
  42. tnfr/dynamics/aliases.py +22 -0
  43. tnfr/dynamics/coordination.py +343 -0
  44. tnfr/dynamics/dnfr.py +1936 -354
  45. tnfr/dynamics/dnfr.pyi +33 -0
  46. tnfr/dynamics/integrators.py +369 -75
  47. tnfr/dynamics/integrators.pyi +35 -0
  48. tnfr/dynamics/runtime.py +521 -0
  49. tnfr/dynamics/sampling.py +8 -5
  50. tnfr/dynamics/sampling.pyi +7 -0
  51. tnfr/dynamics/selectors.py +680 -0
  52. tnfr/execution.py +56 -41
  53. tnfr/execution.pyi +65 -0
  54. tnfr/flatten.py +7 -7
  55. tnfr/flatten.pyi +28 -0
  56. tnfr/gamma.py +54 -37
  57. tnfr/gamma.pyi +40 -0
  58. tnfr/glyph_history.py +85 -38
  59. tnfr/glyph_history.pyi +53 -0
  60. tnfr/grammar.py +19 -338
  61. tnfr/grammar.pyi +13 -0
  62. tnfr/helpers/__init__.py +110 -30
  63. tnfr/helpers/__init__.pyi +66 -0
  64. tnfr/helpers/numeric.py +1 -0
  65. tnfr/helpers/numeric.pyi +12 -0
  66. tnfr/immutable.py +55 -19
  67. tnfr/immutable.pyi +37 -0
  68. tnfr/initialization.py +12 -10
  69. tnfr/initialization.pyi +73 -0
  70. tnfr/io.py +99 -34
  71. tnfr/io.pyi +11 -0
  72. tnfr/locking.pyi +7 -0
  73. tnfr/metrics/__init__.pyi +20 -0
  74. tnfr/metrics/coherence.py +934 -294
  75. tnfr/metrics/common.py +1 -3
  76. tnfr/metrics/common.pyi +15 -0
  77. tnfr/metrics/core.py +192 -34
  78. tnfr/metrics/core.pyi +13 -0
  79. tnfr/metrics/diagnosis.py +707 -101
  80. tnfr/metrics/diagnosis.pyi +89 -0
  81. tnfr/metrics/export.py +27 -13
  82. tnfr/metrics/glyph_timing.py +218 -38
  83. tnfr/metrics/reporting.py +22 -18
  84. tnfr/metrics/reporting.pyi +12 -0
  85. tnfr/metrics/sense_index.py +199 -25
  86. tnfr/metrics/sense_index.pyi +9 -0
  87. tnfr/metrics/trig.py +53 -18
  88. tnfr/metrics/trig.pyi +12 -0
  89. tnfr/metrics/trig_cache.py +3 -7
  90. tnfr/metrics/trig_cache.pyi +10 -0
  91. tnfr/node.py +148 -125
  92. tnfr/node.pyi +161 -0
  93. tnfr/observers.py +44 -30
  94. tnfr/observers.pyi +46 -0
  95. tnfr/ontosim.py +14 -13
  96. tnfr/ontosim.pyi +33 -0
  97. tnfr/operators/__init__.py +84 -52
  98. tnfr/operators/__init__.pyi +31 -0
  99. tnfr/operators/definitions.py +181 -0
  100. tnfr/operators/definitions.pyi +92 -0
  101. tnfr/operators/jitter.py +86 -23
  102. tnfr/operators/jitter.pyi +11 -0
  103. tnfr/operators/registry.py +80 -0
  104. tnfr/operators/registry.pyi +15 -0
  105. tnfr/operators/remesh.py +141 -57
  106. tnfr/presets.py +9 -54
  107. tnfr/presets.pyi +7 -0
  108. tnfr/py.typed +0 -0
  109. tnfr/rng.py +259 -73
  110. tnfr/rng.pyi +14 -0
  111. tnfr/selector.py +24 -17
  112. tnfr/selector.pyi +19 -0
  113. tnfr/sense.py +55 -43
  114. tnfr/sense.pyi +30 -0
  115. tnfr/structural.py +44 -267
  116. tnfr/structural.pyi +46 -0
  117. tnfr/telemetry/__init__.py +13 -0
  118. tnfr/telemetry/verbosity.py +37 -0
  119. tnfr/tokens.py +3 -2
  120. tnfr/tokens.pyi +41 -0
  121. tnfr/trace.py +272 -82
  122. tnfr/trace.pyi +68 -0
  123. tnfr/types.py +345 -6
  124. tnfr/types.pyi +145 -0
  125. tnfr/utils/__init__.py +158 -0
  126. tnfr/utils/__init__.pyi +133 -0
  127. tnfr/utils/cache.py +755 -0
  128. tnfr/utils/cache.pyi +156 -0
  129. tnfr/{collections_utils.py → utils/data.py} +57 -90
  130. tnfr/utils/data.pyi +73 -0
  131. tnfr/utils/graph.py +87 -0
  132. tnfr/utils/graph.pyi +10 -0
  133. tnfr/utils/init.py +746 -0
  134. tnfr/utils/init.pyi +85 -0
  135. tnfr/{json_utils.py → utils/io.py} +13 -18
  136. tnfr/utils/io.pyi +10 -0
  137. tnfr/utils/validators.py +130 -0
  138. tnfr/utils/validators.pyi +19 -0
  139. tnfr/validation/__init__.py +25 -0
  140. tnfr/validation/__init__.pyi +17 -0
  141. tnfr/validation/compatibility.py +59 -0
  142. tnfr/validation/compatibility.pyi +8 -0
  143. tnfr/validation/grammar.py +149 -0
  144. tnfr/validation/grammar.pyi +11 -0
  145. tnfr/validation/rules.py +194 -0
  146. tnfr/validation/rules.pyi +18 -0
  147. tnfr/validation/syntax.py +151 -0
  148. tnfr/validation/syntax.pyi +7 -0
  149. tnfr-6.0.0.dist-info/METADATA +135 -0
  150. tnfr-6.0.0.dist-info/RECORD +157 -0
  151. tnfr/graph_utils.py +0 -84
  152. tnfr/import_utils.py +0 -228
  153. tnfr/logging_utils.py +0 -116
  154. tnfr/validators.py +0 -84
  155. tnfr/value_utils.py +0 -59
  156. tnfr-4.5.2.dist-info/METADATA +0 -379
  157. tnfr-4.5.2.dist-info/RECORD +0 -67
  158. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/WHEEL +0 -0
  159. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/entry_points.txt +0 -0
  160. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/licenses/LICENSE.md +0 -0
  161. {tnfr-4.5.2.dist-info → tnfr-6.0.0.dist-info}/top_level.txt +0 -0
tnfr/io.py CHANGED
@@ -1,9 +1,9 @@
1
1
  """Structured file I/O utilities.
2
2
 
3
3
  Optional parsers such as ``tomllib``/``tomli`` and ``pyyaml`` are loaded via
4
- the :func:`tnfr.import_utils.cached_import` helper. Their import results and
4
+ the :func:`tnfr.utils.cached_import` helper. Their import results and
5
5
  failure states are cached and can be cleared with
6
- ``cached_import.cache_clear()`` and :func:`tnfr.import_utils.prune_failed_imports`
6
+ ``cached_import.cache_clear()`` and :func:`tnfr.utils.prune_failed_imports`
7
7
  when needed.
8
8
  """
9
9
 
@@ -16,8 +16,7 @@ from pathlib import Path
16
16
  from typing import Any, Callable
17
17
  from functools import partial
18
18
 
19
- from .import_utils import cached_import
20
- from .logging_utils import get_logger
19
+ from .utils import LazyImportProxy, cached_import, get_logger
21
20
 
22
21
 
23
22
  def _raise_import_error(name: str, *_: Any, **__: Any) -> Any:
@@ -37,47 +36,72 @@ _MISSING_YAML_ERROR = type(
37
36
  )
38
37
 
39
38
 
39
+ def _resolve_lazy(value: Any) -> Any:
40
+ if isinstance(value, LazyImportProxy):
41
+ return value.resolve()
42
+ return value
43
+
44
+
45
+ class _LazyBool:
46
+ __slots__ = ("_value",)
47
+
48
+ def __init__(self, value: Any) -> None:
49
+ self._value = value
50
+
51
+ def __bool__(self) -> bool:
52
+ return _resolve_lazy(self._value) is not None
53
+
54
+
55
+ _TOMLI_MODULE = cached_import("tomli", emit="log", lazy=True)
40
56
  tomllib = cached_import(
41
57
  "tomllib",
42
58
  emit="log",
43
- fallback=cached_import("tomli", emit="log"),
59
+ lazy=True,
60
+ fallback=_TOMLI_MODULE,
44
61
  )
45
- has_toml = tomllib is not None
62
+ has_toml = _LazyBool(tomllib)
46
63
 
47
64
 
65
+ _TOMLI_TOML_ERROR = cached_import(
66
+ "tomli",
67
+ "TOMLDecodeError",
68
+ emit="log",
69
+ lazy=True,
70
+ fallback=_MISSING_TOML_ERROR,
71
+ )
48
72
  TOMLDecodeError = cached_import(
49
73
  "tomllib",
50
74
  "TOMLDecodeError",
51
75
  emit="log",
52
- fallback=cached_import(
53
- "tomli",
54
- "TOMLDecodeError",
55
- emit="log",
56
- fallback=_MISSING_TOML_ERROR,
57
- ),
76
+ lazy=True,
77
+ fallback=_TOMLI_TOML_ERROR,
58
78
  )
59
79
 
60
80
 
81
+ _TOMLI_LOADS = cached_import(
82
+ "tomli",
83
+ "loads",
84
+ emit="log",
85
+ lazy=True,
86
+ fallback=partial(_raise_import_error, "tomllib/tomli"),
87
+ )
61
88
  _TOML_LOADS: Callable[[str], Any] = cached_import(
62
89
  "tomllib",
63
90
  "loads",
64
91
  emit="log",
65
- fallback=cached_import(
66
- "tomli",
67
- "loads",
68
- emit="log",
69
- fallback=partial(_raise_import_error, "tomllib/tomli"),
70
- ),
92
+ lazy=True,
93
+ fallback=_TOMLI_LOADS,
71
94
  )
72
95
 
73
96
 
74
- yaml = cached_import("yaml", emit="log")
97
+ yaml = cached_import("yaml", emit="log", lazy=True)
75
98
 
76
99
 
77
100
  YAMLError = cached_import(
78
101
  "yaml",
79
102
  "YAMLError",
80
103
  emit="log",
104
+ lazy=True,
81
105
  fallback=_MISSING_YAML_ERROR,
82
106
  )
83
107
 
@@ -86,6 +110,7 @@ _YAML_SAFE_LOAD: Callable[[str], Any] = cached_import(
86
110
  "yaml",
87
111
  "safe_load",
88
112
  emit="log",
113
+ lazy=True,
89
114
  fallback=partial(_raise_import_error, "pyyaml"),
90
115
  )
91
116
 
@@ -115,28 +140,73 @@ def _get_parser(suffix: str) -> Callable[[str], Any]:
115
140
  raise ValueError(f"Unsupported suffix: {suffix}") from exc
116
141
 
117
142
 
118
- ERROR_MESSAGES = {
143
+ _BASE_ERROR_MESSAGES: dict[type[BaseException], str] = {
119
144
  OSError: "Could not read {path}: {e}",
120
145
  UnicodeDecodeError: "Encoding error while reading {path}: {e}",
121
146
  json.JSONDecodeError: "Error parsing JSON file at {path}: {e}",
122
- YAMLError: "Error parsing YAML file at {path}: {e}",
123
147
  ImportError: "Missing dependency parsing {path}: {e}",
124
148
  }
125
- if has_toml:
126
- ERROR_MESSAGES[TOMLDecodeError] = "Error parsing TOML file at {path}: {e}"
149
+
150
+
151
+ def _resolve_exception_type(candidate: Any) -> type[BaseException] | None:
152
+ resolved = _resolve_lazy(candidate)
153
+ if isinstance(resolved, type) and issubclass(resolved, BaseException):
154
+ return resolved
155
+ return None
156
+
157
+
158
+ _OPTIONAL_ERROR_MESSAGE_FACTORIES: tuple[
159
+ tuple[Callable[[], type[BaseException] | None], str],
160
+ ...,
161
+ ] = (
162
+ (lambda: _resolve_exception_type(YAMLError), "Error parsing YAML file at {path}: {e}"),
163
+ (lambda: _resolve_exception_type(TOMLDecodeError), "Error parsing TOML file at {path}: {e}"),
164
+ )
165
+
166
+
167
+ _BASE_STRUCTURED_EXCEPTIONS = (
168
+ OSError,
169
+ UnicodeDecodeError,
170
+ json.JSONDecodeError,
171
+ ImportError,
172
+ )
173
+
174
+
175
+ def _iter_optional_exceptions() -> list[type[BaseException]]:
176
+ errors: list[type[BaseException]] = []
177
+ for resolver, _ in _OPTIONAL_ERROR_MESSAGE_FACTORIES:
178
+ exc_type = resolver()
179
+ if exc_type is not None:
180
+ errors.append(exc_type)
181
+ return errors
182
+
183
+
184
+ def _is_structured_error(exc: Exception) -> bool:
185
+ if isinstance(exc, _BASE_STRUCTURED_EXCEPTIONS):
186
+ return True
187
+ for optional_exc in _iter_optional_exceptions():
188
+ if isinstance(exc, optional_exc):
189
+ return True
190
+ return False
127
191
 
128
192
 
129
193
  def _format_structured_file_error(path: Path, e: Exception) -> str:
130
- for exc, msg in ERROR_MESSAGES.items():
194
+ for exc, msg in _BASE_ERROR_MESSAGES.items():
131
195
  if isinstance(e, exc):
132
196
  return msg.format(path=path, e=e)
197
+
198
+ for resolver, msg in _OPTIONAL_ERROR_MESSAGE_FACTORIES:
199
+ exc_type = resolver()
200
+ if exc_type is not None and isinstance(e, exc_type):
201
+ return msg.format(path=path, e=e)
202
+
133
203
  return f"Error parsing {path}: {e}"
134
204
 
135
205
 
136
206
  class StructuredFileError(Exception):
137
207
  """Error while reading or parsing a structured file."""
138
208
 
139
- def __init__(self, path: Path, original: Exception):
209
+ def __init__(self, path: Path, original: Exception) -> None:
140
210
  super().__init__(_format_structured_file_error(path, original))
141
211
  self.path = path
142
212
 
@@ -151,15 +221,10 @@ def read_structured_file(path: Path) -> Any:
151
221
  try:
152
222
  text = path.read_text(encoding="utf-8")
153
223
  return parser(text)
154
- except (
155
- OSError,
156
- UnicodeDecodeError,
157
- json.JSONDecodeError,
158
- YAMLError,
159
- TOMLDecodeError,
160
- ImportError,
161
- ) as e:
162
- raise StructuredFileError(path, e) from e
224
+ except Exception as e:
225
+ if _is_structured_error(e):
226
+ raise StructuredFileError(path, e) from e
227
+ raise
163
228
 
164
229
 
165
230
  logger = get_logger(__name__)
tnfr/io.pyi ADDED
@@ -0,0 +1,11 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ StructuredFileError: Any
8
+ TOMLDecodeError: Any
9
+ YAMLError: Any
10
+ read_structured_file: Any
11
+ safe_write: Any
tnfr/locking.pyi ADDED
@@ -0,0 +1,7 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ get_lock: Any
@@ -0,0 +1,20 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ Tg_by_node: Any
8
+ Tg_global: Any
9
+ build_metrics_summary: Any
10
+ coherence_matrix: Any
11
+ dissonance_events: Any
12
+ export_metrics: Any
13
+ glyph_top: Any
14
+ glyphogram_series: Any
15
+ latency_series: Any
16
+ local_phase_sync: Any
17
+ local_phase_sync_weighted: Any
18
+ register_coherence_callbacks: Any
19
+ register_diagnosis_callbacks: Any
20
+ register_metrics_callbacks: Any