tnfr 4.5.2__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 (365) hide show
  1. tnfr/__init__.py +334 -50
  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 +214 -37
  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 +149 -556
  15. tnfr/cache.pyi +13 -0
  16. tnfr/cli/__init__.py +51 -16
  17. tnfr/cli/__init__.pyi +26 -0
  18. tnfr/cli/arguments.py +344 -32
  19. tnfr/cli/arguments.pyi +29 -0
  20. tnfr/cli/execution.py +676 -50
  21. tnfr/cli/execution.pyi +70 -0
  22. tnfr/cli/interactive_validator.py +614 -0
  23. tnfr/cli/utils.py +18 -3
  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/{constants_glyphs.py → config/constants.py} +26 -20
  34. tnfr/config/constants.pyi +12 -0
  35. tnfr/config/defaults.py +54 -0
  36. tnfr/{constants/core.py → config/defaults_core.py} +59 -6
  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 +51 -133
  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 +3 -1
  57. tnfr/constants/init.pyi +12 -0
  58. tnfr/constants/metric.py +9 -15
  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 +213 -633
  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 +2699 -398
  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 +496 -102
  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 +10 -5
  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 +77 -55
  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 +29 -50
  125. tnfr/flatten.pyi +21 -0
  126. tnfr/gamma.py +66 -53
  127. tnfr/gamma.pyi +36 -0
  128. tnfr/glyph_history.py +144 -57
  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 +70 -30
  133. tnfr/immutable.pyi +36 -0
  134. tnfr/initialization.py +22 -16
  135. tnfr/initialization.pyi +65 -0
  136. tnfr/io.py +5 -241
  137. tnfr/io.pyi +13 -0
  138. tnfr/locking.pyi +7 -0
  139. tnfr/mathematics/__init__.py +79 -0
  140. tnfr/mathematics/backend.py +453 -0
  141. tnfr/mathematics/backend.pyi +99 -0
  142. tnfr/mathematics/dynamics.py +408 -0
  143. tnfr/mathematics/dynamics.pyi +90 -0
  144. tnfr/mathematics/epi.py +391 -0
  145. tnfr/mathematics/epi.pyi +65 -0
  146. tnfr/mathematics/generators.py +242 -0
  147. tnfr/mathematics/generators.pyi +29 -0
  148. tnfr/mathematics/metrics.py +119 -0
  149. tnfr/mathematics/metrics.pyi +16 -0
  150. tnfr/mathematics/operators.py +239 -0
  151. tnfr/mathematics/operators.pyi +59 -0
  152. tnfr/mathematics/operators_factory.py +124 -0
  153. tnfr/mathematics/operators_factory.pyi +11 -0
  154. tnfr/mathematics/projection.py +87 -0
  155. tnfr/mathematics/projection.pyi +33 -0
  156. tnfr/mathematics/runtime.py +182 -0
  157. tnfr/mathematics/runtime.pyi +64 -0
  158. tnfr/mathematics/spaces.py +256 -0
  159. tnfr/mathematics/spaces.pyi +83 -0
  160. tnfr/mathematics/transforms.py +305 -0
  161. tnfr/mathematics/transforms.pyi +62 -0
  162. tnfr/metrics/__init__.py +47 -9
  163. tnfr/metrics/__init__.pyi +20 -0
  164. tnfr/metrics/buffer_cache.py +163 -0
  165. tnfr/metrics/buffer_cache.pyi +24 -0
  166. tnfr/metrics/cache_utils.py +214 -0
  167. tnfr/metrics/coherence.py +1510 -330
  168. tnfr/metrics/coherence.pyi +129 -0
  169. tnfr/metrics/common.py +23 -16
  170. tnfr/metrics/common.pyi +35 -0
  171. tnfr/metrics/core.py +251 -36
  172. tnfr/metrics/core.pyi +13 -0
  173. tnfr/metrics/diagnosis.py +709 -110
  174. tnfr/metrics/diagnosis.pyi +86 -0
  175. tnfr/metrics/emergence.py +245 -0
  176. tnfr/metrics/export.py +60 -18
  177. tnfr/metrics/export.pyi +7 -0
  178. tnfr/metrics/glyph_timing.py +233 -43
  179. tnfr/metrics/glyph_timing.pyi +81 -0
  180. tnfr/metrics/learning_metrics.py +280 -0
  181. tnfr/metrics/learning_metrics.pyi +21 -0
  182. tnfr/metrics/phase_coherence.py +351 -0
  183. tnfr/metrics/phase_compatibility.py +349 -0
  184. tnfr/metrics/reporting.py +63 -28
  185. tnfr/metrics/reporting.pyi +25 -0
  186. tnfr/metrics/sense_index.py +1126 -43
  187. tnfr/metrics/sense_index.pyi +9 -0
  188. tnfr/metrics/trig.py +215 -23
  189. tnfr/metrics/trig.pyi +13 -0
  190. tnfr/metrics/trig_cache.py +148 -24
  191. tnfr/metrics/trig_cache.pyi +10 -0
  192. tnfr/multiscale/__init__.py +32 -0
  193. tnfr/multiscale/hierarchical.py +517 -0
  194. tnfr/node.py +646 -140
  195. tnfr/node.pyi +139 -0
  196. tnfr/observers.py +160 -45
  197. tnfr/observers.pyi +31 -0
  198. tnfr/ontosim.py +23 -19
  199. tnfr/ontosim.pyi +28 -0
  200. tnfr/operators/__init__.py +1358 -106
  201. tnfr/operators/__init__.pyi +31 -0
  202. tnfr/operators/algebra.py +277 -0
  203. tnfr/operators/canonical_patterns.py +420 -0
  204. tnfr/operators/cascade.py +267 -0
  205. tnfr/operators/cycle_detection.py +358 -0
  206. tnfr/operators/definitions.py +4108 -0
  207. tnfr/operators/definitions.pyi +78 -0
  208. tnfr/operators/grammar.py +1164 -0
  209. tnfr/operators/grammar.pyi +140 -0
  210. tnfr/operators/hamiltonian.py +710 -0
  211. tnfr/operators/health_analyzer.py +809 -0
  212. tnfr/operators/jitter.py +107 -38
  213. tnfr/operators/jitter.pyi +11 -0
  214. tnfr/operators/lifecycle.py +314 -0
  215. tnfr/operators/metabolism.py +618 -0
  216. tnfr/operators/metrics.py +2138 -0
  217. tnfr/operators/network_analysis/__init__.py +27 -0
  218. tnfr/operators/network_analysis/source_detection.py +186 -0
  219. tnfr/operators/nodal_equation.py +395 -0
  220. tnfr/operators/pattern_detection.py +660 -0
  221. tnfr/operators/patterns.py +669 -0
  222. tnfr/operators/postconditions/__init__.py +38 -0
  223. tnfr/operators/postconditions/mutation.py +236 -0
  224. tnfr/operators/preconditions/__init__.py +1226 -0
  225. tnfr/operators/preconditions/coherence.py +305 -0
  226. tnfr/operators/preconditions/dissonance.py +236 -0
  227. tnfr/operators/preconditions/emission.py +128 -0
  228. tnfr/operators/preconditions/mutation.py +580 -0
  229. tnfr/operators/preconditions/reception.py +125 -0
  230. tnfr/operators/preconditions/resonance.py +364 -0
  231. tnfr/operators/registry.py +74 -0
  232. tnfr/operators/registry.pyi +9 -0
  233. tnfr/operators/remesh.py +1415 -91
  234. tnfr/operators/remesh.pyi +26 -0
  235. tnfr/operators/structural_units.py +268 -0
  236. tnfr/operators/unified_grammar.py +105 -0
  237. tnfr/parallel/__init__.py +54 -0
  238. tnfr/parallel/auto_scaler.py +234 -0
  239. tnfr/parallel/distributed.py +384 -0
  240. tnfr/parallel/engine.py +238 -0
  241. tnfr/parallel/gpu_engine.py +420 -0
  242. tnfr/parallel/monitoring.py +248 -0
  243. tnfr/parallel/partitioner.py +459 -0
  244. tnfr/py.typed +0 -0
  245. tnfr/recipes/__init__.py +22 -0
  246. tnfr/recipes/cookbook.py +743 -0
  247. tnfr/rng.py +75 -151
  248. tnfr/rng.pyi +26 -0
  249. tnfr/schemas/__init__.py +8 -0
  250. tnfr/schemas/grammar.json +94 -0
  251. tnfr/sdk/__init__.py +107 -0
  252. tnfr/sdk/__init__.pyi +19 -0
  253. tnfr/sdk/adaptive_system.py +173 -0
  254. tnfr/sdk/adaptive_system.pyi +21 -0
  255. tnfr/sdk/builders.py +370 -0
  256. tnfr/sdk/builders.pyi +51 -0
  257. tnfr/sdk/fluent.py +1121 -0
  258. tnfr/sdk/fluent.pyi +74 -0
  259. tnfr/sdk/templates.py +342 -0
  260. tnfr/sdk/templates.pyi +41 -0
  261. tnfr/sdk/utils.py +341 -0
  262. tnfr/secure_config.py +46 -0
  263. tnfr/security/__init__.py +70 -0
  264. tnfr/security/database.py +514 -0
  265. tnfr/security/subprocess.py +503 -0
  266. tnfr/security/validation.py +290 -0
  267. tnfr/selector.py +59 -22
  268. tnfr/selector.pyi +19 -0
  269. tnfr/sense.py +92 -67
  270. tnfr/sense.pyi +23 -0
  271. tnfr/services/__init__.py +17 -0
  272. tnfr/services/orchestrator.py +325 -0
  273. tnfr/sparse/__init__.py +39 -0
  274. tnfr/sparse/representations.py +492 -0
  275. tnfr/structural.py +639 -263
  276. tnfr/structural.pyi +83 -0
  277. tnfr/telemetry/__init__.py +35 -0
  278. tnfr/telemetry/cache_metrics.py +226 -0
  279. tnfr/telemetry/cache_metrics.pyi +64 -0
  280. tnfr/telemetry/nu_f.py +422 -0
  281. tnfr/telemetry/nu_f.pyi +108 -0
  282. tnfr/telemetry/verbosity.py +36 -0
  283. tnfr/telemetry/verbosity.pyi +15 -0
  284. tnfr/tokens.py +2 -4
  285. tnfr/tokens.pyi +36 -0
  286. tnfr/tools/__init__.py +20 -0
  287. tnfr/tools/domain_templates.py +478 -0
  288. tnfr/tools/sequence_generator.py +846 -0
  289. tnfr/topology/__init__.py +13 -0
  290. tnfr/topology/asymmetry.py +151 -0
  291. tnfr/trace.py +300 -126
  292. tnfr/trace.pyi +42 -0
  293. tnfr/tutorials/__init__.py +38 -0
  294. tnfr/tutorials/autonomous_evolution.py +285 -0
  295. tnfr/tutorials/interactive.py +1576 -0
  296. tnfr/tutorials/structural_metabolism.py +238 -0
  297. tnfr/types.py +743 -12
  298. tnfr/types.pyi +357 -0
  299. tnfr/units.py +68 -0
  300. tnfr/units.pyi +13 -0
  301. tnfr/utils/__init__.py +282 -0
  302. tnfr/utils/__init__.pyi +215 -0
  303. tnfr/utils/cache.py +4223 -0
  304. tnfr/utils/cache.pyi +470 -0
  305. tnfr/{callback_utils.py → utils/callbacks.py} +26 -39
  306. tnfr/utils/callbacks.pyi +49 -0
  307. tnfr/utils/chunks.py +108 -0
  308. tnfr/utils/chunks.pyi +22 -0
  309. tnfr/utils/data.py +428 -0
  310. tnfr/utils/data.pyi +74 -0
  311. tnfr/utils/graph.py +85 -0
  312. tnfr/utils/graph.pyi +10 -0
  313. tnfr/utils/init.py +821 -0
  314. tnfr/utils/init.pyi +80 -0
  315. tnfr/utils/io.py +559 -0
  316. tnfr/utils/io.pyi +66 -0
  317. tnfr/{helpers → utils}/numeric.py +51 -24
  318. tnfr/utils/numeric.pyi +21 -0
  319. tnfr/validation/__init__.py +257 -0
  320. tnfr/validation/__init__.pyi +85 -0
  321. tnfr/validation/compatibility.py +460 -0
  322. tnfr/validation/compatibility.pyi +6 -0
  323. tnfr/validation/config.py +73 -0
  324. tnfr/validation/graph.py +139 -0
  325. tnfr/validation/graph.pyi +18 -0
  326. tnfr/validation/input_validation.py +755 -0
  327. tnfr/validation/invariants.py +712 -0
  328. tnfr/validation/rules.py +253 -0
  329. tnfr/validation/rules.pyi +44 -0
  330. tnfr/validation/runtime.py +279 -0
  331. tnfr/validation/runtime.pyi +28 -0
  332. tnfr/validation/sequence_validator.py +162 -0
  333. tnfr/validation/soft_filters.py +170 -0
  334. tnfr/validation/soft_filters.pyi +32 -0
  335. tnfr/validation/spectral.py +164 -0
  336. tnfr/validation/spectral.pyi +42 -0
  337. tnfr/validation/validator.py +1266 -0
  338. tnfr/validation/window.py +39 -0
  339. tnfr/validation/window.pyi +1 -0
  340. tnfr/visualization/__init__.py +98 -0
  341. tnfr/visualization/cascade_viz.py +256 -0
  342. tnfr/visualization/hierarchy.py +284 -0
  343. tnfr/visualization/sequence_plotter.py +784 -0
  344. tnfr/viz/__init__.py +60 -0
  345. tnfr/viz/matplotlib.py +278 -0
  346. tnfr/viz/matplotlib.pyi +35 -0
  347. tnfr-8.5.0.dist-info/METADATA +573 -0
  348. tnfr-8.5.0.dist-info/RECORD +353 -0
  349. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/entry_points.txt +1 -0
  350. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/licenses/LICENSE.md +1 -1
  351. tnfr/collections_utils.py +0 -300
  352. tnfr/config.py +0 -32
  353. tnfr/grammar.py +0 -344
  354. tnfr/graph_utils.py +0 -84
  355. tnfr/helpers/__init__.py +0 -71
  356. tnfr/import_utils.py +0 -228
  357. tnfr/json_utils.py +0 -162
  358. tnfr/logging_utils.py +0 -116
  359. tnfr/presets.py +0 -60
  360. tnfr/validators.py +0 -84
  361. tnfr/value_utils.py +0 -59
  362. tnfr-4.5.2.dist-info/METADATA +0 -379
  363. tnfr-4.5.2.dist-info/RECORD +0 -67
  364. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/WHEEL +0 -0
  365. {tnfr-4.5.2.dist-info → tnfr-8.5.0.dist-info}/top_level.txt +0 -0
tnfr/__init__.py CHANGED
@@ -4,88 +4,372 @@ 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
+ 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
19
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
20
149
 
21
- def _missing_dependency(name: str, exc: ImportError):
22
- def _stub(*args, **kwargs):
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:
23
167
  raise ImportError(
24
168
  f"{name} is unavailable because required dependencies could not be imported. "
25
169
  f"Original error ({exc.__class__.__name__}): {exc}. "
26
170
  "Install the missing packages (e.g. 'networkx' or grammar modules)."
27
171
  ) from exc
28
172
 
173
+ _stub.__tnfr_missing_dependency__ = {
174
+ "export": name,
175
+ "module": module,
176
+ "missing": missing_name,
177
+ }
29
178
  return _stub
30
179
 
31
180
 
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)
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
37
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)
38
199
 
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
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
47
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
48
213
 
49
- _metadata = cached_import("importlib.metadata")
50
- if _metadata is None: # pragma: no cover
51
- _metadata = cached_import("importlib_metadata")
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
+ )
52
220
 
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
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
57
231
 
58
- class PackageNotFoundError(Exception):
59
- pass
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
+ )
60
238
 
61
- def version(_: str) -> str:
62
- raise PackageNotFoundError
239
+ issues.append(
240
+ f"helper '{manifest_only}' is listed in EXPORT_DEPENDENCIES but not exported via __all__"
241
+ )
63
242
 
243
+ if issues:
244
+ raise ExportDependencyError(
245
+ "Invalid TNFR export dependency manifest:\n- " + "\n- ".join(issues)
246
+ )
64
247
 
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
71
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":
72
296
  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"
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()
81
337
 
82
338
  __all__ = [
83
339
  "__version__",
84
340
  "step",
85
341
  "run",
86
- "preparar_red",
342
+ "prepare_network",
87
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",
88
351
  ]
89
352
 
90
- if _HAS_RUN_SEQUENCE:
91
- __all__.append("run_sequence")
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