tnfr 6.0.0__tar.gz → 7.0.0__tar.gz

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 (235) hide show
  1. {tnfr-6.0.0 → tnfr-7.0.0}/LICENSE.md +1 -1
  2. {tnfr-6.0.0/src/tnfr.egg-info → tnfr-7.0.0}/PKG-INFO +63 -19
  3. {tnfr-6.0.0 → tnfr-7.0.0}/README.md +37 -17
  4. {tnfr-6.0.0 → tnfr-7.0.0}/pyproject.toml +72 -6
  5. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/__init__.py +50 -5
  6. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/__init__.pyi +0 -7
  7. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/_compat.py +0 -1
  8. tnfr-7.0.0/src/tnfr/_generated_version.py +34 -0
  9. tnfr-7.0.0/src/tnfr/_version.py +49 -0
  10. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/alias.py +14 -13
  11. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/alias.pyi +5 -37
  12. tnfr-7.0.0/src/tnfr/cache.py +12 -0
  13. tnfr-7.0.0/src/tnfr/cache.pyi +16 -0
  14. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/callback_utils.py +16 -31
  15. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/callback_utils.pyi +3 -29
  16. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/cli/__init__.py +17 -11
  17. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/cli/__init__.pyi +0 -21
  18. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/cli/arguments.py +175 -14
  19. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/cli/arguments.pyi +5 -11
  20. tnfr-7.0.0/src/tnfr/cli/execution.py +708 -0
  21. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/cli/execution.pyi +14 -24
  22. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/cli/utils.py +20 -3
  23. tnfr-7.0.0/src/tnfr/cli/utils.pyi +8 -0
  24. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/__init__.py +2 -1
  25. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/__init__.pyi +2 -0
  26. tnfr-7.0.0/src/tnfr/config/feature_flags.py +83 -0
  27. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/init.py +1 -1
  28. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/operator_names.py +1 -14
  29. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/presets.py +6 -26
  30. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/__init__.py +10 -13
  31. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/__init__.pyi +10 -22
  32. tnfr-7.0.0/src/tnfr/constants/aliases.py +31 -0
  33. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/core.py +4 -3
  34. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/init.py +1 -1
  35. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/metric.py +3 -3
  36. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/__init__.py +64 -10
  37. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/__init__.pyi +3 -4
  38. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/adaptation.py +79 -13
  39. tnfr-7.0.0/src/tnfr/dynamics/aliases.py +23 -0
  40. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/coordination.py +77 -35
  41. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/dnfr.py +575 -274
  42. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/dnfr.pyi +1 -10
  43. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/integrators.py +47 -33
  44. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/integrators.pyi +0 -1
  45. tnfr-7.0.0/src/tnfr/dynamics/runtime.py +881 -0
  46. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/sampling.py +2 -0
  47. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/selectors.py +101 -62
  48. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/execution.py +15 -8
  49. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/execution.pyi +5 -25
  50. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/flatten.py +7 -3
  51. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/flatten.pyi +1 -8
  52. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/gamma.py +22 -26
  53. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/gamma.pyi +0 -6
  54. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/glyph_history.py +37 -26
  55. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/glyph_history.pyi +1 -19
  56. tnfr-7.0.0/src/tnfr/glyph_runtime.py +16 -0
  57. tnfr-7.0.0/src/tnfr/glyph_runtime.pyi +9 -0
  58. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/immutable.py +20 -15
  59. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/immutable.pyi +4 -7
  60. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/initialization.py +5 -7
  61. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/initialization.pyi +1 -9
  62. tnfr-7.0.0/src/tnfr/io.py +12 -0
  63. tnfr-7.0.0/src/tnfr/io.pyi +16 -0
  64. tnfr-7.0.0/src/tnfr/mathematics/__init__.py +81 -0
  65. tnfr-7.0.0/src/tnfr/mathematics/backend.py +426 -0
  66. tnfr-7.0.0/src/tnfr/mathematics/dynamics.py +398 -0
  67. tnfr-7.0.0/src/tnfr/mathematics/epi.py +254 -0
  68. tnfr-7.0.0/src/tnfr/mathematics/generators.py +222 -0
  69. tnfr-7.0.0/src/tnfr/mathematics/metrics.py +119 -0
  70. tnfr-7.0.0/src/tnfr/mathematics/operators.py +233 -0
  71. tnfr-7.0.0/src/tnfr/mathematics/operators_factory.py +71 -0
  72. tnfr-7.0.0/src/tnfr/mathematics/projection.py +78 -0
  73. tnfr-7.0.0/src/tnfr/mathematics/runtime.py +173 -0
  74. tnfr-7.0.0/src/tnfr/mathematics/spaces.py +247 -0
  75. tnfr-7.0.0/src/tnfr/mathematics/transforms.py +292 -0
  76. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/coherence.py +123 -94
  77. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/common.py +22 -13
  78. tnfr-7.0.0/src/tnfr/metrics/common.pyi +46 -0
  79. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/core.py +72 -14
  80. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/diagnosis.py +48 -57
  81. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/diagnosis.pyi +3 -7
  82. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/export.py +3 -5
  83. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/glyph_timing.py +41 -31
  84. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/reporting.py +13 -6
  85. tnfr-7.0.0/src/tnfr/metrics/sense_index.py +1064 -0
  86. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/trig.py +167 -11
  87. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/trig.pyi +1 -0
  88. tnfr-7.0.0/src/tnfr/metrics/trig_cache.py +202 -0
  89. tnfr-7.0.0/src/tnfr/node.py +663 -0
  90. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/node.pyi +55 -38
  91. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/observers.py +111 -8
  92. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/observers.pyi +0 -15
  93. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/ontosim.py +9 -6
  94. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/ontosim.pyi +0 -5
  95. tnfr-7.0.0/src/tnfr/operators/__init__.py +939 -0
  96. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/operators/__init__.pyi +14 -0
  97. tnfr-7.0.0/src/tnfr/operators/definitions.py +513 -0
  98. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/operators/definitions.pyi +0 -14
  99. tnfr-7.0.0/src/tnfr/operators/grammar.py +760 -0
  100. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/operators/jitter.py +28 -22
  101. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/operators/registry.py +7 -12
  102. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/operators/registry.pyi +0 -2
  103. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/operators/remesh.py +38 -61
  104. tnfr-7.0.0/src/tnfr/rng.py +157 -0
  105. tnfr-7.0.0/src/tnfr/schemas/__init__.py +8 -0
  106. tnfr-7.0.0/src/tnfr/schemas/grammar.json +94 -0
  107. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/selector.py +3 -4
  108. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/sense.py +22 -24
  109. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/sense.pyi +0 -7
  110. tnfr-7.0.0/src/tnfr/structural.py +589 -0
  111. tnfr-7.0.0/src/tnfr/structural.pyi +69 -0
  112. tnfr-7.0.0/src/tnfr/telemetry/__init__.py +35 -0
  113. tnfr-7.0.0/src/tnfr/telemetry/cache_metrics.py +226 -0
  114. tnfr-7.0.0/src/tnfr/telemetry/nu_f.py +423 -0
  115. tnfr-7.0.0/src/tnfr/telemetry/nu_f.pyi +123 -0
  116. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/tokens.py +1 -4
  117. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/tokens.pyi +1 -6
  118. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/trace.py +20 -53
  119. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/trace.pyi +9 -37
  120. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/types.py +244 -15
  121. tnfr-7.0.0/src/tnfr/types.pyi +331 -0
  122. tnfr-7.0.0/src/tnfr/units.py +69 -0
  123. tnfr-7.0.0/src/tnfr/units.pyi +16 -0
  124. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/__init__.py +107 -48
  125. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/__init__.pyi +80 -11
  126. tnfr-7.0.0/src/tnfr/utils/cache.py +2395 -0
  127. tnfr-7.0.0/src/tnfr/utils/cache.pyi +468 -0
  128. tnfr-7.0.0/src/tnfr/utils/chunks.py +104 -0
  129. tnfr-7.0.0/src/tnfr/utils/chunks.pyi +21 -0
  130. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/data.py +95 -5
  131. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/data.pyi +8 -17
  132. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/graph.py +2 -4
  133. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/init.py +31 -7
  134. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/init.pyi +4 -11
  135. {tnfr-6.0.0/src/tnfr → tnfr-7.0.0/src/tnfr/utils}/io.py +160 -15
  136. {tnfr-6.0.0/src/tnfr/helpers → tnfr-7.0.0/src/tnfr/utils}/numeric.py +50 -24
  137. tnfr-7.0.0/src/tnfr/utils/numeric.pyi +21 -0
  138. tnfr-7.0.0/src/tnfr/validation/__init__.py +113 -0
  139. tnfr-7.0.0/src/tnfr/validation/__init__.pyi +77 -0
  140. tnfr-7.0.0/src/tnfr/validation/compatibility.py +95 -0
  141. tnfr-7.0.0/src/tnfr/validation/compatibility.pyi +6 -0
  142. tnfr-7.0.0/src/tnfr/validation/grammar.py +71 -0
  143. tnfr-7.0.0/src/tnfr/validation/grammar.pyi +40 -0
  144. tnfr-7.0.0/src/tnfr/validation/graph.py +138 -0
  145. tnfr-7.0.0/src/tnfr/validation/graph.pyi +17 -0
  146. tnfr-7.0.0/src/tnfr/validation/rules.py +281 -0
  147. tnfr-7.0.0/src/tnfr/validation/rules.pyi +55 -0
  148. tnfr-7.0.0/src/tnfr/validation/runtime.py +263 -0
  149. tnfr-7.0.0/src/tnfr/validation/runtime.pyi +31 -0
  150. tnfr-7.0.0/src/tnfr/validation/soft_filters.py +170 -0
  151. tnfr-7.0.0/src/tnfr/validation/soft_filters.pyi +37 -0
  152. tnfr-7.0.0/src/tnfr/validation/spectral.py +159 -0
  153. tnfr-7.0.0/src/tnfr/validation/spectral.pyi +46 -0
  154. tnfr-7.0.0/src/tnfr/validation/syntax.py +40 -0
  155. tnfr-7.0.0/src/tnfr/validation/syntax.pyi +10 -0
  156. tnfr-7.0.0/src/tnfr/validation/window.py +39 -0
  157. tnfr-7.0.0/src/tnfr/validation/window.pyi +1 -0
  158. tnfr-7.0.0/src/tnfr/viz/__init__.py +9 -0
  159. tnfr-7.0.0/src/tnfr/viz/matplotlib.py +246 -0
  160. {tnfr-6.0.0 → tnfr-7.0.0/src/tnfr.egg-info}/PKG-INFO +63 -19
  161. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr.egg-info/SOURCES.txt +42 -14
  162. tnfr-7.0.0/src/tnfr.egg-info/requires.txt +58 -0
  163. tnfr-6.0.0/src/tnfr/_version.py +0 -7
  164. tnfr-6.0.0/src/tnfr/cache.py +0 -732
  165. tnfr-6.0.0/src/tnfr/cache.pyi +0 -232
  166. tnfr-6.0.0/src/tnfr/cli/execution.py +0 -322
  167. tnfr-6.0.0/src/tnfr/cli/utils.pyi +0 -8
  168. tnfr-6.0.0/src/tnfr/constants_glyphs.py +0 -16
  169. tnfr-6.0.0/src/tnfr/constants_glyphs.pyi +0 -12
  170. tnfr-6.0.0/src/tnfr/dynamics/aliases.py +0 -22
  171. tnfr-6.0.0/src/tnfr/dynamics/runtime.py +0 -521
  172. tnfr-6.0.0/src/tnfr/grammar.py +0 -25
  173. tnfr-6.0.0/src/tnfr/grammar.pyi +0 -13
  174. tnfr-6.0.0/src/tnfr/helpers/__init__.py +0 -151
  175. tnfr-6.0.0/src/tnfr/helpers/__init__.pyi +0 -66
  176. tnfr-6.0.0/src/tnfr/helpers/numeric.pyi +0 -12
  177. tnfr-6.0.0/src/tnfr/io.pyi +0 -11
  178. tnfr-6.0.0/src/tnfr/metrics/common.pyi +0 -15
  179. tnfr-6.0.0/src/tnfr/metrics/sense_index.py +0 -294
  180. tnfr-6.0.0/src/tnfr/metrics/trig_cache.py +0 -105
  181. tnfr-6.0.0/src/tnfr/node.py +0 -280
  182. tnfr-6.0.0/src/tnfr/operators/__init__.py +0 -452
  183. tnfr-6.0.0/src/tnfr/operators/definitions.py +0 -181
  184. tnfr-6.0.0/src/tnfr/presets.py +0 -15
  185. tnfr-6.0.0/src/tnfr/presets.pyi +0 -7
  186. tnfr-6.0.0/src/tnfr/rng.py +0 -440
  187. tnfr-6.0.0/src/tnfr/structural.py +0 -106
  188. tnfr-6.0.0/src/tnfr/structural.pyi +0 -46
  189. tnfr-6.0.0/src/tnfr/telemetry/__init__.py +0 -13
  190. tnfr-6.0.0/src/tnfr/types.pyi +0 -145
  191. tnfr-6.0.0/src/tnfr/utils/cache.py +0 -755
  192. tnfr-6.0.0/src/tnfr/utils/cache.pyi +0 -156
  193. tnfr-6.0.0/src/tnfr/utils/io.py +0 -157
  194. tnfr-6.0.0/src/tnfr/utils/io.pyi +0 -10
  195. tnfr-6.0.0/src/tnfr/utils/validators.py +0 -130
  196. tnfr-6.0.0/src/tnfr/utils/validators.pyi +0 -19
  197. tnfr-6.0.0/src/tnfr/validation/__init__.py +0 -25
  198. tnfr-6.0.0/src/tnfr/validation/__init__.pyi +0 -17
  199. tnfr-6.0.0/src/tnfr/validation/compatibility.py +0 -59
  200. tnfr-6.0.0/src/tnfr/validation/compatibility.pyi +0 -8
  201. tnfr-6.0.0/src/tnfr/validation/grammar.py +0 -149
  202. tnfr-6.0.0/src/tnfr/validation/grammar.pyi +0 -11
  203. tnfr-6.0.0/src/tnfr/validation/rules.py +0 -194
  204. tnfr-6.0.0/src/tnfr/validation/rules.pyi +0 -18
  205. tnfr-6.0.0/src/tnfr/validation/syntax.py +0 -151
  206. tnfr-6.0.0/src/tnfr/validation/syntax.pyi +0 -7
  207. tnfr-6.0.0/src/tnfr.egg-info/requires.txt +0 -29
  208. {tnfr-6.0.0 → tnfr-7.0.0}/setup.cfg +0 -0
  209. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/_version.pyi +0 -0
  210. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/constants.py +0 -0
  211. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/constants.pyi +0 -0
  212. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/init.pyi +0 -0
  213. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/operator_names.pyi +0 -0
  214. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/config/presets.pyi +0 -0
  215. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/core.pyi +0 -0
  216. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/init.pyi +0 -0
  217. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/constants/metric.pyi +0 -0
  218. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/dynamics/sampling.pyi +0 -0
  219. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/locking.py +0 -0
  220. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/locking.pyi +0 -0
  221. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/__init__.py +10 -10
  222. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/__init__.pyi +0 -0
  223. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/core.pyi +0 -0
  224. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/reporting.pyi +0 -0
  225. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/sense_index.pyi +0 -0
  226. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/metrics/trig_cache.pyi +0 -0
  227. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/operators/jitter.pyi +0 -0
  228. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/py.typed +0 -0
  229. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/rng.pyi +0 -0
  230. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/selector.pyi +1 -1
  231. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/telemetry/verbosity.py +0 -0
  232. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr/utils/graph.pyi +0 -0
  233. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr.egg-info/dependency_links.txt +0 -0
  234. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr.egg-info/entry_points.txt +0 -0
  235. {tnfr-6.0.0 → tnfr-7.0.0}/src/tnfr.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright (c) 2025 TNFR - Teoría de la naturaleza fractral resonante
3
+ Copyright (c) 2025 TNFR Resonant Fractal Nature Theory
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tnfr
3
- Version: 6.0.0
3
+ Version: 7.0.0
4
4
  Summary: Modular structural-based dynamics on networks.
5
5
  Author: fmg
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://pypi.org/project/tnfr/
8
8
  Project-URL: Repository, https://github.com/fermga/TNFR-Python-Engine
9
- Project-URL: GPT, https://chatgpt.com/g/g-67abc78885a88191b2d67f94fd60dc97-tnfr-teoria-de-la-naturaleza-fractal-resonante
9
+ Project-URL: GPT, https://chatgpt.com/g/g-67abc78885a88191b2d67f94fd60dc97-tnfr-resonant-fractal-nature-theory
10
10
  Keywords: TNFR,complex systems,fractals,resonance,networks,structural dynamics,structural analysis
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -28,23 +28,47 @@ Requires-Dist: cachetools>=5
28
28
  Requires-Dist: typing-extensions>=4.4; python_version < "3.10"
29
29
  Provides-Extra: numpy
30
30
  Requires-Dist: numpy>=1.24; extra == "numpy"
31
+ Provides-Extra: jax
32
+ Requires-Dist: jax>=0.4; extra == "jax"
33
+ Provides-Extra: torch
34
+ Requires-Dist: torch>=2.1; extra == "torch"
31
35
  Provides-Extra: yaml
32
36
  Requires-Dist: pyyaml>=6.0; extra == "yaml"
33
37
  Provides-Extra: orjson
34
38
  Requires-Dist: orjson>=3; extra == "orjson"
39
+ Provides-Extra: viz
40
+ Requires-Dist: matplotlib>=3.7; extra == "viz"
41
+ Provides-Extra: docs
42
+ Requires-Dist: sphinx>=7.2; extra == "docs"
43
+ Requires-Dist: sphinx-autodoc-typehints>=1.25; extra == "docs"
44
+ Requires-Dist: myst-parser>=2.0; extra == "docs"
45
+ Requires-Dist: nbsphinx>=0.9; extra == "docs"
46
+ Requires-Dist: sphinx-rtd-theme>=1.3; extra == "docs"
47
+ Requires-Dist: sphinxcontrib-mermaid>=0.9; extra == "docs"
48
+ Requires-Dist: ipykernel>=6; extra == "docs"
49
+ Requires-Dist: nbconvert>=7.16; extra == "docs"
50
+ Requires-Dist: pypandoc-binary>=1.14; extra == "docs"
35
51
  Provides-Extra: test
36
52
  Requires-Dist: pytest>=7; extra == "test"
37
53
  Requires-Dist: pytest-benchmark>=4; extra == "test"
38
54
  Requires-Dist: pydocstyle>=6; extra == "test"
39
55
  Requires-Dist: coverage>=7; extra == "test"
56
+ Requires-Dist: hypothesis>=6; extra == "test"
57
+ Requires-Dist: hypothesis-networkx>=0.3; extra == "test"
40
58
  Requires-Dist: flake8>=5; extra == "test"
41
59
  Requires-Dist: flake8-pyproject>=1.2; extra == "test"
42
60
  Requires-Dist: vulture>=2; extra == "test"
61
+ Requires-Dist: matplotlib>=3.7; extra == "test"
43
62
  Provides-Extra: typecheck
44
63
  Requires-Dist: mypy>=1.8; extra == "typecheck"
45
64
  Requires-Dist: networkx-stubs>=0.0.1; extra == "typecheck"
46
65
  Requires-Dist: types-cachetools>=6.0.0.0; extra == "typecheck"
47
66
  Requires-Dist: numpy>=1.24; extra == "typecheck"
67
+ Provides-Extra: release
68
+ Requires-Dist: python-semantic-release<11,>=10.4; extra == "release"
69
+ Requires-Dist: setuptools-scm<9,>=8; extra == "release"
70
+ Requires-Dist: build>=1; extra == "release"
71
+ Requires-Dist: towncrier>=23; extra == "release"
48
72
  Dynamic: license-file
49
73
 
50
74
  # TNFR Python Engine
@@ -72,31 +96,51 @@ Install from PyPI (Python ≥ 3.9):
72
96
  pip install tnfr
73
97
  ```
74
98
 
75
- Then follow the [quickstart guide](docs/getting-started/quickstart.md) for Python and CLI
99
+ Then follow the [quickstart guide](docs/source/getting-started/quickstart.md) for Python and CLI
76
100
  walkthroughs plus optional dependency caching helpers.
77
101
 
102
+ ## CLI profiling helpers
103
+
104
+ Generate Sense Index and ΔNFR profiling artefacts directly from the CLI with the
105
+ ``profile-pipeline`` subcommand. The helper reproduces the performance benchmark that
106
+ captures vectorised and fallback execution traces for the full pipeline:
107
+
108
+ ```bash
109
+ tnfr profile-pipeline \
110
+ --nodes 120 --edge-probability 0.28 --loops 3 \
111
+ --si-chunk-sizes auto 48 --dnfr-chunk-sizes auto \
112
+ --si-workers auto --dnfr-workers auto \
113
+ --output-dir profiles/pipeline
114
+ ```
115
+
116
+ The command writes ``.pstats`` and JSON summaries for each configuration/mode pair, making
117
+ it easy to inspect hot paths with :mod:`pstats`, Snakeviz, or downstream tooling.
118
+
78
119
  ## Documentation map
79
120
 
80
- - [Documentation index](docs/index.md) — navigation hub for API chapters and examples.
81
- - [API overview](docs/api/overview.md) — package map, invariants, and structural data flow.
82
- - [Structural operators](docs/api/operators.md) — canonical grammar, key concepts, and typical
121
+ - [Documentation index](docs/source/home.md) — navigation hub for API chapters and examples.
122
+ - [API overview](docs/source/api/overview.md) — package map, invariants, and structural data flow.
123
+ - [Structural operators](docs/source/api/operators.md) — canonical grammar, key concepts, and typical
83
124
  workflows.
84
- - [Telemetry & utilities](docs/api/telemetry.md) — coherence metrics, trace capture, locking,
125
+ - [Telemetry & utilities](docs/source/api/telemetry.md) — coherence metrics, trace capture, locking,
85
126
  and helper facades.
86
- - [Examples](docs/examples/README.md) — runnable scenarios, CLI artefacts, and token legend.
127
+ - [Examples](docs/source/examples/README.md) — runnable scenarios, CLI artefacts, and token legend.
87
128
 
88
129
  ## Documentation build workflow
89
130
 
90
- Netlify publishes the documentation with [MkDocs](https://www.mkdocs.org/) so the generated
91
- site preserves the canonical TNFR structure. The same steps can be executed locally:
131
+ Netlify now renders the documentation with [Sphinx](https://www.sphinx-doc.org/) so MyST Markdown,
132
+ doctests, and notebooks share a single pipeline. Reproduce the hosted site locally as follows:
92
133
 
93
134
  1. Create and activate a virtual environment (e.g. `python -m venv .venv && source .venv/bin/activate`).
94
- 2. Install the documentation toolchain: `python -m pip install -r docs/requirements.txt`.
95
- 3. Preview changes live with `mkdocs serve` or reproduce the Netlify pipeline with
96
- `mkdocs build`, which writes the static site to the `site/` directory.
135
+ 2. Install the documentation toolchain and project extras:
136
+ `python -m pip install -r docs/requirements.txt && python -m pip install -e .[docs]`.
137
+ 3. Execute the doctest suite with `sphinx-build -b doctest docs/source docs/_build/doctest` to ensure
138
+ structural snippets remain coherent.
139
+ 4. Generate the HTML site with `make docs`, which wraps `sphinx-build -b html docs/source docs/_build/html`.
97
140
 
98
- The Netlify build (`netlify.toml`) runs `python -m pip install -r docs/requirements.txt && mkdocs build`
99
- and publishes the resulting `site/` directory, ensuring the hosted documentation matches local builds.
141
+ The Netlify build (`netlify.toml`) runs `python -m pip install -r docs/requirements.txt && make docs`
142
+ and publishes the resulting `docs/_build/html` directory, keeping the hosted documentation aligned with
143
+ local verification runs.
100
144
 
101
145
  ## Local development
102
146
 
@@ -122,11 +166,11 @@ integration.
122
166
 
123
167
  ## Migration notes
124
168
 
125
- - **Si dispersion keys:** Replace any remaining ``dSi_ddisp_fase`` entries in graph payloads
126
- or configuration files with the English ``dSi_dphase_disp`` key before upgrading. The
127
- runtime now raises :class:`ValueError` listing any unexpected sensitivity keys, and
169
+ - **Si dispersion keys:** Ensure graph payloads and configuration files use the canonical
170
+ ``dSi_dphase_disp`` attribute for Si dispersion sensitivity before upgrading. The runtime now
171
+ raises :class:`ValueError` listing any unexpected sensitivity keys, and
128
172
  :func:`tnfr.metrics.sense_index.compute_Si_node` rejects unknown keyword arguments.
129
- - Refer to the [release notes](docs/releases.md#1100-si-dispersion-legacy-keys-removed) for
173
+ - Refer to the [release notes](docs/source/releases.md#1100-si-dispersion-legacy-keys-removed) for
130
174
  a migration snippet that rewrites stored graphs in place prior to running the new version.
131
175
 
132
176
  ## Licensing
@@ -23,31 +23,51 @@ Install from PyPI (Python ≥ 3.9):
23
23
  pip install tnfr
24
24
  ```
25
25
 
26
- Then follow the [quickstart guide](docs/getting-started/quickstart.md) for Python and CLI
26
+ Then follow the [quickstart guide](docs/source/getting-started/quickstart.md) for Python and CLI
27
27
  walkthroughs plus optional dependency caching helpers.
28
28
 
29
+ ## CLI profiling helpers
30
+
31
+ Generate Sense Index and ΔNFR profiling artefacts directly from the CLI with the
32
+ ``profile-pipeline`` subcommand. The helper reproduces the performance benchmark that
33
+ captures vectorised and fallback execution traces for the full pipeline:
34
+
35
+ ```bash
36
+ tnfr profile-pipeline \
37
+ --nodes 120 --edge-probability 0.28 --loops 3 \
38
+ --si-chunk-sizes auto 48 --dnfr-chunk-sizes auto \
39
+ --si-workers auto --dnfr-workers auto \
40
+ --output-dir profiles/pipeline
41
+ ```
42
+
43
+ The command writes ``.pstats`` and JSON summaries for each configuration/mode pair, making
44
+ it easy to inspect hot paths with :mod:`pstats`, Snakeviz, or downstream tooling.
45
+
29
46
  ## Documentation map
30
47
 
31
- - [Documentation index](docs/index.md) — navigation hub for API chapters and examples.
32
- - [API overview](docs/api/overview.md) — package map, invariants, and structural data flow.
33
- - [Structural operators](docs/api/operators.md) — canonical grammar, key concepts, and typical
48
+ - [Documentation index](docs/source/home.md) — navigation hub for API chapters and examples.
49
+ - [API overview](docs/source/api/overview.md) — package map, invariants, and structural data flow.
50
+ - [Structural operators](docs/source/api/operators.md) — canonical grammar, key concepts, and typical
34
51
  workflows.
35
- - [Telemetry & utilities](docs/api/telemetry.md) — coherence metrics, trace capture, locking,
52
+ - [Telemetry & utilities](docs/source/api/telemetry.md) — coherence metrics, trace capture, locking,
36
53
  and helper facades.
37
- - [Examples](docs/examples/README.md) — runnable scenarios, CLI artefacts, and token legend.
54
+ - [Examples](docs/source/examples/README.md) — runnable scenarios, CLI artefacts, and token legend.
38
55
 
39
56
  ## Documentation build workflow
40
57
 
41
- Netlify publishes the documentation with [MkDocs](https://www.mkdocs.org/) so the generated
42
- site preserves the canonical TNFR structure. The same steps can be executed locally:
58
+ Netlify now renders the documentation with [Sphinx](https://www.sphinx-doc.org/) so MyST Markdown,
59
+ doctests, and notebooks share a single pipeline. Reproduce the hosted site locally as follows:
43
60
 
44
61
  1. Create and activate a virtual environment (e.g. `python -m venv .venv && source .venv/bin/activate`).
45
- 2. Install the documentation toolchain: `python -m pip install -r docs/requirements.txt`.
46
- 3. Preview changes live with `mkdocs serve` or reproduce the Netlify pipeline with
47
- `mkdocs build`, which writes the static site to the `site/` directory.
62
+ 2. Install the documentation toolchain and project extras:
63
+ `python -m pip install -r docs/requirements.txt && python -m pip install -e .[docs]`.
64
+ 3. Execute the doctest suite with `sphinx-build -b doctest docs/source docs/_build/doctest` to ensure
65
+ structural snippets remain coherent.
66
+ 4. Generate the HTML site with `make docs`, which wraps `sphinx-build -b html docs/source docs/_build/html`.
48
67
 
49
- The Netlify build (`netlify.toml`) runs `python -m pip install -r docs/requirements.txt && mkdocs build`
50
- and publishes the resulting `site/` directory, ensuring the hosted documentation matches local builds.
68
+ The Netlify build (`netlify.toml`) runs `python -m pip install -r docs/requirements.txt && make docs`
69
+ and publishes the resulting `docs/_build/html` directory, keeping the hosted documentation aligned with
70
+ local verification runs.
51
71
 
52
72
  ## Local development
53
73
 
@@ -73,11 +93,11 @@ integration.
73
93
 
74
94
  ## Migration notes
75
95
 
76
- - **Si dispersion keys:** Replace any remaining ``dSi_ddisp_fase`` entries in graph payloads
77
- or configuration files with the English ``dSi_dphase_disp`` key before upgrading. The
78
- runtime now raises :class:`ValueError` listing any unexpected sensitivity keys, and
96
+ - **Si dispersion keys:** Ensure graph payloads and configuration files use the canonical
97
+ ``dSi_dphase_disp`` attribute for Si dispersion sensitivity before upgrading. The runtime now
98
+ raises :class:`ValueError` listing any unexpected sensitivity keys, and
79
99
  :func:`tnfr.metrics.sense_index.compute_Si_node` rejects unknown keyword arguments.
80
- - Refer to the [release notes](docs/releases.md#1100-si-dispersion-legacy-keys-removed) for
100
+ - Refer to the [release notes](docs/source/releases.md#1100-si-dispersion-legacy-keys-removed) for
81
101
  a migration snippet that rewrites stored graphs in place prior to running the new version.
82
102
 
83
103
  ## Licensing
@@ -33,16 +33,33 @@ dependencies = [
33
33
 
34
34
  [project.optional-dependencies]
35
35
  numpy = ["numpy>=1.24"]
36
+ jax = ["jax>=0.4"]
37
+ torch = ["torch>=2.1"]
36
38
  yaml = ["pyyaml>=6.0"]
37
39
  orjson = ["orjson>=3"]
40
+ viz = ["matplotlib>=3.7"]
41
+ docs = [
42
+ "sphinx>=7.2",
43
+ "sphinx-autodoc-typehints>=1.25",
44
+ "myst-parser>=2.0",
45
+ "nbsphinx>=0.9",
46
+ "sphinx-rtd-theme>=1.3",
47
+ "sphinxcontrib-mermaid>=0.9",
48
+ "ipykernel>=6",
49
+ "nbconvert>=7.16",
50
+ "pypandoc-binary>=1.14",
51
+ ]
38
52
  test = [
39
53
  "pytest>=7",
40
54
  "pytest-benchmark>=4",
41
55
  "pydocstyle>=6",
42
56
  "coverage>=7",
57
+ "hypothesis>=6",
58
+ "hypothesis-networkx>=0.3",
43
59
  "flake8>=5",
44
60
  "flake8-pyproject>=1.2",
45
61
  "vulture>=2",
62
+ "matplotlib>=3.7",
46
63
  ]
47
64
  typecheck = [
48
65
  "mypy>=1.8",
@@ -50,6 +67,12 @@ typecheck = [
50
67
  "types-cachetools>=6.0.0.0",
51
68
  "numpy>=1.24",
52
69
  ]
70
+ release = [
71
+ "python-semantic-release>=10.4,<11",
72
+ "setuptools-scm>=8,<9",
73
+ "build>=1",
74
+ "towncrier>=23",
75
+ ]
53
76
 
54
77
  [project.scripts]
55
78
  tnfr = "tnfr.cli:main"
@@ -57,13 +80,43 @@ tnfr = "tnfr.cli:main"
57
80
  [project.urls]
58
81
  Homepage = "https://pypi.org/project/tnfr/"
59
82
  Repository = "https://github.com/fermga/TNFR-Python-Engine"
60
- GPT = "https://chatgpt.com/g/g-67abc78885a88191b2d67f94fd60dc97-tnfr-teoria-de-la-naturaleza-fractal-resonante"
61
-
62
- [tool.setuptools.dynamic]
63
- version = { attr = "tnfr._version.__version__" }
83
+ GPT = "https://chatgpt.com/g/g-67abc78885a88191b2d67f94fd60dc97-tnfr-resonant-fractal-nature-theory"
64
84
 
65
85
  [tool.setuptools.package-data]
66
- tnfr = ["py.typed"]
86
+ tnfr = ["py.typed", "schemas/*.json"]
87
+
88
+ [tool.setuptools_scm]
89
+ tag_regex = '^v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)$'
90
+ local_scheme = "no-local-version"
91
+ write_to = "src/tnfr/_generated_version.py"
92
+
93
+ [tool.semantic_release]
94
+ version_source = "tag"
95
+ commit_parser = "conventional"
96
+ allow_zero_version = false
97
+ major_on_zero = false
98
+ tag_format = "v{version}"
99
+
100
+ [tool.semantic_release.branches.main]
101
+ match = "^main$"
102
+ prerelease = false
103
+
104
+ [tool.semantic_release.changelog]
105
+ template_dir = "meta/semantic_release/templates"
106
+ mode = "update"
107
+ changelog_file = ""
108
+
109
+ [tool.semantic_release.changelog.default_templates]
110
+ mask_initial_release = true
111
+
112
+ [tool.semantic_release.commit_parser_options]
113
+ minor_tags = ["feat", "structure"]
114
+ patch_tags = ["fix", "perf", "refactor", "docs", "test", "build", "ci", "style", "chore"]
115
+ other_allowed_tags = ["revert", "docs", "test", "build", "ci", "style", "refactor", "perf", "chore"]
116
+ allowed_tags = ["feat", "fix", "perf", "refactor", "docs", "test", "build", "ci", "style", "chore", "structure", "revert"]
117
+ default_bump_level = 0
118
+ parse_squash_commits = true
119
+ ignore_merge_commits = true
67
120
 
68
121
  [tool.black]
69
122
  line-length = 88
@@ -79,12 +132,25 @@ max-line-length = 88
79
132
  ignore = ["E501", "W503"]
80
133
  exclude = ["benchmarks/"]
81
134
 
135
+ [tool.pydocstyle]
136
+ convention = "numpy"
137
+ add-ignore = [
138
+ "D202", # Allow blank line after docstring where needed for readability.
139
+ ]
140
+
141
+ [tool.tnfr.language_check]
142
+ exclude = [
143
+ "TNFR.pdf",
144
+ "benchmarks/**/*.pdf",
145
+ ]
146
+
82
147
  [tool.pytest.ini_options]
83
148
  pythonpath = ["src"]
84
149
  addopts = "-m 'not slow' --benchmark-skip"
85
150
  markers = [
86
151
  "slow: marks tests as slow (deselect with '-m \"not slow\"')",
87
152
  "benchmarks: run with 'pytest benchmarks --benchmark-only' to execute the benchmark suite",
153
+ "stress: high-load deterministic stress coverage (select with '-m \"stress\"')",
88
154
  ]
89
155
 
90
156
  [tool.mypy]
@@ -111,5 +177,5 @@ ignore_missing_imports = true
111
177
 
112
178
 
113
179
  [build-system]
114
- requires = ["setuptools>=78.1.1", "wheel"]
180
+ requires = ["setuptools>=78.1.1", "wheel", "setuptools-scm>=8"]
115
181
  build-backend = "setuptools.build_meta"
@@ -43,7 +43,6 @@ from importlib import import_module, metadata
43
43
  from importlib.metadata import PackageNotFoundError
44
44
  from typing import Any, Callable, NoReturn
45
45
 
46
-
47
46
  EXPORT_DEPENDENCIES: dict[str, dict[str, tuple[str, ...]]] = {
48
47
  "step": {
49
48
  "submodules": ("tnfr.dynamics",),
@@ -76,6 +75,21 @@ EXPORT_DEPENDENCIES: dict[str, dict[str, tuple[str, ...]]] = {
76
75
  ),
77
76
  "third_party": ("networkx",),
78
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
+ },
79
93
  "run_sequence": {
80
94
  "submodules": (
81
95
  "tnfr.structural",
@@ -87,6 +101,27 @@ EXPORT_DEPENDENCIES: dict[str, dict[str, tuple[str, ...]]] = {
87
101
  ),
88
102
  "third_party": ("networkx",),
89
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
+ },
90
125
  }
91
126
 
92
127
 
@@ -184,7 +219,9 @@ def _validate_export_dependencies() -> None:
184
219
  f"helper '{export_name}' is missing '{key}' dependencies in EXPORT_DEPENDENCIES"
185
220
  )
186
221
 
187
- missing_exports = manifest_names.difference(export_names).difference(_MISSING_EXPORTS)
222
+ missing_exports = manifest_names.difference(export_names).difference(
223
+ _MISSING_EXPORTS
224
+ )
188
225
  for manifest_only in sorted(missing_exports):
189
226
  entry = manifest[manifest_only]
190
227
  if not isinstance(entry, dict):
@@ -235,7 +272,12 @@ _assign_exports("dynamics", ("step", "run"))
235
272
  _HAS_PREPARE_NETWORK = _assign_exports("ontosim", ("prepare_network",))
236
273
 
237
274
 
238
- _HAS_RUN_SEQUENCE = _assign_exports("structural", ("create_nfr", "run_sequence"))
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"))
239
281
 
240
282
 
241
283
  def _emit_missing_dependency_warning() -> None:
@@ -261,10 +303,13 @@ __all__ = [
261
303
  "run",
262
304
  "prepare_network",
263
305
  "create_nfr",
306
+ "get_hz_bridge",
307
+ "hz_str_to_hz",
308
+ "hz_to_hz_str",
264
309
  ]
265
310
 
266
- if _HAS_RUN_SEQUENCE:
267
- __all__.append("run_sequence")
311
+ if _HAS_STRUCTURAL_EXPORTS:
312
+ __all__.extend(["run_sequence", "create_math_nfr"])
268
313
 
269
314
 
270
315
  _validate_export_dependencies()
@@ -15,25 +15,18 @@ _MISSING_EXPORTS: dict[str, dict[str, Any]]
15
15
  __version__: str
16
16
  __all__: list[str]
17
17
 
18
-
19
18
  class ExportDependencyError(RuntimeError):
20
19
  """Raised when the export dependency manifest is inconsistent."""
21
20
 
22
-
23
21
  def _is_internal_import_error(exc: ImportError) -> bool: ...
24
-
25
22
  def _missing_dependency(
26
23
  name: str,
27
24
  exc: ImportError,
28
25
  *,
29
26
  module: str | None = ...,
30
27
  ) -> Callable[..., NoReturn]: ...
31
-
32
-
33
28
  def _validate_export_dependencies() -> None: ...
34
-
35
29
  def _assign_exports(module: str, names: tuple[str, ...]) -> bool: ...
36
-
37
30
  def _emit_missing_dependency_warning() -> None: ...
38
31
 
39
32
  _HAS_PREPARE_NETWORK: bool
@@ -8,4 +8,3 @@ except (ImportError, AttributeError): # pragma: no cover - Python < 3.10
8
8
  from typing_extensions import TypeAlias # type: ignore[assignment]
9
9
 
10
10
  __all__ = ["TypeAlias"]
11
-
@@ -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
@@ -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()
@@ -7,6 +7,7 @@ alias-based attribute access. Legacy wrappers ``alias_get`` and
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
+
10
11
  from collections import defaultdict
11
12
  from collections.abc import Iterable, Mapping, MutableMapping, Sized
12
13
  from dataclasses import dataclass
@@ -24,14 +25,10 @@ from typing import (
24
25
  cast,
25
26
  )
26
27
 
27
- from .constants import get_aliases
28
+ from .constants.aliases import ALIAS_DNFR, ALIAS_THETA, ALIAS_VF
28
29
  from .types import FloatArray, NodeId
29
30
  from .utils import convert_value
30
31
 
31
- ALIAS_VF = get_aliases("VF")
32
- ALIAS_DNFR = get_aliases("DNFR")
33
- ALIAS_THETA = get_aliases("THETA")
34
-
35
32
  if TYPE_CHECKING: # pragma: no cover
36
33
  import networkx
37
34
 
@@ -133,6 +130,8 @@ class AliasAccessor(Generic[T]):
133
130
  log_level: int | None = None,
134
131
  conv: Callable[[Any], T] | None = None,
135
132
  ) -> Optional[T]:
133
+ """Return ``value`` for the first alias present in ``d``."""
134
+
136
135
  aliases, conv, default = self._prepare(aliases, conv, default)
137
136
  cache_key, key = self._resolve_cache_key(d, aliases)
138
137
  if key is not None:
@@ -169,6 +168,8 @@ class AliasAccessor(Generic[T]):
169
168
  value: Any,
170
169
  conv: Callable[[Any], T] | None = None,
171
170
  ) -> T:
171
+ """Write ``value`` under the first matching alias and cache the choice."""
172
+
172
173
  aliases, conv, _ = self._prepare(aliases, conv)
173
174
  cache_key, key = self._resolve_cache_key(d, aliases)
174
175
  if key is not None:
@@ -269,7 +270,9 @@ def collect_attr(
269
270
  return float(get_attr(G.nodes[node], aliases, default))
270
271
 
271
272
  if np is not None:
272
- values: FloatArray = np.fromiter((_value(n) for n in nodes_iter), float, count=size)
273
+ values: FloatArray = np.fromiter(
274
+ (_value(n) for n in nodes_iter), float, count=size
275
+ )
273
276
  return values
274
277
  return [_value(n) for n in nodes_iter]
275
278
 
@@ -297,7 +300,9 @@ def collect_theta_attr(
297
300
  return float(get_theta_attr(G.nodes[node], default))
298
301
 
299
302
  if np is not None:
300
- values: FloatArray = np.fromiter((_value(n) for n in nodes_iter), float, count=size)
303
+ values: FloatArray = np.fromiter(
304
+ (_value(n) for n in nodes_iter), float, count=size
305
+ )
301
306
  return values
302
307
 
303
308
  return [_value(n) for n in nodes_iter]
@@ -445,9 +450,7 @@ def _update_cached_abs_max(
445
450
  cur_node = cast(Hashable | None, G.graph.get(node_key))
446
451
 
447
452
  if val >= cur:
448
- return _compute_abs_max_result(
449
- G, aliases, key=key, candidate=(n, val)
450
- )
453
+ return _compute_abs_max_result(G, aliases, key=key, candidate=(n, val))
451
454
  if cur_node == n:
452
455
  return _compute_abs_max_result(G, aliases, key=key)
453
456
  return AbsMaxResult(max_value=cur, node=cur_node)
@@ -518,9 +521,7 @@ def set_scalar(
518
521
  return set_attr_and_cache(G, n, alias, value, cache=cache, extra=extra)
519
522
 
520
523
 
521
- def _increment_trig_version(
522
- G: "networkx.Graph", _: Hashable, __: float
523
- ) -> None:
524
+ def _increment_trig_version(G: "networkx.Graph", _: Hashable, __: float) -> None:
524
525
  """Increment cached trig version to invalidate trig caches."""
525
526
  g = G.graph
526
527
  g["_trig_version"] = int(g.get("_trig_version", 0)) + 1