tnfr 3.0.3__py3-none-any.whl → 8.5.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 (360) hide show
  1. tnfr/__init__.py +375 -56
  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 +723 -0
  8. tnfr/alias.pyi +108 -0
  9. tnfr/backends/__init__.py +354 -0
  10. tnfr/backends/jax_backend.py +173 -0
  11. tnfr/backends/numpy_backend.py +238 -0
  12. tnfr/backends/optimized_numpy.py +420 -0
  13. tnfr/backends/torch_backend.py +408 -0
  14. tnfr/cache.py +171 -0
  15. tnfr/cache.pyi +13 -0
  16. tnfr/cli/__init__.py +110 -0
  17. tnfr/cli/__init__.pyi +26 -0
  18. tnfr/cli/arguments.py +489 -0
  19. tnfr/cli/arguments.pyi +29 -0
  20. tnfr/cli/execution.py +914 -0
  21. tnfr/cli/execution.pyi +70 -0
  22. tnfr/cli/interactive_validator.py +614 -0
  23. tnfr/cli/utils.py +51 -0
  24. tnfr/cli/utils.pyi +7 -0
  25. tnfr/cli/validate.py +236 -0
  26. tnfr/compat/__init__.py +85 -0
  27. tnfr/compat/dataclass.py +136 -0
  28. tnfr/compat/jsonschema_stub.py +61 -0
  29. tnfr/compat/matplotlib_stub.py +73 -0
  30. tnfr/compat/numpy_stub.py +155 -0
  31. tnfr/config/__init__.py +224 -0
  32. tnfr/config/__init__.pyi +10 -0
  33. tnfr/config/constants.py +104 -0
  34. tnfr/config/constants.pyi +12 -0
  35. tnfr/config/defaults.py +54 -0
  36. tnfr/config/defaults_core.py +212 -0
  37. tnfr/config/defaults_init.py +33 -0
  38. tnfr/config/defaults_metric.py +104 -0
  39. tnfr/config/feature_flags.py +81 -0
  40. tnfr/config/feature_flags.pyi +16 -0
  41. tnfr/config/glyph_constants.py +31 -0
  42. tnfr/config/init.py +77 -0
  43. tnfr/config/init.pyi +8 -0
  44. tnfr/config/operator_names.py +254 -0
  45. tnfr/config/operator_names.pyi +36 -0
  46. tnfr/config/physics_derivation.py +354 -0
  47. tnfr/config/presets.py +83 -0
  48. tnfr/config/presets.pyi +7 -0
  49. tnfr/config/security.py +927 -0
  50. tnfr/config/thresholds.py +114 -0
  51. tnfr/config/tnfr_config.py +498 -0
  52. tnfr/constants/__init__.py +92 -0
  53. tnfr/constants/__init__.pyi +92 -0
  54. tnfr/constants/aliases.py +33 -0
  55. tnfr/constants/aliases.pyi +27 -0
  56. tnfr/constants/init.py +33 -0
  57. tnfr/constants/init.pyi +12 -0
  58. tnfr/constants/metric.py +104 -0
  59. tnfr/constants/metric.pyi +19 -0
  60. tnfr/core/__init__.py +33 -0
  61. tnfr/core/container.py +226 -0
  62. tnfr/core/default_implementations.py +329 -0
  63. tnfr/core/interfaces.py +279 -0
  64. tnfr/dynamics/__init__.py +238 -0
  65. tnfr/dynamics/__init__.pyi +83 -0
  66. tnfr/dynamics/adaptation.py +267 -0
  67. tnfr/dynamics/adaptation.pyi +7 -0
  68. tnfr/dynamics/adaptive_sequences.py +189 -0
  69. tnfr/dynamics/adaptive_sequences.pyi +14 -0
  70. tnfr/dynamics/aliases.py +23 -0
  71. tnfr/dynamics/aliases.pyi +19 -0
  72. tnfr/dynamics/bifurcation.py +232 -0
  73. tnfr/dynamics/canonical.py +229 -0
  74. tnfr/dynamics/canonical.pyi +48 -0
  75. tnfr/dynamics/coordination.py +385 -0
  76. tnfr/dynamics/coordination.pyi +25 -0
  77. tnfr/dynamics/dnfr.py +3034 -0
  78. tnfr/dynamics/dnfr.pyi +26 -0
  79. tnfr/dynamics/dynamic_limits.py +225 -0
  80. tnfr/dynamics/feedback.py +252 -0
  81. tnfr/dynamics/feedback.pyi +24 -0
  82. tnfr/dynamics/fused_dnfr.py +454 -0
  83. tnfr/dynamics/homeostasis.py +157 -0
  84. tnfr/dynamics/homeostasis.pyi +14 -0
  85. tnfr/dynamics/integrators.py +661 -0
  86. tnfr/dynamics/integrators.pyi +36 -0
  87. tnfr/dynamics/learning.py +310 -0
  88. tnfr/dynamics/learning.pyi +33 -0
  89. tnfr/dynamics/metabolism.py +254 -0
  90. tnfr/dynamics/nbody.py +796 -0
  91. tnfr/dynamics/nbody_tnfr.py +783 -0
  92. tnfr/dynamics/propagation.py +326 -0
  93. tnfr/dynamics/runtime.py +908 -0
  94. tnfr/dynamics/runtime.pyi +77 -0
  95. tnfr/dynamics/sampling.py +36 -0
  96. tnfr/dynamics/sampling.pyi +7 -0
  97. tnfr/dynamics/selectors.py +711 -0
  98. tnfr/dynamics/selectors.pyi +85 -0
  99. tnfr/dynamics/structural_clip.py +207 -0
  100. tnfr/errors/__init__.py +37 -0
  101. tnfr/errors/contextual.py +492 -0
  102. tnfr/execution.py +223 -0
  103. tnfr/execution.pyi +45 -0
  104. tnfr/extensions/__init__.py +205 -0
  105. tnfr/extensions/__init__.pyi +18 -0
  106. tnfr/extensions/base.py +173 -0
  107. tnfr/extensions/base.pyi +35 -0
  108. tnfr/extensions/business/__init__.py +71 -0
  109. tnfr/extensions/business/__init__.pyi +11 -0
  110. tnfr/extensions/business/cookbook.py +88 -0
  111. tnfr/extensions/business/cookbook.pyi +8 -0
  112. tnfr/extensions/business/health_analyzers.py +202 -0
  113. tnfr/extensions/business/health_analyzers.pyi +9 -0
  114. tnfr/extensions/business/patterns.py +183 -0
  115. tnfr/extensions/business/patterns.pyi +8 -0
  116. tnfr/extensions/medical/__init__.py +73 -0
  117. tnfr/extensions/medical/__init__.pyi +11 -0
  118. tnfr/extensions/medical/cookbook.py +88 -0
  119. tnfr/extensions/medical/cookbook.pyi +8 -0
  120. tnfr/extensions/medical/health_analyzers.py +181 -0
  121. tnfr/extensions/medical/health_analyzers.pyi +9 -0
  122. tnfr/extensions/medical/patterns.py +163 -0
  123. tnfr/extensions/medical/patterns.pyi +8 -0
  124. tnfr/flatten.py +262 -0
  125. tnfr/flatten.pyi +21 -0
  126. tnfr/gamma.py +354 -0
  127. tnfr/gamma.pyi +36 -0
  128. tnfr/glyph_history.py +377 -0
  129. tnfr/glyph_history.pyi +35 -0
  130. tnfr/glyph_runtime.py +19 -0
  131. tnfr/glyph_runtime.pyi +8 -0
  132. tnfr/immutable.py +218 -0
  133. tnfr/immutable.pyi +36 -0
  134. tnfr/initialization.py +203 -0
  135. tnfr/initialization.pyi +65 -0
  136. tnfr/io.py +10 -0
  137. tnfr/io.pyi +13 -0
  138. tnfr/locking.py +37 -0
  139. tnfr/locking.pyi +7 -0
  140. tnfr/mathematics/__init__.py +79 -0
  141. tnfr/mathematics/backend.py +453 -0
  142. tnfr/mathematics/backend.pyi +99 -0
  143. tnfr/mathematics/dynamics.py +408 -0
  144. tnfr/mathematics/dynamics.pyi +90 -0
  145. tnfr/mathematics/epi.py +391 -0
  146. tnfr/mathematics/epi.pyi +65 -0
  147. tnfr/mathematics/generators.py +242 -0
  148. tnfr/mathematics/generators.pyi +29 -0
  149. tnfr/mathematics/metrics.py +119 -0
  150. tnfr/mathematics/metrics.pyi +16 -0
  151. tnfr/mathematics/operators.py +239 -0
  152. tnfr/mathematics/operators.pyi +59 -0
  153. tnfr/mathematics/operators_factory.py +124 -0
  154. tnfr/mathematics/operators_factory.pyi +11 -0
  155. tnfr/mathematics/projection.py +87 -0
  156. tnfr/mathematics/projection.pyi +33 -0
  157. tnfr/mathematics/runtime.py +182 -0
  158. tnfr/mathematics/runtime.pyi +64 -0
  159. tnfr/mathematics/spaces.py +256 -0
  160. tnfr/mathematics/spaces.pyi +83 -0
  161. tnfr/mathematics/transforms.py +305 -0
  162. tnfr/mathematics/transforms.pyi +62 -0
  163. tnfr/metrics/__init__.py +79 -0
  164. tnfr/metrics/__init__.pyi +20 -0
  165. tnfr/metrics/buffer_cache.py +163 -0
  166. tnfr/metrics/buffer_cache.pyi +24 -0
  167. tnfr/metrics/cache_utils.py +214 -0
  168. tnfr/metrics/coherence.py +2009 -0
  169. tnfr/metrics/coherence.pyi +129 -0
  170. tnfr/metrics/common.py +158 -0
  171. tnfr/metrics/common.pyi +35 -0
  172. tnfr/metrics/core.py +316 -0
  173. tnfr/metrics/core.pyi +13 -0
  174. tnfr/metrics/diagnosis.py +833 -0
  175. tnfr/metrics/diagnosis.pyi +86 -0
  176. tnfr/metrics/emergence.py +245 -0
  177. tnfr/metrics/export.py +179 -0
  178. tnfr/metrics/export.pyi +7 -0
  179. tnfr/metrics/glyph_timing.py +379 -0
  180. tnfr/metrics/glyph_timing.pyi +81 -0
  181. tnfr/metrics/learning_metrics.py +280 -0
  182. tnfr/metrics/learning_metrics.pyi +21 -0
  183. tnfr/metrics/phase_coherence.py +351 -0
  184. tnfr/metrics/phase_compatibility.py +349 -0
  185. tnfr/metrics/reporting.py +183 -0
  186. tnfr/metrics/reporting.pyi +25 -0
  187. tnfr/metrics/sense_index.py +1203 -0
  188. tnfr/metrics/sense_index.pyi +9 -0
  189. tnfr/metrics/trig.py +373 -0
  190. tnfr/metrics/trig.pyi +13 -0
  191. tnfr/metrics/trig_cache.py +233 -0
  192. tnfr/metrics/trig_cache.pyi +10 -0
  193. tnfr/multiscale/__init__.py +32 -0
  194. tnfr/multiscale/hierarchical.py +517 -0
  195. tnfr/node.py +763 -0
  196. tnfr/node.pyi +139 -0
  197. tnfr/observers.py +255 -130
  198. tnfr/observers.pyi +31 -0
  199. tnfr/ontosim.py +144 -137
  200. tnfr/ontosim.pyi +28 -0
  201. tnfr/operators/__init__.py +1672 -0
  202. tnfr/operators/__init__.pyi +31 -0
  203. tnfr/operators/algebra.py +277 -0
  204. tnfr/operators/canonical_patterns.py +420 -0
  205. tnfr/operators/cascade.py +267 -0
  206. tnfr/operators/cycle_detection.py +358 -0
  207. tnfr/operators/definitions.py +4108 -0
  208. tnfr/operators/definitions.pyi +78 -0
  209. tnfr/operators/grammar.py +1164 -0
  210. tnfr/operators/grammar.pyi +140 -0
  211. tnfr/operators/hamiltonian.py +710 -0
  212. tnfr/operators/health_analyzer.py +809 -0
  213. tnfr/operators/jitter.py +272 -0
  214. tnfr/operators/jitter.pyi +11 -0
  215. tnfr/operators/lifecycle.py +314 -0
  216. tnfr/operators/metabolism.py +618 -0
  217. tnfr/operators/metrics.py +2138 -0
  218. tnfr/operators/network_analysis/__init__.py +27 -0
  219. tnfr/operators/network_analysis/source_detection.py +186 -0
  220. tnfr/operators/nodal_equation.py +395 -0
  221. tnfr/operators/pattern_detection.py +660 -0
  222. tnfr/operators/patterns.py +669 -0
  223. tnfr/operators/postconditions/__init__.py +38 -0
  224. tnfr/operators/postconditions/mutation.py +236 -0
  225. tnfr/operators/preconditions/__init__.py +1226 -0
  226. tnfr/operators/preconditions/coherence.py +305 -0
  227. tnfr/operators/preconditions/dissonance.py +236 -0
  228. tnfr/operators/preconditions/emission.py +128 -0
  229. tnfr/operators/preconditions/mutation.py +580 -0
  230. tnfr/operators/preconditions/reception.py +125 -0
  231. tnfr/operators/preconditions/resonance.py +364 -0
  232. tnfr/operators/registry.py +74 -0
  233. tnfr/operators/registry.pyi +9 -0
  234. tnfr/operators/remesh.py +1809 -0
  235. tnfr/operators/remesh.pyi +26 -0
  236. tnfr/operators/structural_units.py +268 -0
  237. tnfr/operators/unified_grammar.py +105 -0
  238. tnfr/parallel/__init__.py +54 -0
  239. tnfr/parallel/auto_scaler.py +234 -0
  240. tnfr/parallel/distributed.py +384 -0
  241. tnfr/parallel/engine.py +238 -0
  242. tnfr/parallel/gpu_engine.py +420 -0
  243. tnfr/parallel/monitoring.py +248 -0
  244. tnfr/parallel/partitioner.py +459 -0
  245. tnfr/py.typed +0 -0
  246. tnfr/recipes/__init__.py +22 -0
  247. tnfr/recipes/cookbook.py +743 -0
  248. tnfr/rng.py +178 -0
  249. tnfr/rng.pyi +26 -0
  250. tnfr/schemas/__init__.py +8 -0
  251. tnfr/schemas/grammar.json +94 -0
  252. tnfr/sdk/__init__.py +107 -0
  253. tnfr/sdk/__init__.pyi +19 -0
  254. tnfr/sdk/adaptive_system.py +173 -0
  255. tnfr/sdk/adaptive_system.pyi +21 -0
  256. tnfr/sdk/builders.py +370 -0
  257. tnfr/sdk/builders.pyi +51 -0
  258. tnfr/sdk/fluent.py +1121 -0
  259. tnfr/sdk/fluent.pyi +74 -0
  260. tnfr/sdk/templates.py +342 -0
  261. tnfr/sdk/templates.pyi +41 -0
  262. tnfr/sdk/utils.py +341 -0
  263. tnfr/secure_config.py +46 -0
  264. tnfr/security/__init__.py +70 -0
  265. tnfr/security/database.py +514 -0
  266. tnfr/security/subprocess.py +503 -0
  267. tnfr/security/validation.py +290 -0
  268. tnfr/selector.py +247 -0
  269. tnfr/selector.pyi +19 -0
  270. tnfr/sense.py +378 -0
  271. tnfr/sense.pyi +23 -0
  272. tnfr/services/__init__.py +17 -0
  273. tnfr/services/orchestrator.py +325 -0
  274. tnfr/sparse/__init__.py +39 -0
  275. tnfr/sparse/representations.py +492 -0
  276. tnfr/structural.py +705 -0
  277. tnfr/structural.pyi +83 -0
  278. tnfr/telemetry/__init__.py +35 -0
  279. tnfr/telemetry/cache_metrics.py +226 -0
  280. tnfr/telemetry/cache_metrics.pyi +64 -0
  281. tnfr/telemetry/nu_f.py +422 -0
  282. tnfr/telemetry/nu_f.pyi +108 -0
  283. tnfr/telemetry/verbosity.py +36 -0
  284. tnfr/telemetry/verbosity.pyi +15 -0
  285. tnfr/tokens.py +58 -0
  286. tnfr/tokens.pyi +36 -0
  287. tnfr/tools/__init__.py +20 -0
  288. tnfr/tools/domain_templates.py +478 -0
  289. tnfr/tools/sequence_generator.py +846 -0
  290. tnfr/topology/__init__.py +13 -0
  291. tnfr/topology/asymmetry.py +151 -0
  292. tnfr/trace.py +543 -0
  293. tnfr/trace.pyi +42 -0
  294. tnfr/tutorials/__init__.py +38 -0
  295. tnfr/tutorials/autonomous_evolution.py +285 -0
  296. tnfr/tutorials/interactive.py +1576 -0
  297. tnfr/tutorials/structural_metabolism.py +238 -0
  298. tnfr/types.py +775 -0
  299. tnfr/types.pyi +357 -0
  300. tnfr/units.py +68 -0
  301. tnfr/units.pyi +13 -0
  302. tnfr/utils/__init__.py +282 -0
  303. tnfr/utils/__init__.pyi +215 -0
  304. tnfr/utils/cache.py +4223 -0
  305. tnfr/utils/cache.pyi +470 -0
  306. tnfr/utils/callbacks.py +375 -0
  307. tnfr/utils/callbacks.pyi +49 -0
  308. tnfr/utils/chunks.py +108 -0
  309. tnfr/utils/chunks.pyi +22 -0
  310. tnfr/utils/data.py +428 -0
  311. tnfr/utils/data.pyi +74 -0
  312. tnfr/utils/graph.py +85 -0
  313. tnfr/utils/graph.pyi +10 -0
  314. tnfr/utils/init.py +821 -0
  315. tnfr/utils/init.pyi +80 -0
  316. tnfr/utils/io.py +559 -0
  317. tnfr/utils/io.pyi +66 -0
  318. tnfr/utils/numeric.py +114 -0
  319. tnfr/utils/numeric.pyi +21 -0
  320. tnfr/validation/__init__.py +257 -0
  321. tnfr/validation/__init__.pyi +85 -0
  322. tnfr/validation/compatibility.py +460 -0
  323. tnfr/validation/compatibility.pyi +6 -0
  324. tnfr/validation/config.py +73 -0
  325. tnfr/validation/graph.py +139 -0
  326. tnfr/validation/graph.pyi +18 -0
  327. tnfr/validation/input_validation.py +755 -0
  328. tnfr/validation/invariants.py +712 -0
  329. tnfr/validation/rules.py +253 -0
  330. tnfr/validation/rules.pyi +44 -0
  331. tnfr/validation/runtime.py +279 -0
  332. tnfr/validation/runtime.pyi +28 -0
  333. tnfr/validation/sequence_validator.py +162 -0
  334. tnfr/validation/soft_filters.py +170 -0
  335. tnfr/validation/soft_filters.pyi +32 -0
  336. tnfr/validation/spectral.py +164 -0
  337. tnfr/validation/spectral.pyi +42 -0
  338. tnfr/validation/validator.py +1266 -0
  339. tnfr/validation/window.py +39 -0
  340. tnfr/validation/window.pyi +1 -0
  341. tnfr/visualization/__init__.py +98 -0
  342. tnfr/visualization/cascade_viz.py +256 -0
  343. tnfr/visualization/hierarchy.py +284 -0
  344. tnfr/visualization/sequence_plotter.py +784 -0
  345. tnfr/viz/__init__.py +60 -0
  346. tnfr/viz/matplotlib.py +278 -0
  347. tnfr/viz/matplotlib.pyi +35 -0
  348. tnfr-8.5.0.dist-info/METADATA +573 -0
  349. tnfr-8.5.0.dist-info/RECORD +353 -0
  350. tnfr-8.5.0.dist-info/entry_points.txt +3 -0
  351. tnfr-3.0.3.dist-info/licenses/LICENSE.txt → tnfr-8.5.0.dist-info/licenses/LICENSE.md +1 -1
  352. tnfr/constants.py +0 -183
  353. tnfr/dynamics.py +0 -543
  354. tnfr/helpers.py +0 -198
  355. tnfr/main.py +0 -37
  356. tnfr/operators.py +0 -296
  357. tnfr-3.0.3.dist-info/METADATA +0 -35
  358. tnfr-3.0.3.dist-info/RECORD +0 -13
  359. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
  360. {tnfr-3.0.3.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/__init__.py CHANGED
@@ -1,56 +1,375 @@
1
- from __future__ import annotations
2
- """
3
- TNFR Teoría de la Naturaleza Fractal Resonante
4
- API pública del paquete.
5
-
6
- Ecuación nodal:
7
- ∂EPI/∂t = νf · ΔNFR(t)
8
- """
9
-
10
- __version__ = "3.0.3"
11
-
12
- import sys as _sys
13
-
14
- # ------------------------------------------------------------
15
- # 1) Crear alias para módulos con imports absolutos entre sí
16
- # (los submódulos usan cosas tipo `from constants import ...`)
17
- # Por eso registramos primero: constants helpers → operators → observers
18
- # ------------------------------------------------------------
19
- from . import constants as _constants
20
- _sys.modules.setdefault("constants", _constants)
21
-
22
- from . import helpers as _helpers
23
- _sys.modules.setdefault("helpers", _helpers)
24
-
25
- from . import operators as _operators
26
- _sys.modules.setdefault("operators", _operators)
27
-
28
- from . import observers as _observers
29
- _sys.modules.setdefault("observers", _observers)
30
-
31
- # ------------------------------------------------------------
32
- # 2) IMPORTAR dynamics y ALIAS antes de ontosim
33
- # (porque ontosim hace `from dynamics import ...`)
34
- # ------------------------------------------------------------
35
- from . import dynamics as _dynamics
36
- _sys.modules.setdefault("dynamics", _dynamics)
37
-
38
- # ------------------------------------------------------------
39
- # 3) Ahora sí, importar ontosim y alias
40
- # ------------------------------------------------------------
41
- from . import ontosim as _ontosim
42
- _sys.modules.setdefault("ontosim", _ontosim)
43
-
44
- # ------------------------------------------------------------
45
- # 4) Re-exports de la API pública
46
- # ------------------------------------------------------------
47
- from .dynamics import step, run, set_delta_nfr_hook
48
- from .ontosim import preparar_red
49
- from .observers import attach_standard_observer, coherencia_global, orden_kuramoto
50
-
51
- __all__ = [
52
- "preparar_red",
53
- "step", "run", "set_delta_nfr_hook",
54
- "attach_standard_observer", "coherencia_global", "orden_kuramoto",
55
- "__version__",
56
- ]
1
+ """Minimal public API for :mod:`tnfr`.
2
+
3
+ This package only re-exports a handful of high level helpers. Most
4
+ functionality lives in submodules that should be imported directly, for
5
+ example :mod:`tnfr.metrics`, :mod:`tnfr.observers` or the DSL utilities
6
+ in :mod:`tnfr.tokens`, :mod:`tnfr.flatten` and :mod:`tnfr.execution`.
7
+
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.
37
+ """
38
+
39
+ from __future__ import annotations
40
+
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
+ try: # pragma: no cover - exercised in version resolution tests
128
+ __version__ = metadata.version("tnfr")
129
+ except PackageNotFoundError: # pragma: no cover - fallback tested explicitly
130
+ from ._version import __version__ as _fallback_version
131
+
132
+ __version__ = _fallback_version
133
+
134
+
135
+ def _is_internal_import_error(exc: ImportError) -> bool:
136
+ missing_name = getattr(exc, "name", None) or ""
137
+ if missing_name.startswith("tnfr"):
138
+ return True
139
+
140
+ module_name = getattr(exc, "module", None) or ""
141
+ if module_name.startswith("tnfr"):
142
+ return True
143
+
144
+ missing_path = getattr(exc, "path", None) or ""
145
+ if missing_path:
146
+ normalized = missing_path.replace("\\", "/")
147
+ if "/tnfr/" in normalized or normalized.endswith("/tnfr"):
148
+ return True
149
+
150
+ message = str(exc)
151
+ lowered = message.lower()
152
+ mentions_base_package = "module 'tnfr'" in lowered or 'module "tnfr"' in lowered
153
+ if ("tnfr." in message or mentions_base_package) and (
154
+ "circular import" in lowered or "partially initialized module" in lowered
155
+ ):
156
+ return True
157
+
158
+ return False
159
+
160
+
161
+ def _missing_dependency(
162
+ name: str, exc: ImportError, *, module: str | None = None
163
+ ) -> Callable[..., NoReturn]:
164
+ missing_name = getattr(exc, "name", None)
165
+
166
+ def _stub(*args: Any, **kwargs: Any) -> NoReturn:
167
+ raise ImportError(
168
+ f"{name} is unavailable because required dependencies could not be imported. "
169
+ f"Original error ({exc.__class__.__name__}): {exc}. "
170
+ "Install the missing packages (e.g. 'networkx' or grammar modules)."
171
+ ) from exc
172
+
173
+ _stub.__tnfr_missing_dependency__ = {
174
+ "export": name,
175
+ "module": module,
176
+ "missing": missing_name,
177
+ }
178
+ return _stub
179
+
180
+
181
+ _MISSING_EXPORTS: dict[str, dict[str, Any]] = {}
182
+
183
+
184
+ class ExportDependencyError(RuntimeError):
185
+ """Raised when the export dependency manifest is inconsistent."""
186
+
187
+
188
+ def _validate_export_dependencies() -> None:
189
+ """Ensure exported helpers and their manifest entries stay in sync."""
190
+
191
+ if "__all__" not in globals():
192
+ # Defensive guard for unusual import orders (should never trigger).
193
+ return
194
+
195
+ issues: list[str] = []
196
+ manifest = EXPORT_DEPENDENCIES
197
+ export_names = [name for name in __all__ if name != "__version__"]
198
+ manifest_names = set(manifest)
199
+
200
+ for export_name in export_names:
201
+ if export_name not in manifest:
202
+ issues.append(
203
+ f"helper '{export_name}' is exported via __all__ but missing from EXPORT_DEPENDENCIES"
204
+ )
205
+ continue
206
+
207
+ entry = manifest[export_name]
208
+ if not isinstance(entry, dict):
209
+ issues.append(
210
+ f"helper '{export_name}' has a malformed manifest entry (expected mapping, got {type(entry)!r})"
211
+ )
212
+ continue
213
+
214
+ for key in ("submodules", "third_party"):
215
+ value = entry.get(key)
216
+ if not value:
217
+ issues.append(
218
+ f"helper '{export_name}' is missing '{key}' dependencies in EXPORT_DEPENDENCIES"
219
+ )
220
+
221
+ missing_exports = manifest_names.difference(export_names).difference(
222
+ _MISSING_EXPORTS
223
+ )
224
+ for manifest_only in sorted(missing_exports):
225
+ entry = manifest[manifest_only]
226
+ if not isinstance(entry, dict):
227
+ issues.append(
228
+ f"helper '{manifest_only}' has a malformed manifest entry (expected mapping, got {type(entry)!r})"
229
+ )
230
+ continue
231
+
232
+ for key in ("submodules", "third_party"):
233
+ value = entry.get(key)
234
+ if not value:
235
+ issues.append(
236
+ f"helper '{manifest_only}' is missing '{key}' dependencies in EXPORT_DEPENDENCIES"
237
+ )
238
+
239
+ issues.append(
240
+ f"helper '{manifest_only}' is listed in EXPORT_DEPENDENCIES but not exported via __all__"
241
+ )
242
+
243
+ if issues:
244
+ raise ExportDependencyError(
245
+ "Invalid TNFR export dependency manifest:\n- " + "\n- ".join(issues)
246
+ )
247
+
248
+
249
+ def _assign_exports(module: str, names: tuple[str, ...]) -> bool:
250
+ try: # pragma: no cover - exercised in import tests
251
+ mod = import_module(f".{module}", __name__)
252
+ except ImportError as exc: # pragma: no cover - no missing deps in CI
253
+ if _is_internal_import_error(exc):
254
+ raise
255
+ for export_name in names:
256
+ stub = _missing_dependency(export_name, exc, module=module)
257
+ globals()[export_name] = stub
258
+ _MISSING_EXPORTS[export_name] = getattr(
259
+ stub, "__tnfr_missing_dependency__", {}
260
+ )
261
+ return False
262
+ else:
263
+ for export_name in names:
264
+ globals()[export_name] = getattr(mod, export_name)
265
+ return True
266
+
267
+
268
+ def __getattr__(name: str) -> Any:
269
+ """Lazy load SDK components and handle missing dependencies."""
270
+ # SDK exports - lazy loaded to avoid circular dependencies
271
+ if name == "TNFRNetwork":
272
+ try:
273
+ from .sdk.fluent import TNFRNetwork
274
+
275
+ globals()[name] = TNFRNetwork
276
+ return TNFRNetwork
277
+ except ImportError as exc:
278
+ if _is_internal_import_error(exc):
279
+ raise
280
+ stub = _missing_dependency(name, exc, module="sdk.fluent")
281
+ globals()[name] = stub
282
+ return stub
283
+ elif name == "TNFRTemplates":
284
+ try:
285
+ from .sdk.templates import TNFRTemplates
286
+
287
+ globals()[name] = TNFRTemplates
288
+ return TNFRTemplates
289
+ except ImportError as exc:
290
+ if _is_internal_import_error(exc):
291
+ raise
292
+ stub = _missing_dependency(name, exc, module="sdk.templates")
293
+ globals()[name] = stub
294
+ return stub
295
+ elif name == "TNFRExperimentBuilder":
296
+ try:
297
+ from .sdk.builders import TNFRExperimentBuilder
298
+
299
+ globals()[name] = TNFRExperimentBuilder
300
+ return TNFRExperimentBuilder
301
+ except ImportError as exc:
302
+ if _is_internal_import_error(exc):
303
+ raise
304
+ stub = _missing_dependency(name, exc, module="sdk.builders")
305
+ globals()[name] = stub
306
+ return stub
307
+
308
+ raise AttributeError(f"module 'tnfr' has no attribute '{name}'")
309
+
310
+
311
+ _assign_exports("dynamics", ("step", "run"))
312
+
313
+ _HAS_PREPARE_NETWORK = _assign_exports("ontosim", ("prepare_network",))
314
+
315
+ _HAS_STRUCTURAL_EXPORTS = _assign_exports(
316
+ "structural", ("create_nfr", "run_sequence", "create_math_nfr")
317
+ )
318
+
319
+ _assign_exports("units", ("get_hz_bridge", "hz_str_to_hz", "hz_to_hz_str"))
320
+
321
+
322
+ def _emit_missing_dependency_warning() -> None:
323
+ if not _MISSING_EXPORTS:
324
+ return
325
+ details = ", ".join(
326
+ f"{name} (missing: {info.get('missing') or 'unknown'})"
327
+ for name, info in sorted(_MISSING_EXPORTS.items())
328
+ )
329
+ warnings.warn(
330
+ "TNFR helpers disabled because dependencies are missing: " + details,
331
+ ImportWarning,
332
+ stacklevel=2,
333
+ )
334
+
335
+
336
+ _emit_missing_dependency_warning()
337
+
338
+ __all__ = [
339
+ "__version__",
340
+ "step",
341
+ "run",
342
+ "prepare_network",
343
+ "create_nfr",
344
+ "get_hz_bridge",
345
+ "hz_str_to_hz",
346
+ "hz_to_hz_str",
347
+ # SDK exports (lazily loaded)
348
+ "TNFRNetwork",
349
+ "TNFRTemplates",
350
+ "TNFRExperimentBuilder",
351
+ ]
352
+
353
+ if _HAS_STRUCTURAL_EXPORTS:
354
+ __all__.extend(["run_sequence", "create_math_nfr"])
355
+
356
+ # Add SDK exports to dependency manifest for validation
357
+ EXPORT_DEPENDENCIES["TNFRNetwork"] = {
358
+ "submodules": (
359
+ "tnfr.sdk.fluent",
360
+ "tnfr.structural",
361
+ "tnfr.metrics",
362
+ "tnfr.validation",
363
+ ),
364
+ "third_party": ("networkx",),
365
+ }
366
+ EXPORT_DEPENDENCIES["TNFRTemplates"] = {
367
+ "submodules": ("tnfr.sdk.templates", "tnfr.sdk.fluent"),
368
+ "third_party": ("networkx",),
369
+ }
370
+ EXPORT_DEPENDENCIES["TNFRExperimentBuilder"] = {
371
+ "submodules": ("tnfr.sdk.builders", "tnfr.sdk.fluent"),
372
+ "third_party": ("networkx",),
373
+ }
374
+
375
+ _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 = '8.5.0'
32
+ __version_tuple__ = version_tuple = (8, 5, 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 # Fallback to alternative version sources
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 # Generated version not available
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 # setuptools_scm not available
40
+ else:
41
+ try:
42
+ return get_version(relative_to=__file__)
43
+ except LookupError:
44
+ pass # No version found via setuptools_scm
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