# NexPy β Transitive Synchronization and Shared-State Fusion for Python
**NexPy** (distributed on PyPI as `nexpylib`) is a reactive synchronization framework for Python that provides a universal mechanism for maintaining coherent shared state across independent objects through **Nexus fusion** and **internal Hook synchronization**.
[](https://pypi.org/project/nexpylib/)
[](https://pypi.org/project/nexpylib/)
[](https://github.com/babrandes/nexpylib/blob/main/LICENSE)
---
## π― Core Concept: Inter-Object Synchronization via Nexus Fusion
Unlike traditional reactive frameworks that propagate changes through dependency graphs, NexPy creates **fusion domains** where multiple hooks share a single **Nexus**βa centralized synchronization core that holds and propagates state.
### What is a Nexus?
A **Nexus** is a shared synchronization core that represents a fusion domain. Each Hook in NexPy references a Nexus, but **does not own it**βinstead, multiple hooks may share the same Nexus, forming a dynamic network of coherence.
### What is Nexus Fusion?
When two hooks are **joined**, their respective Nexuses undergo a **fusion process**:
1. **Original Nexuses are destroyed** β Both hooks' previous Nexuses cease to exist
2. **New unified Nexus is created** β A single Nexus is created to hold the shared value
3. **Both hooks join the same fusion domain** β They now share synchronized state
This joining is:
- **Symmetric** β `A.join(B)` is equivalent to `B.join(A)`
- **Transitive** β Joining creates equivalence chains across all connected hooks
- **Non-directional** β There's no "master" or "slave"; all hooks are equal participants
### Transitive Synchronization Example
```python
import nexpy as nx
A = nx.Hook(1)
B = nx.Hook(2)
C = nx.Hook(3)
D = nx.Hook(4)
# Create first fusion domain
A.join(B) # β creates Nexus_AB containing A and B
# Create second fusion domain
C.join(D) # β creates Nexus_CD containing C and D
# Fuse both domains by connecting any pair
B.join(C) # β fuses both domains β Nexus_ABCD
# All four hooks now share the same Nexus and value
# Even though A and D were never joined directly!
print(A.value, B.value, C.value, D.value) # All have the same value
# Changing any hook updates all hooks in the fusion domain
A.value = 42
print(A.value, B.value, C.value, D.value) # 42 42 42 42
```
### Hook Isolation
A hook can later be **isolated**, which:
- Removes it from its current fusion domain
- Creates a new, independent Nexus initialized with the hook's current value
- Leaves remaining hooks still joined and synchronized
```python
import nexpy as nx
A = nx.Hook(1)
B = nx.Hook(1)
C = nx.Hook(1)
A.join(B)
B.join(C)
# All share Nexus_ABC
B.isolate()
# B now has a fresh Nexus_B
# A and C remain joined via Nexus_AC
A.value = 10
print(A.value, B.value, C.value) # 10 1 10
```
---
## βοΈ Internal Synchronization: Intra-Object Coherence
In addition to global fusion, NexPy maintains **atomic internal synchronization** among related hooks within a single object through a **transaction-like validation and update protocol**.
### Example: XDictSelect β Multi-Hook Atomic Synchronization
`XDictSelect` exposes **5 synchronized hooks**: `dict`, `keys`, `values`, `key`, and `value`.
```python
import nexpy as nx
# Create a selection dict that maintains consistency between
# the dict, selected key, and corresponding value
select = nx.XDictSelect({"a": 1, "b": 2, "c": 3}, key="a")
# All hooks are synchronized
print(select.dict_hook.value) # {"a": 1, "b": 2, "c": 3}
print(select.key_hook.value) # "a"
print(select.value_hook.value) # 1
# Changing the key automatically updates the value
select.key = "b"
print(select.value) # 2
# Changing the value updates the dictionary
select.value = 20
print(select.dict) # {"a": 1, "b": 20, "c": 3}
# All changes maintain invariants atomically
```
### The Internal Synchronization Protocol
When one hook changes (e.g., `key`), NexPy:
1. **Determines affected Nexuses** β Which related Nexuses must update (e.g., `value`, `dict`)
2. **Readiness check (validation pre-step)** β Queries each affected Nexus via validation callbacks
3. **Atomic update** β If all Nexuses report readiness, applies all updates in one transaction
4. **Rejection** β Otherwise rejects the change to maintain global validity
This ensures the system is:
- **Atomic** β All updates occur together or not at all
- **Consistent** β Constraints are always satisfied
- **Isolated** β Concurrent modifications are safely locked
- **Durable (logical)** β Once accepted, coherence persists until the next explicit change
NexPy guarantees **continuous validity** both within objects (internal sync) and across objects (Nexus fusion).
---
## π Quick Start
### Installation
```bash
pip install nexpylib
```
### Basic Usage
#### 1. Simple Reactive Value
```python
import nexpy as nx
# Create a reactive value
value = nx.XValue(42)
# Read the value
print(value.value) # 42
# Update the value
value.value = 100
print(value.value) # 100
# Add a listener that reacts to changes
def on_change():
print(f"Value changed to: {value.value}")
value.value_hook.add_listener(on_change)
value.value = 200 # Prints: "Value changed to: 200"
```
#### 2. Hook Fusion Across Independent Objects
```python
import nexpy as nx
# Create two independent reactive values
temperature_sensor = nx.XValue(20.0)
display_value = nx.XValue(0.0)
# Fuse them so they share the same state
temperature_sensor.value_hook.join(display_value.value_hook)
# Now they're synchronized
print(temperature_sensor.value, display_value.value) # 20.0 20.0
# Changing one updates the other
temperature_sensor.value = 25.5
print(display_value.value) # 25.5
```
#### 3. Reactive Collections
```python
import nexpy as nx
# Reactive list
numbers = nx.XList([1, 2, 3])
numbers.list_hook.add_listener(lambda: print(f"List changed: {numbers.list}"))
numbers.append(4) # Prints: "List changed: [1, 2, 3, 4]"
# Reactive set
tags = nx.XSet({"python", "reactive"})
tags.add("framework")
print(tags.set) # {"python", "reactive", "framework"}
# Reactive dict
config = nx.XDict({"debug": False, "version": "1.0"})
config["debug"] = True
print(config.dict) # {"debug": True, "version": "1.0"}
```
#### 4. Selection Objects with Internal Synchronization
```python
import nexpy as nx
# Create a selection from a dictionary
options = nx.XDictSelect(
{"low": 1, "medium": 5, "high": 10},
key="medium"
)
print(options.key) # "medium"
print(options.value) # 5
# Change selection
options.key = "high"
print(options.value) # 10 (automatically updated)
# Modify value (updates dict atomically)
options.value = 15
print(options.dict) # {"low": 1, "medium": 5, "high": 15}
```
#### 5. Custom Equality for Floating-Point Numbers
```python
import nexpy as nx
from nexpy.core.nexus_system.default_nexus_manager import DEFAULT_NEXUS_MANAGER
# Configure BEFORE creating any hooks or x_objects
# Standard practice: 1e-9 tolerance for floating-point equality
def float_equality(a: float, b: float) -> bool:
return abs(a - b) < 1e-9
DEFAULT_NEXUS_MANAGER.add_value_equality_callback((float, float), float_equality)
# Now floating-point comparisons use tolerance
temperature = nx.XValue(20.0)
temperature.value = 20.0000000001 # No update (within tolerance)
temperature.value = 20.001 # Update triggered (exceeds tolerance)
```
---
## π Key Features
### π Transitive Hook Fusion
- Join any hooks to create fusion domains
- Transitive synchronization: `AβB` + `BβC` = `AβBβC`
- Symmetric and non-directional connections
- Isolate hooks to break fusion domains
### βοΈ Atomic Internal Synchronization
- ACID-like guarantees for multi-hook objects
- Transaction-style validation and updates
- Automatic constraint maintenance
- Continuous validity enforcement
### π Reactive Collections
- `XList` β Reactive lists with element access
- `XSet` β Reactive sets with membership tracking
- `XDict` β Reactive dictionaries with key-value pairs
- Full Python collection protocol support
### π― Selection Objects
- `XDictSelect` β Select key-value pairs from dicts
- `XSetSelect` β Select elements from sets
- `XSetMultiSelect` β Multiple selection support
- Optional selection variants (allow `None` selection)
### π Thread-Safe by Design
- All operations protected by reentrant locks
- Safe concurrent access from multiple threads
- Reentrancy protection against recursive modifications
- Independent nested submissions allowed
### π Multiple Notification Philosophies
1. **Listeners (Synchronous)** β Direct callbacks during updates
2. **Publish-Subscribe (Asynchronous)** β Decoupled async notifications
3. **Hooks (Bidirectional Validation)** β Enforce constraints across objects
### π― Custom Equality Checks
- Register custom equality callbacks at the NexusManager level
- Standard practice: floating-point tolerance (e.g., 1e-9) to avoid spurious updates
- Cross-type comparison support (e.g., `float` vs `int`)
- Per-manager configuration for different precision requirements
---
## π Documentation
- **[Usage Guide](docs/usage.md)** β Join/isolate mechanics, Hook basics, Nexus fusion
- **[Internal Synchronization](docs/internal_sync.md)** β Atomic updates and validation protocol
- **[Architecture](docs/architecture.md)** β Design philosophy, data flow, locking
- **[API Reference](docs/api_reference.md)** β Complete API documentation
- **[Examples](docs/examples.md)** β Practical examples and runnable code
- **[Concepts](docs/concepts.md)** β Deep dive into fusion domains and synchronization
---
## ποΈ Architecture Overview
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β User Objects β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β
β β XValue β β XDict β β XList β β XSet β β
β ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ β
βββββββββΌββββββββββββββΌββββββββββββββΌββββββββββββββΌβββββββββββ
β β β β
βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ
β
βββββββββββββββββββ΄ββββββββββββββββββ
β Hook Layer β
β (Owned Hooks + Floating Hooks) β
βββββββββββββββββββ¬ββββββββββββββββββ
β
βββββββββββββββββββ΄ββββββββββββββββββ
β Nexus Layer β
β (Fusion Domains + Shared State) β
βββββββββββββββββββ¬ββββββββββββββββββ
β
βββββββββββββββββββ΄ββββββββββββββββββ
β NexusManager β
β (Coordination + Validation) β
βββββββββββββββββββββββββββββββββββββ
```
**Key Components:**
- **Hooks** β Connection points that reference Nexuses
- **Nexus** β Shared synchronization core for fusion domains
- **NexusManager** β Central coordinator for validation and updates
- **X Objects** β High-level reactive data structures
---
## π Use Cases
### 1. GUI Data Binding
```python
import nexpy as nx
# Model
user_name = nx.XValue("Alice")
# View (simulated)
class TextWidget:
def __init__(self, hook):
self.hook = hook
hook.add_listener(self.refresh)
def refresh(self):
print(f"Display: {self.hook.value}")
widget = TextWidget(user_name.value_hook)
# Changing model updates view automatically
user_name.value = "Bob" # Display: Bob
```
### 2. Configuration Synchronization
```python
import nexpy as nx
# Multiple configuration stores that stay in sync
app_config = nx.XDict({"theme": "dark", "lang": "en"})
cache_config = nx.XDict({})
# Fuse configuration hooks
cache_config.dict_hook.join(app_config.dict_hook)
# Both stay synchronized
app_config["theme"] = "light"
print(cache_config["theme"]) # "light"
```
### 3. State Machines with Atomic Transitions
```python
import nexpy as nx
states = {"idle", "running", "paused", "stopped"}
current = nx.XDictSelect(
{state: state for state in states},
key="idle"
)
def validate_transition(values):
# Add custom validation logic
if values["key"] == "running" and some_condition:
return False, "Cannot transition to running"
return True, "Valid"
# Transitions are atomic and validated
try:
current.key = "running"
except ValueError as e:
print(f"Transition rejected: {e}")
```
---
## π€ Contributing
Contributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
### Development Setup
```bash
# Clone the repository
git clone https://github.com/babrandes/nexpylib.git
cd nexpylib
# Install in development mode
pip install -e .
# Run tests
python -m pytest tests/
```
---
## π License
This project is licensed under the Apache License 2.0 β see the [LICENSE](LICENSE) file for details.
---
## π Links
- **PyPI**: [https://pypi.org/project/nexpylib/](https://pypi.org/project/nexpylib/)
- **GitHub**: [https://github.com/babrandes/nexpylib](https://github.com/babrandes/nexpylib)
- **Documentation**: [https://github.com/babrandes/nexpylib#readme](https://github.com/babrandes/nexpylib#readme)
- **Issue Tracker**: [https://github.com/babrandes/nexpylib/issues](https://github.com/babrandes/nexpylib/issues)
---
## π― Changelog
See [CHANGELOG.md](CHANGELOG.md) for a list of changes between versions.
---
## β Star History
If you find NexPy useful, please consider starring the repository on GitHub!
---
**Built with β€οΈ by Benedikt Axel Brandes**
Raw data
{
"_id": null,
"home_page": null,
"name": "nexpylib",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.13",
"maintainer_email": "Benedikt Axel Brandes <benedikt.brandes@me.com>",
"keywords": "reactive, binding, data-binding, synchronization, nexus, fusion, observable, gui, reactive-programming",
"author": null,
"author_email": "Benedikt Axel Brandes <benedikt.brandes@me.com>",
"download_url": "https://files.pythonhosted.org/packages/1d/e5/38c1e4ba2c6bf1492cb89732c6c00b764009ce98219444ad99d9764d0066/nexpylib-0.1.0.tar.gz",
"platform": null,
"description": "# NexPy \u2014 Transitive Synchronization and Shared-State Fusion for Python\n\n**NexPy** (distributed on PyPI as `nexpylib`) is a reactive synchronization framework for Python that provides a universal mechanism for maintaining coherent shared state across independent objects through **Nexus fusion** and **internal Hook synchronization**.\n\n[](https://pypi.org/project/nexpylib/)\n[](https://pypi.org/project/nexpylib/)\n[](https://github.com/babrandes/nexpylib/blob/main/LICENSE)\n\n---\n\n## \ud83c\udfaf Core Concept: Inter-Object Synchronization via Nexus Fusion\n\nUnlike traditional reactive frameworks that propagate changes through dependency graphs, NexPy creates **fusion domains** where multiple hooks share a single **Nexus**\u2014a centralized synchronization core that holds and propagates state.\n\n### What is a Nexus?\n\nA **Nexus** is a shared synchronization core that represents a fusion domain. Each Hook in NexPy references a Nexus, but **does not own it**\u2014instead, multiple hooks may share the same Nexus, forming a dynamic network of coherence.\n\n### What is Nexus Fusion?\n\nWhen two hooks are **joined**, their respective Nexuses undergo a **fusion process**:\n\n1. **Original Nexuses are destroyed** \u2014 Both hooks' previous Nexuses cease to exist\n2. **New unified Nexus is created** \u2014 A single Nexus is created to hold the shared value\n3. **Both hooks join the same fusion domain** \u2014 They now share synchronized state\n\nThis joining is:\n- **Symmetric** \u2014 `A.join(B)` is equivalent to `B.join(A)`\n- **Transitive** \u2014 Joining creates equivalence chains across all connected hooks\n- **Non-directional** \u2014 There's no \"master\" or \"slave\"; all hooks are equal participants\n\n### Transitive Synchronization Example\n\n```python\nimport nexpy as nx\n\nA = nx.Hook(1)\nB = nx.Hook(2)\nC = nx.Hook(3)\nD = nx.Hook(4)\n\n# Create first fusion domain\nA.join(B) # \u2192 creates Nexus_AB containing A and B\n\n# Create second fusion domain\nC.join(D) # \u2192 creates Nexus_CD containing C and D\n\n# Fuse both domains by connecting any pair\nB.join(C) # \u2192 fuses both domains \u2192 Nexus_ABCD\n\n# All four hooks now share the same Nexus and value\n# Even though A and D were never joined directly!\nprint(A.value, B.value, C.value, D.value) # All have the same value\n\n# Changing any hook updates all hooks in the fusion domain\nA.value = 42\nprint(A.value, B.value, C.value, D.value) # 42 42 42 42\n```\n\n### Hook Isolation\n\nA hook can later be **isolated**, which:\n- Removes it from its current fusion domain\n- Creates a new, independent Nexus initialized with the hook's current value\n- Leaves remaining hooks still joined and synchronized\n\n```python\nimport nexpy as nx\n\nA = nx.Hook(1)\nB = nx.Hook(1)\nC = nx.Hook(1)\n\nA.join(B)\nB.join(C)\n# All share Nexus_ABC\n\nB.isolate()\n# B now has a fresh Nexus_B\n# A and C remain joined via Nexus_AC\n\nA.value = 10\nprint(A.value, B.value, C.value) # 10 1 10\n```\n\n---\n\n## \u269b\ufe0f Internal Synchronization: Intra-Object Coherence\n\nIn addition to global fusion, NexPy maintains **atomic internal synchronization** among related hooks within a single object through a **transaction-like validation and update protocol**.\n\n### Example: XDictSelect \u2014 Multi-Hook Atomic Synchronization\n\n`XDictSelect` exposes **5 synchronized hooks**: `dict`, `keys`, `values`, `key`, and `value`.\n\n```python\nimport nexpy as nx\n\n# Create a selection dict that maintains consistency between\n# the dict, selected key, and corresponding value\nselect = nx.XDictSelect({\"a\": 1, \"b\": 2, \"c\": 3}, key=\"a\")\n\n# All hooks are synchronized\nprint(select.dict_hook.value) # {\"a\": 1, \"b\": 2, \"c\": 3}\nprint(select.key_hook.value) # \"a\"\nprint(select.value_hook.value) # 1\n\n# Changing the key automatically updates the value\nselect.key = \"b\"\nprint(select.value) # 2\n\n# Changing the value updates the dictionary\nselect.value = 20\nprint(select.dict) # {\"a\": 1, \"b\": 20, \"c\": 3}\n\n# All changes maintain invariants atomically\n```\n\n### The Internal Synchronization Protocol\n\nWhen one hook changes (e.g., `key`), NexPy:\n\n1. **Determines affected Nexuses** \u2014 Which related Nexuses must update (e.g., `value`, `dict`)\n2. **Readiness check (validation pre-step)** \u2014 Queries each affected Nexus via validation callbacks\n3. **Atomic update** \u2014 If all Nexuses report readiness, applies all updates in one transaction\n4. **Rejection** \u2014 Otherwise rejects the change to maintain global validity\n\nThis ensures the system is:\n- **Atomic** \u2014 All updates occur together or not at all\n- **Consistent** \u2014 Constraints are always satisfied\n- **Isolated** \u2014 Concurrent modifications are safely locked\n- **Durable (logical)** \u2014 Once accepted, coherence persists until the next explicit change\n\nNexPy guarantees **continuous validity** both within objects (internal sync) and across objects (Nexus fusion).\n\n---\n\n## \ud83d\ude80 Quick Start\n\n### Installation\n\n```bash\npip install nexpylib\n```\n\n### Basic Usage\n\n#### 1. Simple Reactive Value\n\n```python\nimport nexpy as nx\n\n# Create a reactive value\nvalue = nx.XValue(42)\n\n# Read the value\nprint(value.value) # 42\n\n# Update the value\nvalue.value = 100\nprint(value.value) # 100\n\n# Add a listener that reacts to changes\ndef on_change():\n print(f\"Value changed to: {value.value}\")\n\nvalue.value_hook.add_listener(on_change)\nvalue.value = 200 # Prints: \"Value changed to: 200\"\n```\n\n#### 2. Hook Fusion Across Independent Objects\n\n```python\nimport nexpy as nx\n\n# Create two independent reactive values\ntemperature_sensor = nx.XValue(20.0)\ndisplay_value = nx.XValue(0.0)\n\n# Fuse them so they share the same state\ntemperature_sensor.value_hook.join(display_value.value_hook)\n\n# Now they're synchronized\nprint(temperature_sensor.value, display_value.value) # 20.0 20.0\n\n# Changing one updates the other\ntemperature_sensor.value = 25.5\nprint(display_value.value) # 25.5\n```\n\n#### 3. Reactive Collections\n\n```python\nimport nexpy as nx\n\n# Reactive list\nnumbers = nx.XList([1, 2, 3])\nnumbers.list_hook.add_listener(lambda: print(f\"List changed: {numbers.list}\"))\n\nnumbers.append(4) # Prints: \"List changed: [1, 2, 3, 4]\"\n\n# Reactive set\ntags = nx.XSet({\"python\", \"reactive\"})\ntags.add(\"framework\")\nprint(tags.set) # {\"python\", \"reactive\", \"framework\"}\n\n# Reactive dict\nconfig = nx.XDict({\"debug\": False, \"version\": \"1.0\"})\nconfig[\"debug\"] = True\nprint(config.dict) # {\"debug\": True, \"version\": \"1.0\"}\n```\n\n#### 4. Selection Objects with Internal Synchronization\n\n```python\nimport nexpy as nx\n\n# Create a selection from a dictionary\noptions = nx.XDictSelect(\n {\"low\": 1, \"medium\": 5, \"high\": 10},\n key=\"medium\"\n)\n\nprint(options.key) # \"medium\"\nprint(options.value) # 5\n\n# Change selection\noptions.key = \"high\"\nprint(options.value) # 10 (automatically updated)\n\n# Modify value (updates dict atomically)\noptions.value = 15\nprint(options.dict) # {\"low\": 1, \"medium\": 5, \"high\": 15}\n```\n\n#### 5. Custom Equality for Floating-Point Numbers\n\n```python\nimport nexpy as nx\nfrom nexpy.core.nexus_system.default_nexus_manager import DEFAULT_NEXUS_MANAGER\n\n# Configure BEFORE creating any hooks or x_objects\n# Standard practice: 1e-9 tolerance for floating-point equality\ndef float_equality(a: float, b: float) -> bool:\n return abs(a - b) < 1e-9\n\nDEFAULT_NEXUS_MANAGER.add_value_equality_callback((float, float), float_equality)\n\n# Now floating-point comparisons use tolerance\ntemperature = nx.XValue(20.0)\ntemperature.value = 20.0000000001 # No update (within tolerance)\ntemperature.value = 20.001 # Update triggered (exceeds tolerance)\n```\n\n---\n\n## \ud83d\udcda Key Features\n\n### \ud83d\udd17 Transitive Hook Fusion\n- Join any hooks to create fusion domains\n- Transitive synchronization: `A\u2192B` + `B\u2192C` = `A\u2192B\u2192C`\n- Symmetric and non-directional connections\n- Isolate hooks to break fusion domains\n\n### \u269b\ufe0f Atomic Internal Synchronization\n- ACID-like guarantees for multi-hook objects\n- Transaction-style validation and updates\n- Automatic constraint maintenance\n- Continuous validity enforcement\n\n### \ud83d\udd04 Reactive Collections\n- `XList` \u2014 Reactive lists with element access\n- `XSet` \u2014 Reactive sets with membership tracking\n- `XDict` \u2014 Reactive dictionaries with key-value pairs\n- Full Python collection protocol support\n\n### \ud83c\udfaf Selection Objects\n- `XDictSelect` \u2014 Select key-value pairs from dicts\n- `XSetSelect` \u2014 Select elements from sets\n- `XSetMultiSelect` \u2014 Multiple selection support\n- Optional selection variants (allow `None` selection)\n\n### \ud83d\udd12 Thread-Safe by Design\n- All operations protected by reentrant locks\n- Safe concurrent access from multiple threads\n- Reentrancy protection against recursive modifications\n- Independent nested submissions allowed\n\n### \ud83c\udfad Multiple Notification Philosophies\n1. **Listeners (Synchronous)** \u2014 Direct callbacks during updates\n2. **Publish-Subscribe (Asynchronous)** \u2014 Decoupled async notifications\n3. **Hooks (Bidirectional Validation)** \u2014 Enforce constraints across objects\n\n### \ud83c\udfaf Custom Equality Checks\n- Register custom equality callbacks at the NexusManager level\n- Standard practice: floating-point tolerance (e.g., 1e-9) to avoid spurious updates\n- Cross-type comparison support (e.g., `float` vs `int`)\n- Per-manager configuration for different precision requirements\n\n---\n\n## \ud83d\udcd6 Documentation\n\n- **[Usage Guide](docs/usage.md)** \u2014 Join/isolate mechanics, Hook basics, Nexus fusion\n- **[Internal Synchronization](docs/internal_sync.md)** \u2014 Atomic updates and validation protocol\n- **[Architecture](docs/architecture.md)** \u2014 Design philosophy, data flow, locking\n- **[API Reference](docs/api_reference.md)** \u2014 Complete API documentation\n- **[Examples](docs/examples.md)** \u2014 Practical examples and runnable code\n- **[Concepts](docs/concepts.md)** \u2014 Deep dive into fusion domains and synchronization\n\n---\n\n## \ud83c\udfd7\ufe0f Architecture Overview\n\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 User Objects \u2502\n\u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n\u2502 \u2502 XValue \u2502 \u2502 XDict \u2502 \u2502 XList \u2502 \u2502 XSet \u2502 \u2502\n\u2502 \u2514\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502 \u2502 \u2502 \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 Hook Layer \u2502\n \u2502 (Owned Hooks + Floating Hooks) \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 Nexus Layer \u2502\n \u2502 (Fusion Domains + Shared State) \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 NexusManager \u2502\n \u2502 (Coordination + Validation) \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n**Key Components:**\n\n- **Hooks** \u2014 Connection points that reference Nexuses\n- **Nexus** \u2014 Shared synchronization core for fusion domains\n- **NexusManager** \u2014 Central coordinator for validation and updates\n- **X Objects** \u2014 High-level reactive data structures\n\n---\n\n## \ud83c\udf93 Use Cases\n\n### 1. GUI Data Binding\n\n```python\nimport nexpy as nx\n\n# Model\nuser_name = nx.XValue(\"Alice\")\n\n# View (simulated)\nclass TextWidget:\n def __init__(self, hook):\n self.hook = hook\n hook.add_listener(self.refresh)\n \n def refresh(self):\n print(f\"Display: {self.hook.value}\")\n\nwidget = TextWidget(user_name.value_hook)\n\n# Changing model updates view automatically\nuser_name.value = \"Bob\" # Display: Bob\n```\n\n### 2. Configuration Synchronization\n\n```python\nimport nexpy as nx\n\n# Multiple configuration stores that stay in sync\napp_config = nx.XDict({\"theme\": \"dark\", \"lang\": \"en\"})\ncache_config = nx.XDict({})\n\n# Fuse configuration hooks\ncache_config.dict_hook.join(app_config.dict_hook)\n\n# Both stay synchronized\napp_config[\"theme\"] = \"light\"\nprint(cache_config[\"theme\"]) # \"light\"\n```\n\n### 3. State Machines with Atomic Transitions\n\n```python\nimport nexpy as nx\n\nstates = {\"idle\", \"running\", \"paused\", \"stopped\"}\ncurrent = nx.XDictSelect(\n {state: state for state in states},\n key=\"idle\"\n)\n\ndef validate_transition(values):\n # Add custom validation logic\n if values[\"key\"] == \"running\" and some_condition:\n return False, \"Cannot transition to running\"\n return True, \"Valid\"\n\n# Transitions are atomic and validated\ntry:\n current.key = \"running\"\nexcept ValueError as e:\n print(f\"Transition rejected: {e}\")\n```\n\n---\n\n## \ud83e\udd1d Contributing\n\nContributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n### Development Setup\n\n```bash\n# Clone the repository\ngit clone https://github.com/babrandes/nexpylib.git\ncd nexpylib\n\n# Install in development mode\npip install -e .\n\n# Run tests\npython -m pytest tests/\n```\n\n---\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the Apache License 2.0 \u2014 see the [LICENSE](LICENSE) file for details.\n\n---\n\n## \ud83d\udd17 Links\n\n- **PyPI**: [https://pypi.org/project/nexpylib/](https://pypi.org/project/nexpylib/)\n- **GitHub**: [https://github.com/babrandes/nexpylib](https://github.com/babrandes/nexpylib)\n- **Documentation**: [https://github.com/babrandes/nexpylib#readme](https://github.com/babrandes/nexpylib#readme)\n- **Issue Tracker**: [https://github.com/babrandes/nexpylib/issues](https://github.com/babrandes/nexpylib/issues)\n\n---\n\n## \ud83c\udfaf Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for a list of changes between versions.\n\n---\n\n## \u2b50 Star History\n\nIf you find NexPy useful, please consider starring the repository on GitHub!\n\n---\n\n**Built with \u2764\ufe0f by Benedikt Axel Brandes**\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Transitive synchronization and shared-state fusion for Python through Nexus fusion and atomic internal synchronization",
"version": "0.1.0",
"project_urls": {
"Bug Tracker": "https://github.com/babrandes/nexpylib/issues",
"Documentation": "https://nexpylib.readthedocs.io/",
"Homepage": "https://github.com/babrandes/nexpylib",
"Repository": "https://github.com/babrandes/nexpylib.git"
},
"split_keywords": [
"reactive",
" binding",
" data-binding",
" synchronization",
" nexus",
" fusion",
" observable",
" gui",
" reactive-programming"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "72ff748ff5b7f52b34c6345cca12b9291501586c1b9844036297b9414a84303c",
"md5": "87457a2660bc2f213eeb437cedd7f5fc",
"sha256": "f0d0c17a886a064055ecae59e31421bc8c03cecf6cfc56fa7b6a16cb0ffd2c8a"
},
"downloads": -1,
"filename": "nexpylib-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "87457a2660bc2f213eeb437cedd7f5fc",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.13",
"size": 153546,
"upload_time": "2025-10-20T22:21:13",
"upload_time_iso_8601": "2025-10-20T22:21:13.800523Z",
"url": "https://files.pythonhosted.org/packages/72/ff/748ff5b7f52b34c6345cca12b9291501586c1b9844036297b9414a84303c/nexpylib-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "1de538c1e4ba2c6bf1492cb89732c6c00b764009ce98219444ad99d9764d0066",
"md5": "bf22372a2b44b8e535881ed13a6b6fe3",
"sha256": "5a06bd57ac315b7c2ac248160f42a6c68bca023537c73f2c3b550661a4de77c1"
},
"downloads": -1,
"filename": "nexpylib-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "bf22372a2b44b8e535881ed13a6b6fe3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.13",
"size": 191589,
"upload_time": "2025-10-20T22:21:15",
"upload_time_iso_8601": "2025-10-20T22:21:15.718802Z",
"url": "https://files.pythonhosted.org/packages/1d/e5/38c1e4ba2c6bf1492cb89732c6c00b764009ce98219444ad99d9764d0066/nexpylib-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-20 22:21:15",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "babrandes",
"github_project": "nexpylib",
"github_not_found": true,
"lcname": "nexpylib"
}