tnfr 4.5.2__py3-none-any.whl → 7.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.

Potentially problematic release.


This version of tnfr might be problematic. Click here for more details.

Files changed (195) hide show
  1. tnfr/__init__.py +275 -51
  2. tnfr/__init__.pyi +33 -0
  3. tnfr/_compat.py +10 -0
  4. tnfr/_generated_version.py +34 -0
  5. tnfr/_version.py +49 -0
  6. tnfr/_version.pyi +7 -0
  7. tnfr/alias.py +117 -31
  8. tnfr/alias.pyi +108 -0
  9. tnfr/cache.py +6 -572
  10. tnfr/cache.pyi +16 -0
  11. tnfr/callback_utils.py +16 -38
  12. tnfr/callback_utils.pyi +79 -0
  13. tnfr/cli/__init__.py +34 -14
  14. tnfr/cli/__init__.pyi +26 -0
  15. tnfr/cli/arguments.py +211 -28
  16. tnfr/cli/arguments.pyi +27 -0
  17. tnfr/cli/execution.py +470 -50
  18. tnfr/cli/execution.pyi +70 -0
  19. tnfr/cli/utils.py +18 -3
  20. tnfr/cli/utils.pyi +8 -0
  21. tnfr/config/__init__.py +13 -0
  22. tnfr/config/__init__.pyi +10 -0
  23. tnfr/{constants_glyphs.py → config/constants.py} +26 -20
  24. tnfr/config/constants.pyi +12 -0
  25. tnfr/config/feature_flags.py +83 -0
  26. tnfr/{config.py → config/init.py} +11 -7
  27. tnfr/config/init.pyi +8 -0
  28. tnfr/config/operator_names.py +93 -0
  29. tnfr/config/operator_names.pyi +28 -0
  30. tnfr/config/presets.py +84 -0
  31. tnfr/config/presets.pyi +7 -0
  32. tnfr/constants/__init__.py +80 -29
  33. tnfr/constants/__init__.pyi +92 -0
  34. tnfr/constants/aliases.py +31 -0
  35. tnfr/constants/core.py +4 -4
  36. tnfr/constants/core.pyi +17 -0
  37. tnfr/constants/init.py +1 -1
  38. tnfr/constants/init.pyi +12 -0
  39. tnfr/constants/metric.py +7 -15
  40. tnfr/constants/metric.pyi +19 -0
  41. tnfr/dynamics/__init__.py +165 -633
  42. tnfr/dynamics/__init__.pyi +82 -0
  43. tnfr/dynamics/adaptation.py +267 -0
  44. tnfr/dynamics/aliases.py +23 -0
  45. tnfr/dynamics/coordination.py +385 -0
  46. tnfr/dynamics/dnfr.py +2283 -400
  47. tnfr/dynamics/dnfr.pyi +24 -0
  48. tnfr/dynamics/integrators.py +406 -98
  49. tnfr/dynamics/integrators.pyi +34 -0
  50. tnfr/dynamics/runtime.py +881 -0
  51. tnfr/dynamics/sampling.py +10 -5
  52. tnfr/dynamics/sampling.pyi +7 -0
  53. tnfr/dynamics/selectors.py +719 -0
  54. tnfr/execution.py +70 -48
  55. tnfr/execution.pyi +45 -0
  56. tnfr/flatten.py +13 -9
  57. tnfr/flatten.pyi +21 -0
  58. tnfr/gamma.py +66 -53
  59. tnfr/gamma.pyi +34 -0
  60. tnfr/glyph_history.py +110 -52
  61. tnfr/glyph_history.pyi +35 -0
  62. tnfr/glyph_runtime.py +16 -0
  63. tnfr/glyph_runtime.pyi +9 -0
  64. tnfr/immutable.py +69 -28
  65. tnfr/immutable.pyi +34 -0
  66. tnfr/initialization.py +16 -16
  67. tnfr/initialization.pyi +65 -0
  68. tnfr/io.py +6 -240
  69. tnfr/io.pyi +16 -0
  70. tnfr/locking.pyi +7 -0
  71. tnfr/mathematics/__init__.py +81 -0
  72. tnfr/mathematics/backend.py +426 -0
  73. tnfr/mathematics/dynamics.py +398 -0
  74. tnfr/mathematics/epi.py +254 -0
  75. tnfr/mathematics/generators.py +222 -0
  76. tnfr/mathematics/metrics.py +119 -0
  77. tnfr/mathematics/operators.py +233 -0
  78. tnfr/mathematics/operators_factory.py +71 -0
  79. tnfr/mathematics/projection.py +78 -0
  80. tnfr/mathematics/runtime.py +173 -0
  81. tnfr/mathematics/spaces.py +247 -0
  82. tnfr/mathematics/transforms.py +292 -0
  83. tnfr/metrics/__init__.py +10 -10
  84. tnfr/metrics/__init__.pyi +20 -0
  85. tnfr/metrics/coherence.py +993 -324
  86. tnfr/metrics/common.py +23 -16
  87. tnfr/metrics/common.pyi +46 -0
  88. tnfr/metrics/core.py +251 -35
  89. tnfr/metrics/core.pyi +13 -0
  90. tnfr/metrics/diagnosis.py +708 -111
  91. tnfr/metrics/diagnosis.pyi +85 -0
  92. tnfr/metrics/export.py +27 -15
  93. tnfr/metrics/glyph_timing.py +232 -42
  94. tnfr/metrics/reporting.py +33 -22
  95. tnfr/metrics/reporting.pyi +12 -0
  96. tnfr/metrics/sense_index.py +987 -43
  97. tnfr/metrics/sense_index.pyi +9 -0
  98. tnfr/metrics/trig.py +214 -23
  99. tnfr/metrics/trig.pyi +13 -0
  100. tnfr/metrics/trig_cache.py +115 -22
  101. tnfr/metrics/trig_cache.pyi +10 -0
  102. tnfr/node.py +542 -136
  103. tnfr/node.pyi +178 -0
  104. tnfr/observers.py +152 -35
  105. tnfr/observers.pyi +31 -0
  106. tnfr/ontosim.py +23 -19
  107. tnfr/ontosim.pyi +28 -0
  108. tnfr/operators/__init__.py +601 -82
  109. tnfr/operators/__init__.pyi +45 -0
  110. tnfr/operators/definitions.py +513 -0
  111. tnfr/operators/definitions.pyi +78 -0
  112. tnfr/operators/grammar.py +760 -0
  113. tnfr/operators/jitter.py +107 -38
  114. tnfr/operators/jitter.pyi +11 -0
  115. tnfr/operators/registry.py +75 -0
  116. tnfr/operators/registry.pyi +13 -0
  117. tnfr/operators/remesh.py +149 -88
  118. tnfr/py.typed +0 -0
  119. tnfr/rng.py +46 -143
  120. tnfr/rng.pyi +14 -0
  121. tnfr/schemas/__init__.py +8 -0
  122. tnfr/schemas/grammar.json +94 -0
  123. tnfr/selector.py +25 -19
  124. tnfr/selector.pyi +19 -0
  125. tnfr/sense.py +72 -62
  126. tnfr/sense.pyi +23 -0
  127. tnfr/structural.py +522 -262
  128. tnfr/structural.pyi +69 -0
  129. tnfr/telemetry/__init__.py +35 -0
  130. tnfr/telemetry/cache_metrics.py +226 -0
  131. tnfr/telemetry/nu_f.py +423 -0
  132. tnfr/telemetry/nu_f.pyi +123 -0
  133. tnfr/telemetry/verbosity.py +37 -0
  134. tnfr/tokens.py +1 -3
  135. tnfr/tokens.pyi +36 -0
  136. tnfr/trace.py +270 -113
  137. tnfr/trace.pyi +40 -0
  138. tnfr/types.py +574 -6
  139. tnfr/types.pyi +331 -0
  140. tnfr/units.py +69 -0
  141. tnfr/units.pyi +16 -0
  142. tnfr/utils/__init__.py +217 -0
  143. tnfr/utils/__init__.pyi +202 -0
  144. tnfr/utils/cache.py +2395 -0
  145. tnfr/utils/cache.pyi +468 -0
  146. tnfr/utils/chunks.py +104 -0
  147. tnfr/utils/chunks.pyi +21 -0
  148. tnfr/{collections_utils.py → utils/data.py} +147 -90
  149. tnfr/utils/data.pyi +64 -0
  150. tnfr/utils/graph.py +85 -0
  151. tnfr/utils/graph.pyi +10 -0
  152. tnfr/utils/init.py +770 -0
  153. tnfr/utils/init.pyi +78 -0
  154. tnfr/utils/io.py +456 -0
  155. tnfr/{helpers → utils}/numeric.py +51 -24
  156. tnfr/utils/numeric.pyi +21 -0
  157. tnfr/validation/__init__.py +113 -0
  158. tnfr/validation/__init__.pyi +77 -0
  159. tnfr/validation/compatibility.py +95 -0
  160. tnfr/validation/compatibility.pyi +6 -0
  161. tnfr/validation/grammar.py +71 -0
  162. tnfr/validation/grammar.pyi +40 -0
  163. tnfr/validation/graph.py +138 -0
  164. tnfr/validation/graph.pyi +17 -0
  165. tnfr/validation/rules.py +281 -0
  166. tnfr/validation/rules.pyi +55 -0
  167. tnfr/validation/runtime.py +263 -0
  168. tnfr/validation/runtime.pyi +31 -0
  169. tnfr/validation/soft_filters.py +170 -0
  170. tnfr/validation/soft_filters.pyi +37 -0
  171. tnfr/validation/spectral.py +159 -0
  172. tnfr/validation/spectral.pyi +46 -0
  173. tnfr/validation/syntax.py +40 -0
  174. tnfr/validation/syntax.pyi +10 -0
  175. tnfr/validation/window.py +39 -0
  176. tnfr/validation/window.pyi +1 -0
  177. tnfr/viz/__init__.py +9 -0
  178. tnfr/viz/matplotlib.py +246 -0
  179. tnfr-7.0.0.dist-info/METADATA +179 -0
  180. tnfr-7.0.0.dist-info/RECORD +185 -0
  181. {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/licenses/LICENSE.md +1 -1
  182. tnfr/grammar.py +0 -344
  183. tnfr/graph_utils.py +0 -84
  184. tnfr/helpers/__init__.py +0 -71
  185. tnfr/import_utils.py +0 -228
  186. tnfr/json_utils.py +0 -162
  187. tnfr/logging_utils.py +0 -116
  188. tnfr/presets.py +0 -60
  189. tnfr/validators.py +0 -84
  190. tnfr/value_utils.py +0 -59
  191. tnfr-4.5.2.dist-info/METADATA +0 -379
  192. tnfr-4.5.2.dist-info/RECORD +0 -67
  193. {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/WHEEL +0 -0
  194. {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/entry_points.txt +0 -0
  195. {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/top_level.txt +0 -0
tnfr/__init__.py CHANGED
@@ -4,88 +4,312 @@ This package only re-exports a handful of high level helpers. Most
4
4
  functionality lives in submodules that should be imported directly, for
5
5
  example :mod:`tnfr.metrics`, :mod:`tnfr.observers` or the DSL utilities
6
6
  in :mod:`tnfr.tokens`, :mod:`tnfr.flatten` and :mod:`tnfr.execution`.
7
- Recommended entry points are:
8
7
 
9
- - ``step`` and ``run`` in :mod:`tnfr.dynamics`
10
- - ``preparar_red`` in :mod:`tnfr.ontosim`
11
- - ``create_nfr`` and ``run_sequence`` in :mod:`tnfr.structural`
12
- - ``cached_import`` and ``prune_failed_imports`` for optional dependencies
8
+ Exported helpers and their dependencies
9
+ ---------------------------------------
10
+ The :data:`EXPORT_DEPENDENCIES` mapping enumerates which internal
11
+ submodules and third-party packages are required to load each helper.
12
+ The imports are grouped as follows:
13
+
14
+ ``step`` / ``run``
15
+ Provided by :mod:`tnfr.dynamics`. These helpers rely on the
16
+ machinery defined within the :mod:`tnfr.dynamics` package (operator
17
+ orchestration, validation hooks and metrics integration) and require
18
+ the ``networkx`` package for graph handling.
19
+
20
+ ``prepare_network``
21
+ Defined in :mod:`tnfr.ontosim`. Besides :mod:`tnfr.ontosim`
22
+ itself, the helper imports :mod:`tnfr.callback_utils`,
23
+ :mod:`tnfr.constants`, :mod:`tnfr.dynamics`, :mod:`tnfr.glyph_history`,
24
+ :mod:`tnfr.initialization` and :mod:`tnfr.utils` to assemble the
25
+ graph preparation pipeline. It also requires ``networkx`` at import
26
+ time.
27
+
28
+ ``create_nfr`` / ``run_sequence``
29
+ Re-exported from :mod:`tnfr.structural`. They depend on
30
+ :mod:`tnfr.structural`, :mod:`tnfr.constants`, :mod:`tnfr.dynamics`,
31
+ :mod:`tnfr.operators.definitions`, :mod:`tnfr.operators.registry` and
32
+ :mod:`tnfr.validation`, and additionally require the ``networkx``
33
+ package.
34
+
35
+ ``cached_import`` and ``prune_failed_imports`` remain available from
36
+ ``tnfr.utils`` for optional dependency management.
13
37
  """
14
38
 
15
39
  from __future__ import annotations
16
40
 
17
- from .import_utils import cached_import, prune_failed_imports
18
- from .ontosim import preparar_red
41
+ import warnings
42
+ from importlib import import_module, metadata
43
+ from importlib.metadata import PackageNotFoundError
44
+ from typing import Any, Callable, NoReturn
45
+
46
+ EXPORT_DEPENDENCIES: dict[str, dict[str, tuple[str, ...]]] = {
47
+ "step": {
48
+ "submodules": ("tnfr.dynamics",),
49
+ "third_party": ("networkx",),
50
+ },
51
+ "run": {
52
+ "submodules": ("tnfr.dynamics",),
53
+ "third_party": ("networkx",),
54
+ },
55
+ "prepare_network": {
56
+ "submodules": (
57
+ "tnfr.ontosim",
58
+ "tnfr.callback_utils",
59
+ "tnfr.constants",
60
+ "tnfr.dynamics",
61
+ "tnfr.glyph_history",
62
+ "tnfr.initialization",
63
+ "tnfr.utils",
64
+ ),
65
+ "third_party": ("networkx",),
66
+ },
67
+ "create_nfr": {
68
+ "submodules": (
69
+ "tnfr.structural",
70
+ "tnfr.constants",
71
+ "tnfr.dynamics",
72
+ "tnfr.operators.definitions",
73
+ "tnfr.operators.registry",
74
+ "tnfr.validation",
75
+ ),
76
+ "third_party": ("networkx",),
77
+ },
78
+ "create_math_nfr": {
79
+ "submodules": (
80
+ "tnfr.structural",
81
+ "tnfr.constants",
82
+ "tnfr.dynamics",
83
+ "tnfr.operators.definitions",
84
+ "tnfr.operators.registry",
85
+ "tnfr.validation",
86
+ "tnfr.mathematics",
87
+ ),
88
+ "third_party": (
89
+ "networkx",
90
+ "numpy",
91
+ ),
92
+ },
93
+ "run_sequence": {
94
+ "submodules": (
95
+ "tnfr.structural",
96
+ "tnfr.constants",
97
+ "tnfr.dynamics",
98
+ "tnfr.operators.definitions",
99
+ "tnfr.operators.registry",
100
+ "tnfr.validation",
101
+ ),
102
+ "third_party": ("networkx",),
103
+ },
104
+ "get_hz_bridge": {
105
+ "submodules": (
106
+ "tnfr.units",
107
+ "tnfr.constants",
108
+ ),
109
+ "third_party": ("networkx",),
110
+ },
111
+ "hz_str_to_hz": {
112
+ "submodules": (
113
+ "tnfr.units",
114
+ "tnfr.constants",
115
+ ),
116
+ "third_party": ("networkx",),
117
+ },
118
+ "hz_to_hz_str": {
119
+ "submodules": (
120
+ "tnfr.units",
121
+ "tnfr.constants",
122
+ ),
123
+ "third_party": ("networkx",),
124
+ },
125
+ }
126
+
127
+
128
+ try: # pragma: no cover - exercised in version resolution tests
129
+ __version__ = metadata.version("tnfr")
130
+ except PackageNotFoundError: # pragma: no cover - fallback tested explicitly
131
+ from ._version import __version__ as _fallback_version
132
+
133
+ __version__ = _fallback_version
134
+
19
135
 
136
+ def _is_internal_import_error(exc: ImportError) -> bool:
137
+ missing_name = getattr(exc, "name", None) or ""
138
+ if missing_name.startswith("tnfr"):
139
+ return True
20
140
 
21
- def _missing_dependency(name: str, exc: ImportError):
22
- def _stub(*args, **kwargs):
141
+ module_name = getattr(exc, "module", None) or ""
142
+ if module_name.startswith("tnfr"):
143
+ return True
144
+
145
+ missing_path = getattr(exc, "path", None) or ""
146
+ if missing_path:
147
+ normalized = missing_path.replace("\\", "/")
148
+ if "/tnfr/" in normalized or normalized.endswith("/tnfr"):
149
+ return True
150
+
151
+ message = str(exc)
152
+ lowered = message.lower()
153
+ mentions_base_package = "module 'tnfr'" in lowered or 'module "tnfr"' in lowered
154
+ if ("tnfr." in message or mentions_base_package) and (
155
+ "circular import" in lowered or "partially initialized module" in lowered
156
+ ):
157
+ return True
158
+
159
+ return False
160
+
161
+
162
+ def _missing_dependency(
163
+ name: str, exc: ImportError, *, module: str | None = None
164
+ ) -> Callable[..., NoReturn]:
165
+ missing_name = getattr(exc, "name", None)
166
+
167
+ def _stub(*args: Any, **kwargs: Any) -> NoReturn:
23
168
  raise ImportError(
24
169
  f"{name} is unavailable because required dependencies could not be imported. "
25
170
  f"Original error ({exc.__class__.__name__}): {exc}. "
26
171
  "Install the missing packages (e.g. 'networkx' or grammar modules)."
27
172
  ) from exc
28
173
 
174
+ _stub.__tnfr_missing_dependency__ = {
175
+ "export": name,
176
+ "module": module,
177
+ "missing": missing_name,
178
+ }
29
179
  return _stub
30
180
 
31
181
 
32
- try: # pragma: no cover - exercised in import tests
33
- from .dynamics import step, run
34
- except ImportError as exc: # pragma: no cover - no missing deps in CI
35
- step = _missing_dependency("step", exc)
36
- run = _missing_dependency("run", exc)
182
+ _MISSING_EXPORTS: dict[str, dict[str, Any]] = {}
183
+
184
+
185
+ class ExportDependencyError(RuntimeError):
186
+ """Raised when the export dependency manifest is inconsistent."""
187
+
37
188
 
189
+ def _validate_export_dependencies() -> None:
190
+ """Ensure exported helpers and their manifest entries stay in sync."""
38
191
 
39
- _HAS_RUN_SEQUENCE = False
40
- try: # pragma: no cover - exercised in import tests
41
- from .structural import create_nfr, run_sequence
42
- except ImportError as exc: # pragma: no cover - no missing deps in CI
43
- create_nfr = _missing_dependency("create_nfr", exc)
44
- run_sequence = _missing_dependency("run_sequence", exc)
45
- else:
46
- _HAS_RUN_SEQUENCE = True
192
+ if "__all__" not in globals():
193
+ # Defensive guard for unusual import orders (should never trigger).
194
+ return
47
195
 
196
+ issues: list[str] = []
197
+ manifest = EXPORT_DEPENDENCIES
198
+ export_names = [name for name in __all__ if name != "__version__"]
199
+ manifest_names = set(manifest)
48
200
 
49
- _metadata = cached_import("importlib.metadata")
50
- if _metadata is None: # pragma: no cover
51
- _metadata = cached_import("importlib_metadata")
201
+ for export_name in export_names:
202
+ if export_name not in manifest:
203
+ issues.append(
204
+ f"helper '{export_name}' is exported via __all__ but missing from EXPORT_DEPENDENCIES"
205
+ )
206
+ continue
52
207
 
53
- if _metadata is not None: # pragma: no cover
54
- version = _metadata.version # type: ignore[attr-defined]
55
- PackageNotFoundError = _metadata.PackageNotFoundError # type: ignore[attr-defined]
56
- else: # pragma: no cover
208
+ entry = manifest[export_name]
209
+ if not isinstance(entry, dict):
210
+ issues.append(
211
+ f"helper '{export_name}' has a malformed manifest entry (expected mapping, got {type(entry)!r})"
212
+ )
213
+ continue
57
214
 
58
- class PackageNotFoundError(Exception):
59
- pass
215
+ for key in ("submodules", "third_party"):
216
+ value = entry.get(key)
217
+ if not value:
218
+ issues.append(
219
+ f"helper '{export_name}' is missing '{key}' dependencies in EXPORT_DEPENDENCIES"
220
+ )
60
221
 
61
- def version(_: str) -> str:
62
- raise PackageNotFoundError
222
+ missing_exports = manifest_names.difference(export_names).difference(
223
+ _MISSING_EXPORTS
224
+ )
225
+ for manifest_only in sorted(missing_exports):
226
+ entry = manifest[manifest_only]
227
+ if not isinstance(entry, dict):
228
+ issues.append(
229
+ f"helper '{manifest_only}' has a malformed manifest entry (expected mapping, got {type(entry)!r})"
230
+ )
231
+ continue
63
232
 
233
+ for key in ("submodules", "third_party"):
234
+ value = entry.get(key)
235
+ if not value:
236
+ issues.append(
237
+ f"helper '{manifest_only}' is missing '{key}' dependencies in EXPORT_DEPENDENCIES"
238
+ )
64
239
 
65
- try:
66
- __version__ = version("tnfr")
67
- except PackageNotFoundError: # pragma: no cover
68
- tomllib = cached_import("tomllib")
69
- if tomllib is not None:
70
- from pathlib import Path
240
+ issues.append(
241
+ f"helper '{manifest_only}' is listed in EXPORT_DEPENDENCIES but not exported via __all__"
242
+ )
243
+
244
+ if issues:
245
+ raise ExportDependencyError(
246
+ "Invalid TNFR export dependency manifest:\n- " + "\n- ".join(issues)
247
+ )
248
+
249
+
250
+ def _assign_exports(module: str, names: tuple[str, ...]) -> bool:
251
+ try: # pragma: no cover - exercised in import tests
252
+ mod = import_module(f".{module}", __name__)
253
+ except ImportError as exc: # pragma: no cover - no missing deps in CI
254
+ if _is_internal_import_error(exc):
255
+ raise
256
+ for export_name in names:
257
+ stub = _missing_dependency(export_name, exc, module=module)
258
+ globals()[export_name] = stub
259
+ _MISSING_EXPORTS[export_name] = getattr(
260
+ stub, "__tnfr_missing_dependency__", {}
261
+ )
262
+ return False
263
+ else:
264
+ for export_name in names:
265
+ globals()[export_name] = getattr(mod, export_name)
266
+ return True
267
+
268
+
269
+ _assign_exports("dynamics", ("step", "run"))
270
+
271
+
272
+ _HAS_PREPARE_NETWORK = _assign_exports("ontosim", ("prepare_network",))
273
+
274
+
275
+ _HAS_STRUCTURAL_EXPORTS = _assign_exports(
276
+ "structural", ("create_nfr", "run_sequence", "create_math_nfr")
277
+ )
278
+
279
+
280
+ _assign_exports("units", ("get_hz_bridge", "hz_str_to_hz", "hz_to_hz_str"))
281
+
282
+
283
+ def _emit_missing_dependency_warning() -> None:
284
+ if not _MISSING_EXPORTS:
285
+ return
286
+ details = ", ".join(
287
+ f"{name} (missing: {info.get('missing') or 'unknown'})"
288
+ for name, info in sorted(_MISSING_EXPORTS.items())
289
+ )
290
+ warnings.warn(
291
+ "TNFR helpers disabled because dependencies are missing: " + details,
292
+ ImportWarning,
293
+ stacklevel=2,
294
+ )
295
+
296
+
297
+ _emit_missing_dependency_warning()
71
298
 
72
- try:
73
- with (Path(__file__).resolve().parents[2] / "pyproject.toml").open(
74
- "rb",
75
- ) as f:
76
- __version__ = tomllib.load(f)["project"]["version"]
77
- except (OSError, KeyError, ValueError): # pragma: no cover
78
- __version__ = "0+unknown"
79
- else: # pragma: no cover
80
- __version__ = "0+unknown"
81
299
 
82
300
  __all__ = [
83
301
  "__version__",
84
302
  "step",
85
303
  "run",
86
- "preparar_red",
304
+ "prepare_network",
87
305
  "create_nfr",
306
+ "get_hz_bridge",
307
+ "hz_str_to_hz",
308
+ "hz_to_hz_str",
88
309
  ]
89
310
 
90
- if _HAS_RUN_SEQUENCE:
91
- __all__.append("run_sequence")
311
+ if _HAS_STRUCTURAL_EXPORTS:
312
+ __all__.extend(["run_sequence", "create_math_nfr"])
313
+
314
+
315
+ _validate_export_dependencies()
tnfr/__init__.pyi ADDED
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+ from typing import Any, NoReturn
5
+
6
+ from .dynamics import run, step
7
+ from .ontosim import prepare_network
8
+ from .structural import create_nfr, run_sequence
9
+
10
+ EXPORT_DEPENDENCIES: dict[str, dict[str, tuple[str, ...]]]
11
+ """Manifest describing required submodules and third-party packages."""
12
+
13
+ _MISSING_EXPORTS: dict[str, dict[str, Any]]
14
+
15
+ __version__: str
16
+ __all__: list[str]
17
+
18
+ class ExportDependencyError(RuntimeError):
19
+ """Raised when the export dependency manifest is inconsistent."""
20
+
21
+ def _is_internal_import_error(exc: ImportError) -> bool: ...
22
+ def _missing_dependency(
23
+ name: str,
24
+ exc: ImportError,
25
+ *,
26
+ module: str | None = ...,
27
+ ) -> Callable[..., NoReturn]: ...
28
+ def _validate_export_dependencies() -> None: ...
29
+ def _assign_exports(module: str, names: tuple[str, ...]) -> bool: ...
30
+ def _emit_missing_dependency_warning() -> None: ...
31
+
32
+ _HAS_PREPARE_NETWORK: bool
33
+ _HAS_RUN_SEQUENCE: bool
tnfr/_compat.py ADDED
@@ -0,0 +1,10 @@
1
+ """Compatibility helpers for bridging typing features across Python versions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ try: # pragma: no cover - exercised implicitly by importers
6
+ from typing import TypeAlias # type: ignore[attr-defined]
7
+ except (ImportError, AttributeError): # pragma: no cover - Python < 3.10
8
+ from typing_extensions import TypeAlias # type: ignore[assignment]
9
+
10
+ __all__ = ["TypeAlias"]
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '7.0.0'
32
+ __version_tuple__ = version_tuple = (7, 0, 0)
33
+
34
+ __commit_id__ = commit_id = None
tnfr/_version.py ADDED
@@ -0,0 +1,49 @@
1
+ """Runtime version discovery for :mod:`tnfr`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from importlib import metadata
7
+ from typing import Final
8
+
9
+ __all__ = ["__version__"]
10
+
11
+
12
+ def _read_version() -> str:
13
+ """Resolve the published package version while preserving TNFR invariants."""
14
+
15
+ env_version = os.environ.get("TNFR_VERSION")
16
+ if env_version:
17
+ return env_version
18
+
19
+ try:
20
+ return metadata.version("tnfr")
21
+ except metadata.PackageNotFoundError:
22
+ pass
23
+
24
+ try: # pragma: no cover - only present in built distributions
25
+ from . import _generated_version # type: ignore
26
+ except ImportError: # pragma: no cover - optional artifact
27
+ pass
28
+ else:
29
+ generated = getattr(_generated_version, "version", None)
30
+ if isinstance(generated, str) and generated:
31
+ return generated
32
+ legacy = getattr(_generated_version, "__version__", None)
33
+ if isinstance(legacy, str) and legacy:
34
+ return legacy
35
+
36
+ try:
37
+ from setuptools_scm import get_version
38
+ except Exception: # pragma: no cover - optional dependency
39
+ pass
40
+ else:
41
+ try:
42
+ return get_version(relative_to=__file__)
43
+ except LookupError:
44
+ pass
45
+
46
+ return "0.0.0"
47
+
48
+
49
+ __version__: Final[str] = _read_version()
tnfr/_version.pyi ADDED
@@ -0,0 +1,7 @@
1
+ from typing import Any
2
+
3
+ __all__: Any
4
+
5
+ def __getattr__(name: str) -> Any: ...
6
+
7
+ __version__: Any