tnfr 4.5.2__py3-none-any.whl → 7.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tnfr might be problematic. Click here for more details.
- tnfr/__init__.py +275 -51
- tnfr/__init__.pyi +33 -0
- tnfr/_compat.py +10 -0
- tnfr/_generated_version.py +34 -0
- tnfr/_version.py +49 -0
- tnfr/_version.pyi +7 -0
- tnfr/alias.py +117 -31
- tnfr/alias.pyi +108 -0
- tnfr/cache.py +6 -572
- tnfr/cache.pyi +16 -0
- tnfr/callback_utils.py +16 -38
- tnfr/callback_utils.pyi +79 -0
- tnfr/cli/__init__.py +34 -14
- tnfr/cli/__init__.pyi +26 -0
- tnfr/cli/arguments.py +211 -28
- tnfr/cli/arguments.pyi +27 -0
- tnfr/cli/execution.py +470 -50
- tnfr/cli/execution.pyi +70 -0
- tnfr/cli/utils.py +18 -3
- tnfr/cli/utils.pyi +8 -0
- tnfr/config/__init__.py +13 -0
- tnfr/config/__init__.pyi +10 -0
- tnfr/{constants_glyphs.py → config/constants.py} +26 -20
- tnfr/config/constants.pyi +12 -0
- tnfr/config/feature_flags.py +83 -0
- tnfr/{config.py → config/init.py} +11 -7
- tnfr/config/init.pyi +8 -0
- tnfr/config/operator_names.py +93 -0
- tnfr/config/operator_names.pyi +28 -0
- tnfr/config/presets.py +84 -0
- tnfr/config/presets.pyi +7 -0
- tnfr/constants/__init__.py +80 -29
- tnfr/constants/__init__.pyi +92 -0
- tnfr/constants/aliases.py +31 -0
- tnfr/constants/core.py +4 -4
- tnfr/constants/core.pyi +17 -0
- tnfr/constants/init.py +1 -1
- tnfr/constants/init.pyi +12 -0
- tnfr/constants/metric.py +7 -15
- tnfr/constants/metric.pyi +19 -0
- tnfr/dynamics/__init__.py +165 -633
- tnfr/dynamics/__init__.pyi +82 -0
- tnfr/dynamics/adaptation.py +267 -0
- tnfr/dynamics/aliases.py +23 -0
- tnfr/dynamics/coordination.py +385 -0
- tnfr/dynamics/dnfr.py +2283 -400
- tnfr/dynamics/dnfr.pyi +24 -0
- tnfr/dynamics/integrators.py +406 -98
- tnfr/dynamics/integrators.pyi +34 -0
- tnfr/dynamics/runtime.py +881 -0
- tnfr/dynamics/sampling.py +10 -5
- tnfr/dynamics/sampling.pyi +7 -0
- tnfr/dynamics/selectors.py +719 -0
- tnfr/execution.py +70 -48
- tnfr/execution.pyi +45 -0
- tnfr/flatten.py +13 -9
- tnfr/flatten.pyi +21 -0
- tnfr/gamma.py +66 -53
- tnfr/gamma.pyi +34 -0
- tnfr/glyph_history.py +110 -52
- tnfr/glyph_history.pyi +35 -0
- tnfr/glyph_runtime.py +16 -0
- tnfr/glyph_runtime.pyi +9 -0
- tnfr/immutable.py +69 -28
- tnfr/immutable.pyi +34 -0
- tnfr/initialization.py +16 -16
- tnfr/initialization.pyi +65 -0
- tnfr/io.py +6 -240
- tnfr/io.pyi +16 -0
- tnfr/locking.pyi +7 -0
- tnfr/mathematics/__init__.py +81 -0
- tnfr/mathematics/backend.py +426 -0
- tnfr/mathematics/dynamics.py +398 -0
- tnfr/mathematics/epi.py +254 -0
- tnfr/mathematics/generators.py +222 -0
- tnfr/mathematics/metrics.py +119 -0
- tnfr/mathematics/operators.py +233 -0
- tnfr/mathematics/operators_factory.py +71 -0
- tnfr/mathematics/projection.py +78 -0
- tnfr/mathematics/runtime.py +173 -0
- tnfr/mathematics/spaces.py +247 -0
- tnfr/mathematics/transforms.py +292 -0
- tnfr/metrics/__init__.py +10 -10
- tnfr/metrics/__init__.pyi +20 -0
- tnfr/metrics/coherence.py +993 -324
- tnfr/metrics/common.py +23 -16
- tnfr/metrics/common.pyi +46 -0
- tnfr/metrics/core.py +251 -35
- tnfr/metrics/core.pyi +13 -0
- tnfr/metrics/diagnosis.py +708 -111
- tnfr/metrics/diagnosis.pyi +85 -0
- tnfr/metrics/export.py +27 -15
- tnfr/metrics/glyph_timing.py +232 -42
- tnfr/metrics/reporting.py +33 -22
- tnfr/metrics/reporting.pyi +12 -0
- tnfr/metrics/sense_index.py +987 -43
- tnfr/metrics/sense_index.pyi +9 -0
- tnfr/metrics/trig.py +214 -23
- tnfr/metrics/trig.pyi +13 -0
- tnfr/metrics/trig_cache.py +115 -22
- tnfr/metrics/trig_cache.pyi +10 -0
- tnfr/node.py +542 -136
- tnfr/node.pyi +178 -0
- tnfr/observers.py +152 -35
- tnfr/observers.pyi +31 -0
- tnfr/ontosim.py +23 -19
- tnfr/ontosim.pyi +28 -0
- tnfr/operators/__init__.py +601 -82
- tnfr/operators/__init__.pyi +45 -0
- tnfr/operators/definitions.py +513 -0
- tnfr/operators/definitions.pyi +78 -0
- tnfr/operators/grammar.py +760 -0
- tnfr/operators/jitter.py +107 -38
- tnfr/operators/jitter.pyi +11 -0
- tnfr/operators/registry.py +75 -0
- tnfr/operators/registry.pyi +13 -0
- tnfr/operators/remesh.py +149 -88
- tnfr/py.typed +0 -0
- tnfr/rng.py +46 -143
- tnfr/rng.pyi +14 -0
- tnfr/schemas/__init__.py +8 -0
- tnfr/schemas/grammar.json +94 -0
- tnfr/selector.py +25 -19
- tnfr/selector.pyi +19 -0
- tnfr/sense.py +72 -62
- tnfr/sense.pyi +23 -0
- tnfr/structural.py +522 -262
- tnfr/structural.pyi +69 -0
- tnfr/telemetry/__init__.py +35 -0
- tnfr/telemetry/cache_metrics.py +226 -0
- tnfr/telemetry/nu_f.py +423 -0
- tnfr/telemetry/nu_f.pyi +123 -0
- tnfr/telemetry/verbosity.py +37 -0
- tnfr/tokens.py +1 -3
- tnfr/tokens.pyi +36 -0
- tnfr/trace.py +270 -113
- tnfr/trace.pyi +40 -0
- tnfr/types.py +574 -6
- tnfr/types.pyi +331 -0
- tnfr/units.py +69 -0
- tnfr/units.pyi +16 -0
- tnfr/utils/__init__.py +217 -0
- tnfr/utils/__init__.pyi +202 -0
- tnfr/utils/cache.py +2395 -0
- tnfr/utils/cache.pyi +468 -0
- tnfr/utils/chunks.py +104 -0
- tnfr/utils/chunks.pyi +21 -0
- tnfr/{collections_utils.py → utils/data.py} +147 -90
- tnfr/utils/data.pyi +64 -0
- tnfr/utils/graph.py +85 -0
- tnfr/utils/graph.pyi +10 -0
- tnfr/utils/init.py +770 -0
- tnfr/utils/init.pyi +78 -0
- tnfr/utils/io.py +456 -0
- tnfr/{helpers → utils}/numeric.py +51 -24
- tnfr/utils/numeric.pyi +21 -0
- tnfr/validation/__init__.py +113 -0
- tnfr/validation/__init__.pyi +77 -0
- tnfr/validation/compatibility.py +95 -0
- tnfr/validation/compatibility.pyi +6 -0
- tnfr/validation/grammar.py +71 -0
- tnfr/validation/grammar.pyi +40 -0
- tnfr/validation/graph.py +138 -0
- tnfr/validation/graph.pyi +17 -0
- tnfr/validation/rules.py +281 -0
- tnfr/validation/rules.pyi +55 -0
- tnfr/validation/runtime.py +263 -0
- tnfr/validation/runtime.pyi +31 -0
- tnfr/validation/soft_filters.py +170 -0
- tnfr/validation/soft_filters.pyi +37 -0
- tnfr/validation/spectral.py +159 -0
- tnfr/validation/spectral.pyi +46 -0
- tnfr/validation/syntax.py +40 -0
- tnfr/validation/syntax.pyi +10 -0
- tnfr/validation/window.py +39 -0
- tnfr/validation/window.pyi +1 -0
- tnfr/viz/__init__.py +9 -0
- tnfr/viz/matplotlib.py +246 -0
- tnfr-7.0.0.dist-info/METADATA +179 -0
- tnfr-7.0.0.dist-info/RECORD +185 -0
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/licenses/LICENSE.md +1 -1
- tnfr/grammar.py +0 -344
- tnfr/graph_utils.py +0 -84
- tnfr/helpers/__init__.py +0 -71
- tnfr/import_utils.py +0 -228
- tnfr/json_utils.py +0 -162
- tnfr/logging_utils.py +0 -116
- tnfr/presets.py +0 -60
- tnfr/validators.py +0 -84
- tnfr/value_utils.py +0 -59
- tnfr-4.5.2.dist-info/METADATA +0 -379
- tnfr-4.5.2.dist-info/RECORD +0 -67
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/WHEEL +0 -0
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/entry_points.txt +0 -0
- {tnfr-4.5.2.dist-info → tnfr-7.0.0.dist-info}/top_level.txt +0 -0
tnfr/initialization.py
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
"""Node initialization."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
import random
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
4
|
|
|
5
|
+
import random
|
|
7
6
|
from dataclasses import dataclass
|
|
7
|
+
from typing import TYPE_CHECKING, cast
|
|
8
8
|
|
|
9
|
-
from .constants import
|
|
10
|
-
from .
|
|
9
|
+
from .constants import THETA_KEY, VF_KEY, get_graph_param
|
|
10
|
+
from .utils import clamp
|
|
11
11
|
from .rng import make_rng
|
|
12
|
+
from .types import NodeInitAttrMap
|
|
12
13
|
|
|
13
14
|
if TYPE_CHECKING: # pragma: no cover
|
|
14
|
-
import networkx as nx
|
|
15
|
+
import networkx as nx
|
|
15
16
|
|
|
16
17
|
__all__ = ("InitParams", "init_node_attrs")
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
@dataclass
|
|
20
21
|
class InitParams:
|
|
21
|
-
"""
|
|
22
|
+
"""Parameters governing node initialisation."""
|
|
22
23
|
|
|
23
24
|
seed: int | None
|
|
24
25
|
init_rand_phase: bool
|
|
@@ -38,7 +39,7 @@ class InitParams:
|
|
|
38
39
|
|
|
39
40
|
@classmethod
|
|
40
41
|
def from_graph(cls, G: "nx.Graph") -> "InitParams":
|
|
41
|
-
"""
|
|
42
|
+
"""Construct ``InitParams`` from ``G.graph`` configuration."""
|
|
42
43
|
|
|
43
44
|
return cls(
|
|
44
45
|
seed=get_graph_param(G, "RANDOM_SEED", int),
|
|
@@ -52,9 +53,7 @@ class InitParams:
|
|
|
52
53
|
vf_uniform_max=get_graph_param(G, "INIT_VF_MAX"),
|
|
53
54
|
vf_mean=get_graph_param(G, "INIT_VF_MEAN"),
|
|
54
55
|
vf_std=get_graph_param(G, "INIT_VF_STD"),
|
|
55
|
-
clamp_to_limits=get_graph_param(
|
|
56
|
-
G, "INIT_VF_CLAMP_TO_LIMITS", bool
|
|
57
|
-
),
|
|
56
|
+
clamp_to_limits=get_graph_param(G, "INIT_VF_CLAMP_TO_LIMITS", bool),
|
|
58
57
|
si_min=get_graph_param(G, "INIT_SI_MIN"),
|
|
59
58
|
si_max=get_graph_param(G, "INIT_SI_MAX"),
|
|
60
59
|
epi_val=get_graph_param(G, "INIT_EPI_VALUE"),
|
|
@@ -62,7 +61,7 @@ class InitParams:
|
|
|
62
61
|
|
|
63
62
|
|
|
64
63
|
def _init_phase(
|
|
65
|
-
nd:
|
|
64
|
+
nd: NodeInitAttrMap,
|
|
66
65
|
rng: random.Random,
|
|
67
66
|
*,
|
|
68
67
|
override: bool,
|
|
@@ -82,7 +81,7 @@ def _init_phase(
|
|
|
82
81
|
|
|
83
82
|
|
|
84
83
|
def _init_vf(
|
|
85
|
-
nd:
|
|
84
|
+
nd: NodeInitAttrMap,
|
|
86
85
|
rng: random.Random,
|
|
87
86
|
*,
|
|
88
87
|
override: bool,
|
|
@@ -118,7 +117,7 @@ def _init_vf(
|
|
|
118
117
|
|
|
119
118
|
|
|
120
119
|
def _init_si_epi(
|
|
121
|
-
nd:
|
|
120
|
+
nd: NodeInitAttrMap,
|
|
122
121
|
rng: random.Random,
|
|
123
122
|
*,
|
|
124
123
|
override: bool,
|
|
@@ -163,9 +162,10 @@ def init_node_attrs(G: "nx.Graph", *, override: bool = True) -> "nx.Graph":
|
|
|
163
162
|
|
|
164
163
|
rng = make_rng(params.seed, -1, G)
|
|
165
164
|
for _, nd in G.nodes(data=True):
|
|
165
|
+
node_attrs = cast(NodeInitAttrMap, nd)
|
|
166
166
|
|
|
167
167
|
_init_phase(
|
|
168
|
-
|
|
168
|
+
node_attrs,
|
|
169
169
|
rng,
|
|
170
170
|
override=override,
|
|
171
171
|
random_phase=params.init_rand_phase,
|
|
@@ -173,7 +173,7 @@ def init_node_attrs(G: "nx.Graph", *, override: bool = True) -> "nx.Graph":
|
|
|
173
173
|
th_max=params.th_max,
|
|
174
174
|
)
|
|
175
175
|
_init_vf(
|
|
176
|
-
|
|
176
|
+
node_attrs,
|
|
177
177
|
rng,
|
|
178
178
|
override=override,
|
|
179
179
|
mode=params.vf_mode,
|
|
@@ -186,7 +186,7 @@ def init_node_attrs(G: "nx.Graph", *, override: bool = True) -> "nx.Graph":
|
|
|
186
186
|
clamp_to_limits=params.clamp_to_limits,
|
|
187
187
|
)
|
|
188
188
|
_init_si_epi(
|
|
189
|
-
|
|
189
|
+
node_attrs,
|
|
190
190
|
rng,
|
|
191
191
|
override=override,
|
|
192
192
|
si_min=params.si_min,
|
tnfr/initialization.pyi
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
import networkx as nx
|
|
7
|
+
|
|
8
|
+
from .types import NodeInitAttrMap
|
|
9
|
+
|
|
10
|
+
__all__: tuple[str, str] = ("InitParams", "init_node_attrs")
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class InitParams:
|
|
14
|
+
seed: int | None
|
|
15
|
+
init_rand_phase: bool
|
|
16
|
+
th_min: float
|
|
17
|
+
th_max: float
|
|
18
|
+
vf_mode: str
|
|
19
|
+
vf_min_lim: float
|
|
20
|
+
vf_max_lim: float
|
|
21
|
+
vf_uniform_min: float | None
|
|
22
|
+
vf_uniform_max: float | None
|
|
23
|
+
vf_mean: float
|
|
24
|
+
vf_std: float
|
|
25
|
+
clamp_to_limits: bool
|
|
26
|
+
si_min: float
|
|
27
|
+
si_max: float
|
|
28
|
+
epi_val: float
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def from_graph(cls, G: nx.Graph) -> InitParams: ...
|
|
32
|
+
|
|
33
|
+
def _init_phase(
|
|
34
|
+
nd: NodeInitAttrMap,
|
|
35
|
+
rng: random.Random,
|
|
36
|
+
*,
|
|
37
|
+
override: bool,
|
|
38
|
+
random_phase: bool,
|
|
39
|
+
th_min: float,
|
|
40
|
+
th_max: float,
|
|
41
|
+
) -> None: ...
|
|
42
|
+
def _init_vf(
|
|
43
|
+
nd: NodeInitAttrMap,
|
|
44
|
+
rng: random.Random,
|
|
45
|
+
*,
|
|
46
|
+
override: bool,
|
|
47
|
+
mode: str,
|
|
48
|
+
vf_uniform_min: float,
|
|
49
|
+
vf_uniform_max: float,
|
|
50
|
+
vf_mean: float,
|
|
51
|
+
vf_std: float,
|
|
52
|
+
vf_min_lim: float,
|
|
53
|
+
vf_max_lim: float,
|
|
54
|
+
clamp_to_limits: bool,
|
|
55
|
+
) -> None: ...
|
|
56
|
+
def _init_si_epi(
|
|
57
|
+
nd: NodeInitAttrMap,
|
|
58
|
+
rng: random.Random,
|
|
59
|
+
*,
|
|
60
|
+
override: bool,
|
|
61
|
+
si_min: float,
|
|
62
|
+
si_max: float,
|
|
63
|
+
epi_val: float,
|
|
64
|
+
) -> None: ...
|
|
65
|
+
def init_node_attrs(G: nx.Graph, *, override: bool = True) -> nx.Graph: ...
|
tnfr/io.py
CHANGED
|
@@ -1,246 +1,12 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Legacy JSON utilities module.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
``cached_import.cache_clear()`` and :func:`tnfr.import_utils.prune_failed_imports`
|
|
7
|
-
when needed.
|
|
3
|
+
The backwards-compatible re-export was removed; use :mod:`tnfr.utils.io`
|
|
4
|
+
directly. Importing :mod:`tnfr.io` now raises an :class:`ImportError` with a
|
|
5
|
+
clear migration hint.
|
|
8
6
|
"""
|
|
9
7
|
|
|
10
8
|
from __future__ import annotations
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import tempfile
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
from typing import Any, Callable
|
|
17
|
-
from functools import partial
|
|
18
|
-
|
|
19
|
-
from .import_utils import cached_import
|
|
20
|
-
from .logging_utils import get_logger
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _raise_import_error(name: str, *_: Any, **__: Any) -> Any:
|
|
24
|
-
raise ImportError(f"{name} is not installed")
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
_MISSING_TOML_ERROR = type(
|
|
28
|
-
"MissingTOMLDependencyError",
|
|
29
|
-
(Exception,),
|
|
30
|
-
{"__doc__": "Fallback error used when tomllib/tomli is missing."},
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
_MISSING_YAML_ERROR = type(
|
|
34
|
-
"MissingPyYAMLDependencyError",
|
|
35
|
-
(Exception,),
|
|
36
|
-
{"__doc__": "Fallback error used when pyyaml is missing."},
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
tomllib = cached_import(
|
|
41
|
-
"tomllib",
|
|
42
|
-
emit="log",
|
|
43
|
-
fallback=cached_import("tomli", emit="log"),
|
|
44
|
-
)
|
|
45
|
-
has_toml = tomllib is not None
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
TOMLDecodeError = cached_import(
|
|
49
|
-
"tomllib",
|
|
50
|
-
"TOMLDecodeError",
|
|
51
|
-
emit="log",
|
|
52
|
-
fallback=cached_import(
|
|
53
|
-
"tomli",
|
|
54
|
-
"TOMLDecodeError",
|
|
55
|
-
emit="log",
|
|
56
|
-
fallback=_MISSING_TOML_ERROR,
|
|
57
|
-
),
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
_TOML_LOADS: Callable[[str], Any] = cached_import(
|
|
62
|
-
"tomllib",
|
|
63
|
-
"loads",
|
|
64
|
-
emit="log",
|
|
65
|
-
fallback=cached_import(
|
|
66
|
-
"tomli",
|
|
67
|
-
"loads",
|
|
68
|
-
emit="log",
|
|
69
|
-
fallback=partial(_raise_import_error, "tomllib/tomli"),
|
|
70
|
-
),
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
yaml = cached_import("yaml", emit="log")
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
YAMLError = cached_import(
|
|
78
|
-
"yaml",
|
|
79
|
-
"YAMLError",
|
|
80
|
-
emit="log",
|
|
81
|
-
fallback=_MISSING_YAML_ERROR,
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
_YAML_SAFE_LOAD: Callable[[str], Any] = cached_import(
|
|
86
|
-
"yaml",
|
|
87
|
-
"safe_load",
|
|
88
|
-
emit="log",
|
|
89
|
-
fallback=partial(_raise_import_error, "pyyaml"),
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def _parse_yaml(text: str) -> Any:
|
|
94
|
-
"""Parse YAML ``text`` using ``safe_load`` if available."""
|
|
95
|
-
return _YAML_SAFE_LOAD(text)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def _parse_toml(text: str) -> Any:
|
|
99
|
-
"""Parse TOML ``text`` using ``tomllib`` or ``tomli``."""
|
|
100
|
-
return _TOML_LOADS(text)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
PARSERS = {
|
|
104
|
-
".json": json.loads,
|
|
105
|
-
".yaml": _parse_yaml,
|
|
106
|
-
".yml": _parse_yaml,
|
|
107
|
-
".toml": _parse_toml,
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
def _get_parser(suffix: str) -> Callable[[str], Any]:
|
|
112
|
-
try:
|
|
113
|
-
return PARSERS[suffix]
|
|
114
|
-
except KeyError as exc:
|
|
115
|
-
raise ValueError(f"Unsupported suffix: {suffix}") from exc
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
ERROR_MESSAGES = {
|
|
119
|
-
OSError: "Could not read {path}: {e}",
|
|
120
|
-
UnicodeDecodeError: "Encoding error while reading {path}: {e}",
|
|
121
|
-
json.JSONDecodeError: "Error parsing JSON file at {path}: {e}",
|
|
122
|
-
YAMLError: "Error parsing YAML file at {path}: {e}",
|
|
123
|
-
ImportError: "Missing dependency parsing {path}: {e}",
|
|
124
|
-
}
|
|
125
|
-
if has_toml:
|
|
126
|
-
ERROR_MESSAGES[TOMLDecodeError] = "Error parsing TOML file at {path}: {e}"
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def _format_structured_file_error(path: Path, e: Exception) -> str:
|
|
130
|
-
for exc, msg in ERROR_MESSAGES.items():
|
|
131
|
-
if isinstance(e, exc):
|
|
132
|
-
return msg.format(path=path, e=e)
|
|
133
|
-
return f"Error parsing {path}: {e}"
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
class StructuredFileError(Exception):
|
|
137
|
-
"""Error while reading or parsing a structured file."""
|
|
138
|
-
|
|
139
|
-
def __init__(self, path: Path, original: Exception):
|
|
140
|
-
super().__init__(_format_structured_file_error(path, original))
|
|
141
|
-
self.path = path
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def read_structured_file(path: Path) -> Any:
|
|
145
|
-
"""Read a JSON, YAML or TOML file and return parsed data."""
|
|
146
|
-
suffix = path.suffix.lower()
|
|
147
|
-
try:
|
|
148
|
-
parser = _get_parser(suffix)
|
|
149
|
-
except ValueError as e:
|
|
150
|
-
raise StructuredFileError(path, e) from e
|
|
151
|
-
try:
|
|
152
|
-
text = path.read_text(encoding="utf-8")
|
|
153
|
-
return parser(text)
|
|
154
|
-
except (
|
|
155
|
-
OSError,
|
|
156
|
-
UnicodeDecodeError,
|
|
157
|
-
json.JSONDecodeError,
|
|
158
|
-
YAMLError,
|
|
159
|
-
TOMLDecodeError,
|
|
160
|
-
ImportError,
|
|
161
|
-
) as e:
|
|
162
|
-
raise StructuredFileError(path, e) from e
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
logger = get_logger(__name__)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def safe_write(
|
|
169
|
-
path: str | Path,
|
|
170
|
-
write: Callable[[Any], Any],
|
|
171
|
-
*,
|
|
172
|
-
mode: str = "w",
|
|
173
|
-
encoding: str | None = "utf-8",
|
|
174
|
-
atomic: bool = True,
|
|
175
|
-
sync: bool | None = None,
|
|
176
|
-
**open_kwargs: Any,
|
|
177
|
-
) -> None:
|
|
178
|
-
"""Write to ``path`` ensuring parent directory exists and handle errors.
|
|
179
|
-
|
|
180
|
-
Parameters
|
|
181
|
-
----------
|
|
182
|
-
path:
|
|
183
|
-
Destination file path.
|
|
184
|
-
write:
|
|
185
|
-
Callback receiving the opened file object and performing the actual
|
|
186
|
-
write.
|
|
187
|
-
mode:
|
|
188
|
-
File mode passed to :func:`open`. Text modes (default) use UTF-8
|
|
189
|
-
encoding unless ``encoding`` is ``None``. When a binary mode is used
|
|
190
|
-
(``'b'`` in ``mode``) no encoding parameter is supplied so
|
|
191
|
-
``write`` may write bytes.
|
|
192
|
-
encoding:
|
|
193
|
-
Encoding for text modes. Ignored for binary modes.
|
|
194
|
-
atomic:
|
|
195
|
-
When ``True`` (default) writes to a temporary file and atomically
|
|
196
|
-
replaces the destination after flushing to disk. When ``False``
|
|
197
|
-
writes directly to ``path`` without any atomicity guarantee.
|
|
198
|
-
sync:
|
|
199
|
-
When ``True`` flushes and fsyncs the file descriptor after writing.
|
|
200
|
-
``None`` uses ``atomic`` to determine syncing behaviour.
|
|
201
|
-
"""
|
|
202
|
-
path = Path(path)
|
|
203
|
-
path.parent.mkdir(parents=True, exist_ok=True)
|
|
204
|
-
open_params = dict(mode=mode, **open_kwargs)
|
|
205
|
-
if "b" not in mode and encoding is not None:
|
|
206
|
-
open_params["encoding"] = encoding
|
|
207
|
-
if sync is None:
|
|
208
|
-
sync = atomic
|
|
209
|
-
tmp_path: Path | None = None
|
|
210
|
-
try:
|
|
211
|
-
if atomic:
|
|
212
|
-
tmp_fd = tempfile.NamedTemporaryFile(dir=path.parent, delete=False)
|
|
213
|
-
tmp_path = Path(tmp_fd.name)
|
|
214
|
-
tmp_fd.close()
|
|
215
|
-
with open(tmp_path, **open_params) as fd:
|
|
216
|
-
write(fd)
|
|
217
|
-
if sync:
|
|
218
|
-
fd.flush()
|
|
219
|
-
os.fsync(fd.fileno())
|
|
220
|
-
try:
|
|
221
|
-
os.replace(tmp_path, path)
|
|
222
|
-
except OSError as e:
|
|
223
|
-
logger.error(
|
|
224
|
-
"Atomic replace failed for %s -> %s: %s", tmp_path, path, e
|
|
225
|
-
)
|
|
226
|
-
raise
|
|
227
|
-
else:
|
|
228
|
-
with open(path, **open_params) as fd:
|
|
229
|
-
write(fd)
|
|
230
|
-
if sync:
|
|
231
|
-
fd.flush()
|
|
232
|
-
os.fsync(fd.fileno())
|
|
233
|
-
except (OSError, ValueError, TypeError) as e:
|
|
234
|
-
raise type(e)(f"Failed to write file {path}: {e}") from e
|
|
235
|
-
finally:
|
|
236
|
-
if tmp_path is not None:
|
|
237
|
-
tmp_path.unlink(missing_ok=True)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
__all__ = (
|
|
241
|
-
"read_structured_file",
|
|
242
|
-
"safe_write",
|
|
243
|
-
"StructuredFileError",
|
|
244
|
-
"TOMLDecodeError",
|
|
245
|
-
"YAMLError",
|
|
10
|
+
raise ImportError(
|
|
11
|
+
"`tnfr.io` was removed. Import helpers from `tnfr.utils.io` instead."
|
|
246
12
|
)
|
tnfr/io.pyi
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Compatibility stub removed; import from :mod:`tnfr.utils.io` instead."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import NoReturn
|
|
6
|
+
|
|
7
|
+
__all__ = ()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def __getattr__(name: str) -> NoReturn:
|
|
11
|
+
"""Indicate that :mod:`tnfr.io` no longer exports IO helpers."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def __dir__() -> tuple[str, ...]:
|
|
15
|
+
"""Return an empty set of exports to mirror the removed shim."""
|
|
16
|
+
|
tnfr/locking.pyi
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Mathematics primitives aligned with TNFR coherence modeling.
|
|
2
|
+
|
|
3
|
+
Backend selection
|
|
4
|
+
-----------------
|
|
5
|
+
Use :func:`get_backend` to retrieve a numerical backend compatible with TNFR's
|
|
6
|
+
structural operators. The selection order is ``name`` → ``TNFR_MATH_BACKEND``
|
|
7
|
+
→ :func:`tnfr.config.get_flags`. NumPy remains the canonical default so
|
|
8
|
+
existing code continues to operate even when optional dependencies are absent.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .backend import (
|
|
12
|
+
MathematicsBackend,
|
|
13
|
+
available_backends,
|
|
14
|
+
ensure_array,
|
|
15
|
+
ensure_numpy,
|
|
16
|
+
get_backend,
|
|
17
|
+
register_backend,
|
|
18
|
+
)
|
|
19
|
+
from .dynamics import ContractiveDynamicsEngine, MathematicalDynamicsEngine
|
|
20
|
+
from .epi import BEPIElement, CoherenceEvaluation, evaluate_coherence_transform
|
|
21
|
+
from .generators import build_delta_nfr, build_lindblad_delta_nfr
|
|
22
|
+
from .metrics import dcoh
|
|
23
|
+
from .operators import CoherenceOperator, FrequencyOperator
|
|
24
|
+
from .operators_factory import make_coherence_operator, make_frequency_operator
|
|
25
|
+
from .projection import BasicStateProjector, StateProjector
|
|
26
|
+
from .runtime import (
|
|
27
|
+
coherence,
|
|
28
|
+
coherence_expectation,
|
|
29
|
+
frequency_expectation,
|
|
30
|
+
frequency_positive,
|
|
31
|
+
normalized,
|
|
32
|
+
stable_unitary,
|
|
33
|
+
)
|
|
34
|
+
from .spaces import BanachSpaceEPI, HilbertSpace
|
|
35
|
+
from .transforms import (
|
|
36
|
+
CoherenceMonotonicityReport,
|
|
37
|
+
CoherenceViolation,
|
|
38
|
+
IsometryFactory,
|
|
39
|
+
build_isometry_factory,
|
|
40
|
+
ensure_coherence_monotonicity,
|
|
41
|
+
validate_norm_preservation,
|
|
42
|
+
)
|
|
43
|
+
from ..validation import NFRValidator
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
"MathematicsBackend",
|
|
47
|
+
"ensure_array",
|
|
48
|
+
"ensure_numpy",
|
|
49
|
+
"HilbertSpace",
|
|
50
|
+
"BanachSpaceEPI",
|
|
51
|
+
"BEPIElement",
|
|
52
|
+
"CoherenceEvaluation",
|
|
53
|
+
"CoherenceOperator",
|
|
54
|
+
"ContractiveDynamicsEngine",
|
|
55
|
+
"CoherenceMonotonicityReport",
|
|
56
|
+
"CoherenceViolation",
|
|
57
|
+
"FrequencyOperator",
|
|
58
|
+
"MathematicalDynamicsEngine",
|
|
59
|
+
"build_delta_nfr",
|
|
60
|
+
"build_lindblad_delta_nfr",
|
|
61
|
+
"make_coherence_operator",
|
|
62
|
+
"make_frequency_operator",
|
|
63
|
+
"NFRValidator",
|
|
64
|
+
"IsometryFactory",
|
|
65
|
+
"build_isometry_factory",
|
|
66
|
+
"validate_norm_preservation",
|
|
67
|
+
"ensure_coherence_monotonicity",
|
|
68
|
+
"evaluate_coherence_transform",
|
|
69
|
+
"StateProjector",
|
|
70
|
+
"BasicStateProjector",
|
|
71
|
+
"normalized",
|
|
72
|
+
"coherence",
|
|
73
|
+
"frequency_positive",
|
|
74
|
+
"stable_unitary",
|
|
75
|
+
"dcoh",
|
|
76
|
+
"coherence_expectation",
|
|
77
|
+
"frequency_expectation",
|
|
78
|
+
"available_backends",
|
|
79
|
+
"get_backend",
|
|
80
|
+
"register_backend",
|
|
81
|
+
]
|