tnfr 4.5.2__tar.gz → 6.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.
- tnfr-6.0.0/PKG-INFO +135 -0
- tnfr-6.0.0/README.md +86 -0
- tnfr-6.0.0/pyproject.toml +115 -0
- tnfr-6.0.0/src/tnfr/__init__.py +270 -0
- tnfr-6.0.0/src/tnfr/__init__.pyi +40 -0
- tnfr-6.0.0/src/tnfr/_compat.py +11 -0
- tnfr-6.0.0/src/tnfr/_version.py +7 -0
- tnfr-6.0.0/src/tnfr/_version.pyi +7 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/alias.py +106 -21
- tnfr-6.0.0/src/tnfr/alias.pyi +140 -0
- tnfr-6.0.0/src/tnfr/cache.py +732 -0
- tnfr-6.0.0/src/tnfr/cache.pyi +232 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/callback_utils.py +2 -9
- tnfr-6.0.0/src/tnfr/callback_utils.pyi +105 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/cli/__init__.py +21 -7
- tnfr-6.0.0/src/tnfr/cli/__init__.pyi +47 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/cli/arguments.py +42 -20
- tnfr-6.0.0/src/tnfr/cli/arguments.pyi +33 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/cli/execution.py +54 -20
- tnfr-6.0.0/src/tnfr/cli/execution.pyi +80 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/cli/utils.py +0 -2
- tnfr-6.0.0/src/tnfr/cli/utils.pyi +8 -0
- tnfr-6.0.0/src/tnfr/config/__init__.py +12 -0
- tnfr-6.0.0/src/tnfr/config/__init__.pyi +8 -0
- tnfr-4.5.2/src/tnfr/constants_glyphs.py → tnfr-6.0.0/src/tnfr/config/constants.py +26 -20
- tnfr-6.0.0/src/tnfr/config/constants.pyi +12 -0
- tnfr-4.5.2/src/tnfr/config.py → tnfr-6.0.0/src/tnfr/config/init.py +11 -7
- tnfr-6.0.0/src/tnfr/config/init.pyi +8 -0
- tnfr-6.0.0/src/tnfr/config/operator_names.py +106 -0
- tnfr-6.0.0/src/tnfr/config/operator_names.pyi +28 -0
- tnfr-6.0.0/src/tnfr/config/presets.py +104 -0
- tnfr-6.0.0/src/tnfr/config/presets.pyi +7 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/constants/__init__.py +78 -24
- tnfr-6.0.0/src/tnfr/constants/__init__.pyi +104 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/constants/core.py +1 -2
- tnfr-6.0.0/src/tnfr/constants/core.pyi +17 -0
- tnfr-6.0.0/src/tnfr/constants/init.pyi +12 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/constants/metric.py +4 -12
- tnfr-6.0.0/src/tnfr/constants/metric.pyi +19 -0
- tnfr-6.0.0/src/tnfr/constants_glyphs.py +16 -0
- tnfr-6.0.0/src/tnfr/constants_glyphs.pyi +12 -0
- tnfr-6.0.0/src/tnfr/dynamics/__init__.py +136 -0
- tnfr-6.0.0/src/tnfr/dynamics/__init__.pyi +83 -0
- tnfr-6.0.0/src/tnfr/dynamics/adaptation.py +201 -0
- tnfr-6.0.0/src/tnfr/dynamics/aliases.py +22 -0
- tnfr-6.0.0/src/tnfr/dynamics/coordination.py +343 -0
- tnfr-6.0.0/src/tnfr/dynamics/dnfr.py +2315 -0
- tnfr-6.0.0/src/tnfr/dynamics/dnfr.pyi +33 -0
- tnfr-6.0.0/src/tnfr/dynamics/integrators.py +561 -0
- tnfr-6.0.0/src/tnfr/dynamics/integrators.pyi +35 -0
- tnfr-6.0.0/src/tnfr/dynamics/runtime.py +521 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/dynamics/sampling.py +8 -5
- tnfr-6.0.0/src/tnfr/dynamics/sampling.pyi +7 -0
- tnfr-6.0.0/src/tnfr/dynamics/selectors.py +680 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/execution.py +56 -41
- tnfr-6.0.0/src/tnfr/execution.pyi +65 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/flatten.py +7 -7
- tnfr-6.0.0/src/tnfr/flatten.pyi +28 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/gamma.py +54 -37
- tnfr-6.0.0/src/tnfr/gamma.pyi +40 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/glyph_history.py +85 -38
- tnfr-6.0.0/src/tnfr/glyph_history.pyi +53 -0
- tnfr-6.0.0/src/tnfr/grammar.py +25 -0
- tnfr-6.0.0/src/tnfr/grammar.pyi +13 -0
- tnfr-6.0.0/src/tnfr/helpers/__init__.py +151 -0
- tnfr-6.0.0/src/tnfr/helpers/__init__.pyi +66 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/helpers/numeric.py +1 -0
- tnfr-6.0.0/src/tnfr/helpers/numeric.pyi +12 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/immutable.py +55 -19
- tnfr-6.0.0/src/tnfr/immutable.pyi +37 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/initialization.py +12 -10
- tnfr-6.0.0/src/tnfr/initialization.pyi +73 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/io.py +99 -34
- tnfr-6.0.0/src/tnfr/io.pyi +11 -0
- tnfr-6.0.0/src/tnfr/locking.pyi +7 -0
- tnfr-6.0.0/src/tnfr/metrics/__init__.pyi +20 -0
- tnfr-6.0.0/src/tnfr/metrics/coherence.py +1469 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/metrics/common.py +1 -3
- tnfr-6.0.0/src/tnfr/metrics/common.pyi +15 -0
- tnfr-6.0.0/src/tnfr/metrics/core.py +259 -0
- tnfr-6.0.0/src/tnfr/metrics/core.pyi +13 -0
- tnfr-6.0.0/src/tnfr/metrics/diagnosis.py +840 -0
- tnfr-6.0.0/src/tnfr/metrics/diagnosis.pyi +89 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/metrics/export.py +27 -13
- tnfr-6.0.0/src/tnfr/metrics/glyph_timing.py +369 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/metrics/reporting.py +22 -18
- tnfr-6.0.0/src/tnfr/metrics/reporting.pyi +12 -0
- tnfr-6.0.0/src/tnfr/metrics/sense_index.py +294 -0
- tnfr-6.0.0/src/tnfr/metrics/sense_index.pyi +9 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/metrics/trig.py +53 -18
- tnfr-6.0.0/src/tnfr/metrics/trig.pyi +12 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/metrics/trig_cache.py +3 -7
- tnfr-6.0.0/src/tnfr/metrics/trig_cache.pyi +10 -0
- tnfr-6.0.0/src/tnfr/node.py +280 -0
- tnfr-6.0.0/src/tnfr/node.pyi +161 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/observers.py +44 -30
- tnfr-6.0.0/src/tnfr/observers.pyi +46 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/ontosim.py +14 -13
- tnfr-6.0.0/src/tnfr/ontosim.pyi +33 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/operators/__init__.py +84 -52
- tnfr-6.0.0/src/tnfr/operators/__init__.pyi +31 -0
- tnfr-6.0.0/src/tnfr/operators/definitions.py +181 -0
- tnfr-6.0.0/src/tnfr/operators/definitions.pyi +92 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/operators/jitter.py +86 -23
- tnfr-6.0.0/src/tnfr/operators/jitter.pyi +11 -0
- tnfr-6.0.0/src/tnfr/operators/registry.py +80 -0
- tnfr-6.0.0/src/tnfr/operators/registry.pyi +15 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/operators/remesh.py +141 -57
- tnfr-6.0.0/src/tnfr/presets.py +15 -0
- tnfr-6.0.0/src/tnfr/presets.pyi +7 -0
- tnfr-6.0.0/src/tnfr/py.typed +0 -0
- tnfr-6.0.0/src/tnfr/rng.py +440 -0
- tnfr-6.0.0/src/tnfr/rng.pyi +14 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/selector.py +24 -17
- tnfr-6.0.0/src/tnfr/selector.pyi +19 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/sense.py +55 -43
- tnfr-6.0.0/src/tnfr/sense.pyi +30 -0
- tnfr-6.0.0/src/tnfr/structural.py +106 -0
- tnfr-6.0.0/src/tnfr/structural.pyi +46 -0
- tnfr-6.0.0/src/tnfr/telemetry/__init__.py +13 -0
- tnfr-6.0.0/src/tnfr/telemetry/verbosity.py +37 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/tokens.py +3 -2
- tnfr-6.0.0/src/tnfr/tokens.pyi +41 -0
- tnfr-6.0.0/src/tnfr/trace.py +559 -0
- tnfr-6.0.0/src/tnfr/trace.pyi +68 -0
- tnfr-6.0.0/src/tnfr/types.py +383 -0
- tnfr-6.0.0/src/tnfr/types.pyi +145 -0
- tnfr-6.0.0/src/tnfr/utils/__init__.py +158 -0
- tnfr-6.0.0/src/tnfr/utils/__init__.pyi +133 -0
- {tnfr-4.5.2/src/tnfr → tnfr-6.0.0/src/tnfr/utils}/cache.py +316 -139
- tnfr-6.0.0/src/tnfr/utils/cache.pyi +156 -0
- tnfr-4.5.2/src/tnfr/collections_utils.py → tnfr-6.0.0/src/tnfr/utils/data.py +57 -90
- tnfr-6.0.0/src/tnfr/utils/data.pyi +73 -0
- tnfr-6.0.0/src/tnfr/utils/graph.py +87 -0
- tnfr-6.0.0/src/tnfr/utils/graph.pyi +10 -0
- tnfr-6.0.0/src/tnfr/utils/init.py +746 -0
- tnfr-6.0.0/src/tnfr/utils/init.pyi +85 -0
- tnfr-4.5.2/src/tnfr/json_utils.py → tnfr-6.0.0/src/tnfr/utils/io.py +13 -18
- tnfr-6.0.0/src/tnfr/utils/io.pyi +10 -0
- tnfr-6.0.0/src/tnfr/utils/validators.py +130 -0
- tnfr-6.0.0/src/tnfr/utils/validators.pyi +19 -0
- tnfr-6.0.0/src/tnfr/validation/__init__.py +25 -0
- tnfr-6.0.0/src/tnfr/validation/__init__.pyi +17 -0
- tnfr-6.0.0/src/tnfr/validation/compatibility.py +59 -0
- tnfr-6.0.0/src/tnfr/validation/compatibility.pyi +8 -0
- tnfr-6.0.0/src/tnfr/validation/grammar.py +149 -0
- tnfr-6.0.0/src/tnfr/validation/grammar.pyi +11 -0
- tnfr-6.0.0/src/tnfr/validation/rules.py +194 -0
- tnfr-6.0.0/src/tnfr/validation/rules.pyi +18 -0
- tnfr-6.0.0/src/tnfr/validation/syntax.py +151 -0
- tnfr-6.0.0/src/tnfr/validation/syntax.pyi +7 -0
- tnfr-6.0.0/src/tnfr.egg-info/PKG-INFO +135 -0
- tnfr-6.0.0/src/tnfr.egg-info/SOURCES.txt +160 -0
- tnfr-6.0.0/src/tnfr.egg-info/requires.txt +29 -0
- tnfr-4.5.2/PKG-INFO +0 -379
- tnfr-4.5.2/README.md +0 -344
- tnfr-4.5.2/pyproject.toml +0 -46
- tnfr-4.5.2/src/tnfr/__init__.py +0 -91
- tnfr-4.5.2/src/tnfr/dynamics/__init__.py +0 -658
- tnfr-4.5.2/src/tnfr/dynamics/dnfr.py +0 -733
- tnfr-4.5.2/src/tnfr/dynamics/integrators.py +0 -267
- tnfr-4.5.2/src/tnfr/grammar.py +0 -344
- tnfr-4.5.2/src/tnfr/graph_utils.py +0 -84
- tnfr-4.5.2/src/tnfr/helpers/__init__.py +0 -71
- tnfr-4.5.2/src/tnfr/import_utils.py +0 -228
- tnfr-4.5.2/src/tnfr/logging_utils.py +0 -116
- tnfr-4.5.2/src/tnfr/metrics/coherence.py +0 -829
- tnfr-4.5.2/src/tnfr/metrics/core.py +0 -101
- tnfr-4.5.2/src/tnfr/metrics/diagnosis.py +0 -234
- tnfr-4.5.2/src/tnfr/metrics/glyph_timing.py +0 -189
- tnfr-4.5.2/src/tnfr/metrics/sense_index.py +0 -120
- tnfr-4.5.2/src/tnfr/node.py +0 -257
- tnfr-4.5.2/src/tnfr/presets.py +0 -60
- tnfr-4.5.2/src/tnfr/rng.py +0 -254
- tnfr-4.5.2/src/tnfr/structural.py +0 -329
- tnfr-4.5.2/src/tnfr/trace.py +0 -369
- tnfr-4.5.2/src/tnfr/types.py +0 -44
- tnfr-4.5.2/src/tnfr/validators.py +0 -84
- tnfr-4.5.2/src/tnfr/value_utils.py +0 -59
- tnfr-4.5.2/src/tnfr.egg-info/PKG-INFO +0 -379
- tnfr-4.5.2/src/tnfr.egg-info/SOURCES.txt +0 -204
- tnfr-4.5.2/src/tnfr.egg-info/requires.txt +0 -15
- tnfr-4.5.2/tests/test_accumulate_cos_sin.py +0 -27
- tnfr-4.5.2/tests/test_add_edge_callbacks.py +0 -11
- tnfr-4.5.2/tests/test_add_edge_errors.py +0 -26
- tnfr-4.5.2/tests/test_add_edge_networkx.py +0 -55
- tnfr-4.5.2/tests/test_add_edge_versions.py +0 -28
- tnfr-4.5.2/tests/test_alias_accessor_usage.py +0 -143
- tnfr-4.5.2/tests/test_alias_get_default.py +0 -10
- tnfr-4.5.2/tests/test_alias_get_strict.py +0 -26
- tnfr-4.5.2/tests/test_alias_helpers_threadsafe.py +0 -19
- tnfr-4.5.2/tests/test_alias_iterable.py +0 -43
- tnfr-4.5.2/tests/test_alias_sequence.py +0 -22
- tnfr-4.5.2/tests/test_alias_set_error.py +0 -10
- tnfr-4.5.2/tests/test_cache_helpers.py +0 -46
- tnfr-4.5.2/tests/test_callback_errors_limit.py +0 -32
- tnfr-4.5.2/tests/test_canon.py +0 -38
- tnfr-4.5.2/tests/test_cli.py +0 -418
- tnfr-4.5.2/tests/test_cli_flatten_tokens.py +0 -6
- tnfr-4.5.2/tests/test_cli_history.py +0 -100
- tnfr-4.5.2/tests/test_cli_sanity.py +0 -100
- tnfr-4.5.2/tests/test_coherence_cache.py +0 -65
- tnfr-4.5.2/tests/test_collect_attr_generators.py +0 -18
- tnfr-4.5.2/tests/test_compute_Si_numpy_usage.py +0 -54
- tnfr-4.5.2/tests/test_compute_coherence.py +0 -73
- tnfr-4.5.2/tests/test_compute_theta_trig.py +0 -22
- tnfr-4.5.2/tests/test_config_apply.py +0 -88
- tnfr-4.5.2/tests/test_count_glyphs.py +0 -28
- tnfr-4.5.2/tests/test_defaults_integrity.py +0 -22
- tnfr-4.5.2/tests/test_diagnosis_state.py +0 -13
- tnfr-4.5.2/tests/test_dnfr_cache.py +0 -233
- tnfr-4.5.2/tests/test_dnfr_hooks.py +0 -41
- tnfr-4.5.2/tests/test_dnfr_precompute.py +0 -74
- tnfr-4.5.2/tests/test_dynamics_benchmark.py +0 -23
- tnfr-4.5.2/tests/test_dynamics_helpers.py +0 -129
- tnfr-4.5.2/tests/test_dynamics_run.py +0 -74
- tnfr-4.5.2/tests/test_dynamics_vectorized.py +0 -39
- tnfr-4.5.2/tests/test_edge_cases.py +0 -74
- tnfr-4.5.2/tests/test_edge_version_cache.py +0 -122
- tnfr-4.5.2/tests/test_edge_version_cache_limit.py +0 -13
- tnfr-4.5.2/tests/test_ensure_callbacks.py +0 -94
- tnfr-4.5.2/tests/test_ensure_collection.py +0 -100
- tnfr-4.5.2/tests/test_ensure_history_trim_performance.py +0 -28
- tnfr-4.5.2/tests/test_export_metrics.py +0 -93
- tnfr-4.5.2/tests/test_flatten_structure.py +0 -52
- tnfr-4.5.2/tests/test_freeze.py +0 -55
- tnfr-4.5.2/tests/test_gamma.py +0 -360
- tnfr-4.5.2/tests/test_get_attr_default.py +0 -62
- tnfr-4.5.2/tests/test_get_attr_strict.py +0 -41
- tnfr-4.5.2/tests/test_get_rng.py +0 -31
- tnfr-4.5.2/tests/test_get_rng_threadsafe.py +0 -27
- tnfr-4.5.2/tests/test_glyph_helpers.py +0 -25
- tnfr-4.5.2/tests/test_glyph_history_dict.py +0 -114
- tnfr-4.5.2/tests/test_glyph_history_windowing.py +0 -277
- tnfr-4.5.2/tests/test_grammar.py +0 -196
- tnfr-4.5.2/tests/test_history.py +0 -23
- tnfr-4.5.2/tests/test_history_counter.py +0 -54
- tnfr-4.5.2/tests/test_history_heap_cleanup.py +0 -58
- tnfr-4.5.2/tests/test_history_maxlen.py +0 -119
- tnfr-4.5.2/tests/test_history_methods.py +0 -31
- tnfr-4.5.2/tests/test_history_series.py +0 -54
- tnfr-4.5.2/tests/test_import_utils.py +0 -149
- tnfr-4.5.2/tests/test_initialization.py +0 -81
- tnfr-4.5.2/tests/test_inject_defaults_tuple.py +0 -16
- tnfr-4.5.2/tests/test_integrators.py +0 -102
- tnfr-4.5.2/tests/test_invariants.py +0 -105
- tnfr-4.5.2/tests/test_invoke_callbacks.py +0 -40
- tnfr-4.5.2/tests/test_is_immutable.py +0 -156
- tnfr-4.5.2/tests/test_json_utils.py +0 -161
- tnfr-4.5.2/tests/test_kahan_sum.py +0 -26
- tnfr-4.5.2/tests/test_knn_edges.py +0 -32
- tnfr-4.5.2/tests/test_list_mean.py +0 -18
- tnfr-4.5.2/tests/test_local_phase_sync.py +0 -29
- tnfr-4.5.2/tests/test_locking.py +0 -25
- tnfr-4.5.2/tests/test_logging_module.py +0 -71
- tnfr-4.5.2/tests/test_logging_threadsafe.py +0 -58
- tnfr-4.5.2/tests/test_make_rng.py +0 -52
- tnfr-4.5.2/tests/test_make_rng_threadsafe.py +0 -45
- tnfr-4.5.2/tests/test_merge_and_normalize_weights.py +0 -23
- tnfr-4.5.2/tests/test_metrics.py +0 -310
- tnfr-4.5.2/tests/test_min_max_range.py +0 -14
- tnfr-4.5.2/tests/test_missing_dependency_error_cache.py +0 -13
- tnfr-4.5.2/tests/test_nav.py +0 -33
- tnfr-4.5.2/tests/test_neighbor_phase_mean_missing_trig.py +0 -89
- tnfr-4.5.2/tests/test_neighbor_phase_mean_no_graph.py +0 -45
- tnfr-4.5.2/tests/test_neighbor_phase_mean_performance.py +0 -47
- tnfr-4.5.2/tests/test_neighbors_map_cache.py +0 -17
- tnfr-4.5.2/tests/test_node_all_nodes.py +0 -24
- tnfr-4.5.2/tests/test_node_from_graph_threadsafe.py +0 -29
- tnfr-4.5.2/tests/test_node_offset.py +0 -24
- tnfr-4.5.2/tests/test_node_sample.py +0 -137
- tnfr-4.5.2/tests/test_node_set_checksum.py +0 -111
- tnfr-4.5.2/tests/test_node_state_extra.py +0 -8
- tnfr-4.5.2/tests/test_node_weights.py +0 -56
- tnfr-4.5.2/tests/test_normalize_callback_entry.py +0 -30
- tnfr-4.5.2/tests/test_normalize_weights.py +0 -118
- tnfr-4.5.2/tests/test_numeric_helpers.py +0 -39
- tnfr-4.5.2/tests/test_observers.py +0 -240
- tnfr-4.5.2/tests/test_operator_factors.py +0 -117
- tnfr-4.5.2/tests/test_operators.py +0 -217
- tnfr-4.5.2/tests/test_optional_import.py +0 -23
- tnfr-4.5.2/tests/test_parse_tokens_errors.py +0 -35
- tnfr-4.5.2/tests/test_parse_toml.py +0 -27
- tnfr-4.5.2/tests/test_preparar_red.py +0 -15
- tnfr-4.5.2/tests/test_prepare_dnfr_data_performance.py +0 -37
- tnfr-4.5.2/tests/test_program.py +0 -313
- tnfr-4.5.2/tests/test_public_api.py +0 -28
- tnfr-4.5.2/tests/test_push_glyph.py +0 -34
- tnfr-4.5.2/tests/test_read_structured_file_errors.py +0 -192
- tnfr-4.5.2/tests/test_recent_glyph.py +0 -49
- tnfr-4.5.2/tests/test_register_callback.py +0 -115
- tnfr-4.5.2/tests/test_remesh.py +0 -106
- tnfr-4.5.2/tests/test_remesh_community.py +0 -32
- tnfr-4.5.2/tests/test_rng_base_seed.py +0 -126
- tnfr-4.5.2/tests/test_rng_for_step.py +0 -44
- tnfr-4.5.2/tests/test_safe_write.py +0 -79
- tnfr-4.5.2/tests/test_scenarios.py +0 -40
- tnfr-4.5.2/tests/test_selector_norms.py +0 -36
- tnfr-4.5.2/tests/test_selector_utils.py +0 -136
- tnfr-4.5.2/tests/test_sense.py +0 -140
- tnfr-4.5.2/tests/test_set_attr_error.py +0 -10
- tnfr-4.5.2/tests/test_si_helpers.py +0 -110
- tnfr-4.5.2/tests/test_stable_json.py +0 -26
- tnfr-4.5.2/tests/test_structural.py +0 -89
- tnfr-4.5.2/tests/test_topological_remesh.py +0 -141
- tnfr-4.5.2/tests/test_trace.py +0 -149
- tnfr-4.5.2/tests/test_trig_cache_reuse.py +0 -74
- tnfr-4.5.2/tests/test_update_tg_node.py +0 -39
- tnfr-4.5.2/tests/test_update_tg_performance.py +0 -88
- tnfr-4.5.2/tests/test_validate_aliases.py +0 -30
- tnfr-4.5.2/tests/test_validate_window.py +0 -17
- tnfr-4.5.2/tests/test_validators.py +0 -120
- tnfr-4.5.2/tests/test_value_utils.py +0 -31
- tnfr-4.5.2/tests/test_vf_coherencia.py +0 -33
- tnfr-4.5.2/tests/test_vf_dnfr_max_update.py +0 -73
- tnfr-4.5.2/tests/test_warn_failure_emit.py +0 -62
- {tnfr-4.5.2 → tnfr-6.0.0}/LICENSE.md +0 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/setup.cfg +0 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/constants/init.py +0 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/locking.py +0 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr/metrics/__init__.py +0 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr.egg-info/dependency_links.txt +0 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr.egg-info/entry_points.txt +0 -0
- {tnfr-4.5.2 → tnfr-6.0.0}/src/tnfr.egg-info/top_level.txt +0 -0
tnfr-6.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tnfr
|
|
3
|
+
Version: 6.0.0
|
|
4
|
+
Summary: Modular structural-based dynamics on networks.
|
|
5
|
+
Author: fmg
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://pypi.org/project/tnfr/
|
|
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
|
|
10
|
+
Keywords: TNFR,complex systems,fractals,resonance,networks,structural dynamics,structural analysis
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Intended Audience :: Science/Research
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE.md
|
|
26
|
+
Requires-Dist: networkx>=2.6
|
|
27
|
+
Requires-Dist: cachetools>=5
|
|
28
|
+
Requires-Dist: typing-extensions>=4.4; python_version < "3.10"
|
|
29
|
+
Provides-Extra: numpy
|
|
30
|
+
Requires-Dist: numpy>=1.24; extra == "numpy"
|
|
31
|
+
Provides-Extra: yaml
|
|
32
|
+
Requires-Dist: pyyaml>=6.0; extra == "yaml"
|
|
33
|
+
Provides-Extra: orjson
|
|
34
|
+
Requires-Dist: orjson>=3; extra == "orjson"
|
|
35
|
+
Provides-Extra: test
|
|
36
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
37
|
+
Requires-Dist: pytest-benchmark>=4; extra == "test"
|
|
38
|
+
Requires-Dist: pydocstyle>=6; extra == "test"
|
|
39
|
+
Requires-Dist: coverage>=7; extra == "test"
|
|
40
|
+
Requires-Dist: flake8>=5; extra == "test"
|
|
41
|
+
Requires-Dist: flake8-pyproject>=1.2; extra == "test"
|
|
42
|
+
Requires-Dist: vulture>=2; extra == "test"
|
|
43
|
+
Provides-Extra: typecheck
|
|
44
|
+
Requires-Dist: mypy>=1.8; extra == "typecheck"
|
|
45
|
+
Requires-Dist: networkx-stubs>=0.0.1; extra == "typecheck"
|
|
46
|
+
Requires-Dist: types-cachetools>=6.0.0.0; extra == "typecheck"
|
|
47
|
+
Requires-Dist: numpy>=1.24; extra == "typecheck"
|
|
48
|
+
Dynamic: license-file
|
|
49
|
+
|
|
50
|
+
# TNFR Python Engine
|
|
51
|
+
|
|
52
|
+
Canonical implementation of the Resonant Fractal Nature Theory (TNFR) for modelling structural
|
|
53
|
+
coherence. The engine seeds resonant nodes, applies structural operators, coordinates
|
|
54
|
+
ΔNFR/phase dynamics, and measures coherence metrics (C(t), Si, νf) without breaking the nodal
|
|
55
|
+
equation $\partial EPI/\partial t = \nu_f \cdot \Delta NFR(t)$.
|
|
56
|
+
|
|
57
|
+
## Snapshot
|
|
58
|
+
|
|
59
|
+
- **Operate:** build nodes with `tnfr.create_nfr`, execute trajectories via
|
|
60
|
+
`tnfr.structural.run_sequence`, and evolve dynamics with `tnfr.dynamics.run`.
|
|
61
|
+
- **Observe:** register metrics/trace callbacks to capture ΔNFR, C(t), Si, and structural
|
|
62
|
+
histories
|
|
63
|
+
for every run.
|
|
64
|
+
- **Extend:** rely on the canonical operator grammar and invariants before introducing new
|
|
65
|
+
utilities or telemetry.
|
|
66
|
+
|
|
67
|
+
## Quickstart
|
|
68
|
+
|
|
69
|
+
Install from PyPI (Python ≥ 3.9):
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install tnfr
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Then follow the [quickstart guide](docs/getting-started/quickstart.md) for Python and CLI
|
|
76
|
+
walkthroughs plus optional dependency caching helpers.
|
|
77
|
+
|
|
78
|
+
## Documentation map
|
|
79
|
+
|
|
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
|
|
83
|
+
workflows.
|
|
84
|
+
- [Telemetry & utilities](docs/api/telemetry.md) — coherence metrics, trace capture, locking,
|
|
85
|
+
and helper facades.
|
|
86
|
+
- [Examples](docs/examples/README.md) — runnable scenarios, CLI artefacts, and token legend.
|
|
87
|
+
|
|
88
|
+
## Documentation build workflow
|
|
89
|
+
|
|
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:
|
|
92
|
+
|
|
93
|
+
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.
|
|
97
|
+
|
|
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.
|
|
100
|
+
|
|
101
|
+
## Local development
|
|
102
|
+
|
|
103
|
+
Use the helper scripts to keep formatting aligned with the canonical configuration and to reproduce
|
|
104
|
+
the quality gate locally:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
./scripts/format.sh # Apply Black and isort across src/, tests/, scripts/, and benchmarks/
|
|
108
|
+
./scripts/format.sh --check # Validate formatting without modifying files
|
|
109
|
+
./scripts/run_tests.sh # Execute the full QA battery (type checks, tests, coverage, linting)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The formatting helper automatically prefers `poetry run` when a Poetry environment is available and
|
|
113
|
+
falls back to `python -m` invocations so local runs mirror the tooling invoked in continuous
|
|
114
|
+
integration.
|
|
115
|
+
|
|
116
|
+
## Additional resources
|
|
117
|
+
|
|
118
|
+
- [ARCHITECTURE.md](ARCHITECTURE.md) — orchestration layers and invariant enforcement.
|
|
119
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) — QA battery (`scripts/run_tests.sh`) and review
|
|
120
|
+
expectations.
|
|
121
|
+
- [TNFR.pdf](TNFR.pdf) — theoretical background, structural operators, and paradigm glossary.
|
|
122
|
+
|
|
123
|
+
## Migration notes
|
|
124
|
+
|
|
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
|
|
128
|
+
: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
|
|
130
|
+
a migration snippet that rewrites stored graphs in place prior to running the new version.
|
|
131
|
+
|
|
132
|
+
## Licensing
|
|
133
|
+
|
|
134
|
+
Released under the [MIT License](LICENSE.md). Cite the TNFR paradigm when publishing research
|
|
135
|
+
or derived artefacts based on this engine.
|
tnfr-6.0.0/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# TNFR Python Engine
|
|
2
|
+
|
|
3
|
+
Canonical implementation of the Resonant Fractal Nature Theory (TNFR) for modelling structural
|
|
4
|
+
coherence. The engine seeds resonant nodes, applies structural operators, coordinates
|
|
5
|
+
ΔNFR/phase dynamics, and measures coherence metrics (C(t), Si, νf) without breaking the nodal
|
|
6
|
+
equation $\partial EPI/\partial t = \nu_f \cdot \Delta NFR(t)$.
|
|
7
|
+
|
|
8
|
+
## Snapshot
|
|
9
|
+
|
|
10
|
+
- **Operate:** build nodes with `tnfr.create_nfr`, execute trajectories via
|
|
11
|
+
`tnfr.structural.run_sequence`, and evolve dynamics with `tnfr.dynamics.run`.
|
|
12
|
+
- **Observe:** register metrics/trace callbacks to capture ΔNFR, C(t), Si, and structural
|
|
13
|
+
histories
|
|
14
|
+
for every run.
|
|
15
|
+
- **Extend:** rely on the canonical operator grammar and invariants before introducing new
|
|
16
|
+
utilities or telemetry.
|
|
17
|
+
|
|
18
|
+
## Quickstart
|
|
19
|
+
|
|
20
|
+
Install from PyPI (Python ≥ 3.9):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install tnfr
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then follow the [quickstart guide](docs/getting-started/quickstart.md) for Python and CLI
|
|
27
|
+
walkthroughs plus optional dependency caching helpers.
|
|
28
|
+
|
|
29
|
+
## Documentation map
|
|
30
|
+
|
|
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
|
|
34
|
+
workflows.
|
|
35
|
+
- [Telemetry & utilities](docs/api/telemetry.md) — coherence metrics, trace capture, locking,
|
|
36
|
+
and helper facades.
|
|
37
|
+
- [Examples](docs/examples/README.md) — runnable scenarios, CLI artefacts, and token legend.
|
|
38
|
+
|
|
39
|
+
## Documentation build workflow
|
|
40
|
+
|
|
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:
|
|
43
|
+
|
|
44
|
+
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.
|
|
48
|
+
|
|
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.
|
|
51
|
+
|
|
52
|
+
## Local development
|
|
53
|
+
|
|
54
|
+
Use the helper scripts to keep formatting aligned with the canonical configuration and to reproduce
|
|
55
|
+
the quality gate locally:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
./scripts/format.sh # Apply Black and isort across src/, tests/, scripts/, and benchmarks/
|
|
59
|
+
./scripts/format.sh --check # Validate formatting without modifying files
|
|
60
|
+
./scripts/run_tests.sh # Execute the full QA battery (type checks, tests, coverage, linting)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The formatting helper automatically prefers `poetry run` when a Poetry environment is available and
|
|
64
|
+
falls back to `python -m` invocations so local runs mirror the tooling invoked in continuous
|
|
65
|
+
integration.
|
|
66
|
+
|
|
67
|
+
## Additional resources
|
|
68
|
+
|
|
69
|
+
- [ARCHITECTURE.md](ARCHITECTURE.md) — orchestration layers and invariant enforcement.
|
|
70
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) — QA battery (`scripts/run_tests.sh`) and review
|
|
71
|
+
expectations.
|
|
72
|
+
- [TNFR.pdf](TNFR.pdf) — theoretical background, structural operators, and paradigm glossary.
|
|
73
|
+
|
|
74
|
+
## Migration notes
|
|
75
|
+
|
|
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
|
|
79
|
+
: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
|
|
81
|
+
a migration snippet that rewrites stored graphs in place prior to running the new version.
|
|
82
|
+
|
|
83
|
+
## Licensing
|
|
84
|
+
|
|
85
|
+
Released under the [MIT License](LICENSE.md). Cite the TNFR paradigm when publishing research
|
|
86
|
+
or derived artefacts based on this engine.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tnfr"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "Modular structural-based dynamics on networks."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.9"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
authors = [{ name = "fmg" }]
|
|
9
|
+
keywords = [
|
|
10
|
+
"TNFR", "complex systems", "fractals", "resonance",
|
|
11
|
+
"networks", "structural dynamics",
|
|
12
|
+
"structural analysis"
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"Programming Language :: Python :: 3.9",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Intended Audience :: Science/Research",
|
|
24
|
+
"Topic :: Scientific/Engineering",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
26
|
+
"Topic :: Scientific/Engineering :: Mathematics"
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"networkx>=2.6",
|
|
30
|
+
"cachetools>=5",
|
|
31
|
+
"typing-extensions>=4.4; python_version < \"3.10\"",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
numpy = ["numpy>=1.24"]
|
|
36
|
+
yaml = ["pyyaml>=6.0"]
|
|
37
|
+
orjson = ["orjson>=3"]
|
|
38
|
+
test = [
|
|
39
|
+
"pytest>=7",
|
|
40
|
+
"pytest-benchmark>=4",
|
|
41
|
+
"pydocstyle>=6",
|
|
42
|
+
"coverage>=7",
|
|
43
|
+
"flake8>=5",
|
|
44
|
+
"flake8-pyproject>=1.2",
|
|
45
|
+
"vulture>=2",
|
|
46
|
+
]
|
|
47
|
+
typecheck = [
|
|
48
|
+
"mypy>=1.8",
|
|
49
|
+
"networkx-stubs>=0.0.1",
|
|
50
|
+
"types-cachetools>=6.0.0.0",
|
|
51
|
+
"numpy>=1.24",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[project.scripts]
|
|
55
|
+
tnfr = "tnfr.cli:main"
|
|
56
|
+
|
|
57
|
+
[project.urls]
|
|
58
|
+
Homepage = "https://pypi.org/project/tnfr/"
|
|
59
|
+
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__" }
|
|
64
|
+
|
|
65
|
+
[tool.setuptools.package-data]
|
|
66
|
+
tnfr = ["py.typed"]
|
|
67
|
+
|
|
68
|
+
[tool.black]
|
|
69
|
+
line-length = 88
|
|
70
|
+
target-version = ["py39", "py310", "py311", "py312"]
|
|
71
|
+
|
|
72
|
+
[tool.isort]
|
|
73
|
+
profile = "black"
|
|
74
|
+
line_length = 88
|
|
75
|
+
skip = ["benchmarks"]
|
|
76
|
+
|
|
77
|
+
[tool.flake8]
|
|
78
|
+
max-line-length = 88
|
|
79
|
+
ignore = ["E501", "W503"]
|
|
80
|
+
exclude = ["benchmarks/"]
|
|
81
|
+
|
|
82
|
+
[tool.pytest.ini_options]
|
|
83
|
+
pythonpath = ["src"]
|
|
84
|
+
addopts = "-m 'not slow' --benchmark-skip"
|
|
85
|
+
markers = [
|
|
86
|
+
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
|
|
87
|
+
"benchmarks: run with 'pytest benchmarks --benchmark-only' to execute the benchmark suite",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[tool.mypy]
|
|
91
|
+
python_version = "3.10"
|
|
92
|
+
warn_unused_configs = true
|
|
93
|
+
warn_return_any = false
|
|
94
|
+
no_implicit_optional = false
|
|
95
|
+
strict_equality = false
|
|
96
|
+
disallow_any_unimported = false
|
|
97
|
+
show_error_codes = true
|
|
98
|
+
follow_imports = "skip"
|
|
99
|
+
allow_redefinition = true
|
|
100
|
+
allow_untyped_defs = false
|
|
101
|
+
allow_untyped_calls = false
|
|
102
|
+
allow_untyped_globals = false
|
|
103
|
+
|
|
104
|
+
[[tool.mypy.overrides]]
|
|
105
|
+
module = ["networkx", "networkx.*"]
|
|
106
|
+
ignore_missing_imports = true
|
|
107
|
+
|
|
108
|
+
[[tool.mypy.overrides]]
|
|
109
|
+
module = ["yaml", "yaml.*"]
|
|
110
|
+
ignore_missing_imports = true
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
[build-system]
|
|
114
|
+
requires = ["setuptools>=78.1.1", "wheel"]
|
|
115
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1,270 @@
|
|
|
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
|
+
|
|
47
|
+
EXPORT_DEPENDENCIES: dict[str, dict[str, tuple[str, ...]]] = {
|
|
48
|
+
"step": {
|
|
49
|
+
"submodules": ("tnfr.dynamics",),
|
|
50
|
+
"third_party": ("networkx",),
|
|
51
|
+
},
|
|
52
|
+
"run": {
|
|
53
|
+
"submodules": ("tnfr.dynamics",),
|
|
54
|
+
"third_party": ("networkx",),
|
|
55
|
+
},
|
|
56
|
+
"prepare_network": {
|
|
57
|
+
"submodules": (
|
|
58
|
+
"tnfr.ontosim",
|
|
59
|
+
"tnfr.callback_utils",
|
|
60
|
+
"tnfr.constants",
|
|
61
|
+
"tnfr.dynamics",
|
|
62
|
+
"tnfr.glyph_history",
|
|
63
|
+
"tnfr.initialization",
|
|
64
|
+
"tnfr.utils",
|
|
65
|
+
),
|
|
66
|
+
"third_party": ("networkx",),
|
|
67
|
+
},
|
|
68
|
+
"create_nfr": {
|
|
69
|
+
"submodules": (
|
|
70
|
+
"tnfr.structural",
|
|
71
|
+
"tnfr.constants",
|
|
72
|
+
"tnfr.dynamics",
|
|
73
|
+
"tnfr.operators.definitions",
|
|
74
|
+
"tnfr.operators.registry",
|
|
75
|
+
"tnfr.validation",
|
|
76
|
+
),
|
|
77
|
+
"third_party": ("networkx",),
|
|
78
|
+
},
|
|
79
|
+
"run_sequence": {
|
|
80
|
+
"submodules": (
|
|
81
|
+
"tnfr.structural",
|
|
82
|
+
"tnfr.constants",
|
|
83
|
+
"tnfr.dynamics",
|
|
84
|
+
"tnfr.operators.definitions",
|
|
85
|
+
"tnfr.operators.registry",
|
|
86
|
+
"tnfr.validation",
|
|
87
|
+
),
|
|
88
|
+
"third_party": ("networkx",),
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
try: # pragma: no cover - exercised in version resolution tests
|
|
94
|
+
__version__ = metadata.version("tnfr")
|
|
95
|
+
except PackageNotFoundError: # pragma: no cover - fallback tested explicitly
|
|
96
|
+
from ._version import __version__ as _fallback_version
|
|
97
|
+
|
|
98
|
+
__version__ = _fallback_version
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _is_internal_import_error(exc: ImportError) -> bool:
|
|
102
|
+
missing_name = getattr(exc, "name", None) or ""
|
|
103
|
+
if missing_name.startswith("tnfr"):
|
|
104
|
+
return True
|
|
105
|
+
|
|
106
|
+
module_name = getattr(exc, "module", None) or ""
|
|
107
|
+
if module_name.startswith("tnfr"):
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
missing_path = getattr(exc, "path", None) or ""
|
|
111
|
+
if missing_path:
|
|
112
|
+
normalized = missing_path.replace("\\", "/")
|
|
113
|
+
if "/tnfr/" in normalized or normalized.endswith("/tnfr"):
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
message = str(exc)
|
|
117
|
+
lowered = message.lower()
|
|
118
|
+
mentions_base_package = "module 'tnfr'" in lowered or 'module "tnfr"' in lowered
|
|
119
|
+
if ("tnfr." in message or mentions_base_package) and (
|
|
120
|
+
"circular import" in lowered or "partially initialized module" in lowered
|
|
121
|
+
):
|
|
122
|
+
return True
|
|
123
|
+
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _missing_dependency(
|
|
128
|
+
name: str, exc: ImportError, *, module: str | None = None
|
|
129
|
+
) -> Callable[..., NoReturn]:
|
|
130
|
+
missing_name = getattr(exc, "name", None)
|
|
131
|
+
|
|
132
|
+
def _stub(*args: Any, **kwargs: Any) -> NoReturn:
|
|
133
|
+
raise ImportError(
|
|
134
|
+
f"{name} is unavailable because required dependencies could not be imported. "
|
|
135
|
+
f"Original error ({exc.__class__.__name__}): {exc}. "
|
|
136
|
+
"Install the missing packages (e.g. 'networkx' or grammar modules)."
|
|
137
|
+
) from exc
|
|
138
|
+
|
|
139
|
+
_stub.__tnfr_missing_dependency__ = {
|
|
140
|
+
"export": name,
|
|
141
|
+
"module": module,
|
|
142
|
+
"missing": missing_name,
|
|
143
|
+
}
|
|
144
|
+
return _stub
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
_MISSING_EXPORTS: dict[str, dict[str, Any]] = {}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class ExportDependencyError(RuntimeError):
|
|
151
|
+
"""Raised when the export dependency manifest is inconsistent."""
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _validate_export_dependencies() -> None:
|
|
155
|
+
"""Ensure exported helpers and their manifest entries stay in sync."""
|
|
156
|
+
|
|
157
|
+
if "__all__" not in globals():
|
|
158
|
+
# Defensive guard for unusual import orders (should never trigger).
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
issues: list[str] = []
|
|
162
|
+
manifest = EXPORT_DEPENDENCIES
|
|
163
|
+
export_names = [name for name in __all__ if name != "__version__"]
|
|
164
|
+
manifest_names = set(manifest)
|
|
165
|
+
|
|
166
|
+
for export_name in export_names:
|
|
167
|
+
if export_name not in manifest:
|
|
168
|
+
issues.append(
|
|
169
|
+
f"helper '{export_name}' is exported via __all__ but missing from EXPORT_DEPENDENCIES"
|
|
170
|
+
)
|
|
171
|
+
continue
|
|
172
|
+
|
|
173
|
+
entry = manifest[export_name]
|
|
174
|
+
if not isinstance(entry, dict):
|
|
175
|
+
issues.append(
|
|
176
|
+
f"helper '{export_name}' has a malformed manifest entry (expected mapping, got {type(entry)!r})"
|
|
177
|
+
)
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
for key in ("submodules", "third_party"):
|
|
181
|
+
value = entry.get(key)
|
|
182
|
+
if not value:
|
|
183
|
+
issues.append(
|
|
184
|
+
f"helper '{export_name}' is missing '{key}' dependencies in EXPORT_DEPENDENCIES"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
missing_exports = manifest_names.difference(export_names).difference(_MISSING_EXPORTS)
|
|
188
|
+
for manifest_only in sorted(missing_exports):
|
|
189
|
+
entry = manifest[manifest_only]
|
|
190
|
+
if not isinstance(entry, dict):
|
|
191
|
+
issues.append(
|
|
192
|
+
f"helper '{manifest_only}' has a malformed manifest entry (expected mapping, got {type(entry)!r})"
|
|
193
|
+
)
|
|
194
|
+
continue
|
|
195
|
+
|
|
196
|
+
for key in ("submodules", "third_party"):
|
|
197
|
+
value = entry.get(key)
|
|
198
|
+
if not value:
|
|
199
|
+
issues.append(
|
|
200
|
+
f"helper '{manifest_only}' is missing '{key}' dependencies in EXPORT_DEPENDENCIES"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
issues.append(
|
|
204
|
+
f"helper '{manifest_only}' is listed in EXPORT_DEPENDENCIES but not exported via __all__"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
if issues:
|
|
208
|
+
raise ExportDependencyError(
|
|
209
|
+
"Invalid TNFR export dependency manifest:\n- " + "\n- ".join(issues)
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _assign_exports(module: str, names: tuple[str, ...]) -> bool:
|
|
214
|
+
try: # pragma: no cover - exercised in import tests
|
|
215
|
+
mod = import_module(f".{module}", __name__)
|
|
216
|
+
except ImportError as exc: # pragma: no cover - no missing deps in CI
|
|
217
|
+
if _is_internal_import_error(exc):
|
|
218
|
+
raise
|
|
219
|
+
for export_name in names:
|
|
220
|
+
stub = _missing_dependency(export_name, exc, module=module)
|
|
221
|
+
globals()[export_name] = stub
|
|
222
|
+
_MISSING_EXPORTS[export_name] = getattr(
|
|
223
|
+
stub, "__tnfr_missing_dependency__", {}
|
|
224
|
+
)
|
|
225
|
+
return False
|
|
226
|
+
else:
|
|
227
|
+
for export_name in names:
|
|
228
|
+
globals()[export_name] = getattr(mod, export_name)
|
|
229
|
+
return True
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
_assign_exports("dynamics", ("step", "run"))
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
_HAS_PREPARE_NETWORK = _assign_exports("ontosim", ("prepare_network",))
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
_HAS_RUN_SEQUENCE = _assign_exports("structural", ("create_nfr", "run_sequence"))
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _emit_missing_dependency_warning() -> None:
|
|
242
|
+
if not _MISSING_EXPORTS:
|
|
243
|
+
return
|
|
244
|
+
details = ", ".join(
|
|
245
|
+
f"{name} (missing: {info.get('missing') or 'unknown'})"
|
|
246
|
+
for name, info in sorted(_MISSING_EXPORTS.items())
|
|
247
|
+
)
|
|
248
|
+
warnings.warn(
|
|
249
|
+
"TNFR helpers disabled because dependencies are missing: " + details,
|
|
250
|
+
ImportWarning,
|
|
251
|
+
stacklevel=2,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
_emit_missing_dependency_warning()
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
__all__ = [
|
|
259
|
+
"__version__",
|
|
260
|
+
"step",
|
|
261
|
+
"run",
|
|
262
|
+
"prepare_network",
|
|
263
|
+
"create_nfr",
|
|
264
|
+
]
|
|
265
|
+
|
|
266
|
+
if _HAS_RUN_SEQUENCE:
|
|
267
|
+
__all__.append("run_sequence")
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
_validate_export_dependencies()
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
|
|
19
|
+
class ExportDependencyError(RuntimeError):
|
|
20
|
+
"""Raised when the export dependency manifest is inconsistent."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _is_internal_import_error(exc: ImportError) -> bool: ...
|
|
24
|
+
|
|
25
|
+
def _missing_dependency(
|
|
26
|
+
name: str,
|
|
27
|
+
exc: ImportError,
|
|
28
|
+
*,
|
|
29
|
+
module: str | None = ...,
|
|
30
|
+
) -> Callable[..., NoReturn]: ...
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _validate_export_dependencies() -> None: ...
|
|
34
|
+
|
|
35
|
+
def _assign_exports(module: str, names: tuple[str, ...]) -> bool: ...
|
|
36
|
+
|
|
37
|
+
def _emit_missing_dependency_warning() -> None: ...
|
|
38
|
+
|
|
39
|
+
_HAS_PREPARE_NETWORK: bool
|
|
40
|
+
_HAS_RUN_SEQUENCE: bool
|
|
@@ -0,0 +1,11 @@
|
|
|
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"]
|
|
11
|
+
|