objectstate 2.1.0__tar.gz → 3.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.
- {objectstate-2.1.0 → objectstate-3.0.0}/.github/badges/coverage.svg +1 -1
- {objectstate-2.1.0 → objectstate-3.0.0}/PKG-INFO +1 -1
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/provenance.rst +28 -11
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/__init__.py +5 -7
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/context_manager.py +182 -446
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/docs/context_system.rst +26 -71
- objectstate-3.0.0/src/objectstate/dual_axis_resolver.py +221 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/lazy_factory.py +72 -199
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/live_context_resolver.py +48 -24
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/object_state.py +29 -17
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/object_state_registry.py +108 -79
- objectstate-3.0.0/tests/test_atomic_block_context.py +139 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_callable_baseline.py +0 -3
- objectstate-3.0.0/tests/test_context_failures_surface.py +130 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_context_manager.py +7 -12
- objectstate-3.0.0/tests/test_lazy_counterpart_registry.py +171 -0
- objectstate-3.0.0/tests/test_live_context_resolver_answers.py +106 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_object_state_metadata_contracts.py +0 -3
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_object_state_update_instance.py +0 -3
- objectstate-3.0.0/tests/test_one_field_resolution.py +301 -0
- objectstate-3.0.0/tests/test_scopeless_state_resolution.py +109 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_undo_redo_cascade.py +1 -6
- objectstate-2.1.0/src/objectstate/dual_axis_resolver.py +0 -383
- {objectstate-2.1.0 → objectstate-3.0.0}/.github/workflows/ci.yml +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/.github/workflows/coverage-pages.yml +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/.github/workflows/publish.yml +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/.gitignore +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/.readthedocs.yaml +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/BADGE_SETUP.md +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/LICENSE +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/README.md +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/.gitignore +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/Makefile +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/api/modules.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/architectural_fixes.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/architecture.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/archive/DOCUMENTATION_AUDIT.md +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/archive/DOCUMENTATION_FIXES.md +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/archive/README.md +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/conf.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/examples/atomic_operations.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/examples/basic.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/examples/dual_axis.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/examples/index.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/examples/ui.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/index.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/make.bat +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/performance/canonical-context-type-resolution-20261005.json +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/quickstart.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/state_management.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/state_propagation.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/docs/undo_redo.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/paper.bib +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/paper.md +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/plans/n_dimensional_inheritance.md +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/pyproject.toml +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/scripts/check_ruff_added_lines.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/scripts/release.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/scripts/update_and_release.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/scripts/update_version.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/scripts/verify_release_ready.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/codegen.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/collection_containers.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/config.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/construction_binding.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/docs/configuration_framework.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/docs/object_state_lifecycle.rst +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/edit_session.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/field_access.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/global_config.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/inspection.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/object_state_metadata.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/parameter_owner.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/parameter_structure.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/parametric_axes.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/placeholder.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/reified_generics.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/scope_key.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/snapshot_model.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/subfield_semantics.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/time_travel_profile.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/token_cache.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/transaction_checkpoint.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/ui_visibility.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/src/objectstate/value_semantics.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/__init__.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/conftest.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_authored_paths.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_codegen.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_config.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_construction_history.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_field_access.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_global_config.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_history_persistence.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_inspection.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_integration.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_lazy_factory.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_object_state_restore.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_parameter_owner.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_parametric_axes.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_placeholder.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_registry_subscription.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_reified_generics.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_release_readiness.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_resolved_change_notifications.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_scope_key.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_subfield_semantics.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_timeline_projection.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_transaction_checkpoint.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_ui_visible_field_projection.py +0 -0
- {objectstate-2.1.0 → objectstate-3.0.0}/tests/test_value_semantics.py +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage:
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 75.78%"><title>coverage: 75.78%</title><filter id="blur"><feGaussianBlur stdDeviation="16"/></filter><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="114" height="20" rx="3"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="53" height="20" fill="#67ac09"/><rect width="114" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="315" y="150" fill-opacity=".8" filter="url(#blur)" textLength="510">coverage</text><text x="315" y="150" fill-opacity=".3" textLength="510">coverage</text></g><text x="315" y="140" textLength="510">coverage</text></g><g transform="scale(.1)"><g aria-hidden="true" fill="#010101"><text x="865" y="150" fill-opacity=".8" filter="url(#blur)" textLength="430">75.78%</text><text x="865" y="150" fill-opacity=".3" textLength="430">75.78%</text></g><text x="865" y="140" textLength="430">75.78%</text></g></g></svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: objectstate
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: Generic lazy dataclass configuration framework with dual-axis inheritance and contextvars-based resolution
|
|
5
5
|
Project-URL: Homepage, https://github.com/OpenHCSDev/objectstate
|
|
6
6
|
Project-URL: Documentation, https://objectstate.readthedocs.io
|
|
@@ -77,6 +77,11 @@ Get the source scope_id and type for an inherited field value:
|
|
|
77
77
|
else:
|
|
78
78
|
print("partition_filter is explicitly set on this object")
|
|
79
79
|
|
|
80
|
+
When another config of the same object supplies the value, the source scope is the
|
|
81
|
+
state's own ``scope_id``. For a state created without a scope id that is ``None``, so
|
|
82
|
+
``(None, source_type)`` means "this object, through ``source_type``". ``None`` alone
|
|
83
|
+
still means the value is set on the field itself.
|
|
84
|
+
|
|
80
85
|
**Returns:**
|
|
81
86
|
* ``Tuple[str, type]`` if the value is inherited
|
|
82
87
|
* ``None`` if the value is explicitly set on the current object
|
|
@@ -86,7 +91,8 @@ Get the source scope_id and type for an inherited field value:
|
|
|
86
91
|
resolve_with_provenance()
|
|
87
92
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
88
93
|
|
|
89
|
-
Resolve a field
|
|
94
|
+
Resolve a field in the active context. This is the one resolution: attribute access on a
|
|
95
|
+
lazy config returns its ``value``, and ``ObjectState`` stores all three parts.
|
|
90
96
|
|
|
91
97
|
.. code-block:: python
|
|
92
98
|
|
|
@@ -109,11 +115,21 @@ Resolve a field value AND find its provenance source in ONE walk:
|
|
|
109
115
|
|
|
110
116
|
**Returns:**
|
|
111
117
|
|
|
118
|
+
A ``ResolvedField`` named tuple:
|
|
119
|
+
|
|
112
120
|
* ``value``: The resolved field value (may be ``None``)
|
|
113
|
-
* ``source_scope``: The
|
|
114
|
-
|
|
121
|
+
* ``source_scope``: The scope id of the layer that supplied the value. ``None`` for a layer
|
|
122
|
+
entered with ``config_context(obj)`` without a ``scope_id``.
|
|
123
|
+
* ``source_type``: The type the value was read from: the container type or one of its bases.
|
|
124
|
+
|
|
125
|
+
When no layer holds a value, ``value`` is the declared default and the source names the
|
|
126
|
+
outermost layer holding the nearest type in the MRO (``None`` when no layer holds one).
|
|
115
127
|
|
|
116
|
-
|
|
128
|
+
Raises ``NoActiveContextError`` when no context is active.
|
|
129
|
+
|
|
130
|
+
**Caching:** the answer is kept on the layer stack it was computed from
|
|
131
|
+
(``ContextLayerStack.resolved_fields``) and is dropped with that stack. Entering or leaving a
|
|
132
|
+
context, in this thread or another, never clears another context's answers.
|
|
117
133
|
|
|
118
134
|
get_field_provenance()
|
|
119
135
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -142,13 +158,14 @@ The provenance system uses the context layer stack for tracking:
|
|
|
142
158
|
|
|
143
159
|
from objectstate.context_manager import get_context_layer_stack
|
|
144
160
|
|
|
145
|
-
|
|
146
|
-
layers
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
# Used by get_field_provenance() to determine which scope provided a resolved value
|
|
161
|
+
stack = get_context_layer_stack()
|
|
162
|
+
for layer in stack.layers: # outermost first
|
|
163
|
+
print(layer.scope_id, layer.obj)
|
|
150
164
|
|
|
151
|
-
The
|
|
165
|
+
The stack holds one ``ContextLayer`` for every object entered with ``config_context()``, with or
|
|
166
|
+
without a scope id, above the global config the context started from (scope ``""``). It is the
|
|
167
|
+
value ``resolve_with_provenance()`` reads. A layer entered with ``mask_with_none=True`` hides the
|
|
168
|
+
layers outside it.
|
|
152
169
|
|
|
153
170
|
Usage Examples
|
|
154
171
|
--------------
|
|
@@ -285,7 +302,7 @@ How Provenance Works
|
|
|
285
302
|
|
|
286
303
|
The provenance system works through these mechanisms:
|
|
287
304
|
|
|
288
|
-
1. **Context Layer Stack**: The ``config_context()`` manager
|
|
305
|
+
1. **Context Layer Stack**: The ``config_context()`` manager adds a ``ContextLayer`` for every object entered.
|
|
289
306
|
|
|
290
307
|
2. **Dual-Axis Resolution with Provenance**: When resolving inherited fields, ``resolve_with_provenance()`` walks both the MRO and context hierarchy, returning the first concrete value found along with its source information.
|
|
291
308
|
|
|
@@ -78,15 +78,14 @@ from objectstate.lazy_factory import (
|
|
|
78
78
|
|
|
79
79
|
# Resolver
|
|
80
80
|
from objectstate.dual_axis_resolver import (
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
ResolvedField,
|
|
82
|
+
resolve_with_provenance,
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
# Context
|
|
86
86
|
from objectstate.context_manager import (
|
|
87
87
|
config_context,
|
|
88
88
|
get_current_temp_global,
|
|
89
|
-
set_current_temp_global,
|
|
90
89
|
clear_current_temp_global,
|
|
91
90
|
merge_configs,
|
|
92
91
|
extract_all_configs,
|
|
@@ -168,12 +167,11 @@ __all__ = [
|
|
|
168
167
|
'is_global_config_type',
|
|
169
168
|
'is_global_config_instance',
|
|
170
169
|
# Resolver
|
|
171
|
-
'
|
|
172
|
-
'
|
|
170
|
+
'ResolvedField',
|
|
171
|
+
'resolve_with_provenance',
|
|
173
172
|
# Context
|
|
174
173
|
'config_context',
|
|
175
174
|
'get_current_temp_global',
|
|
176
|
-
'set_current_temp_global',
|
|
177
175
|
'clear_current_temp_global',
|
|
178
176
|
'merge_configs',
|
|
179
177
|
'extract_all_configs',
|
|
@@ -212,7 +210,7 @@ __all__ = [
|
|
|
212
210
|
'ObjectStateEditSession',
|
|
213
211
|
]
|
|
214
212
|
|
|
215
|
-
__version__ = "
|
|
213
|
+
__version__ = "3.0.0"
|
|
216
214
|
__author__ = 'OpenHCS Team'
|
|
217
215
|
__description__ = 'Generic configuration framework for lazy dataclass resolution'
|
|
218
216
|
|