nexpylib


Namenexpylib JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryTransitive synchronization and shared-state fusion for Python through Nexus fusion and atomic internal synchronization
upload_time2025-10-20 22:21:15
maintainerNone
docs_urlNone
authorNone
requires_python>=3.13
licenseApache-2.0
keywords reactive binding data-binding synchronization nexus fusion observable gui reactive-programming
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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**.

[![PyPI version](https://img.shields.io/pypi/v/nexpylib.svg)](https://pypi.org/project/nexpylib/)
[![Python versions](https://img.shields.io/pypi/pyversions/nexpylib.svg)](https://pypi.org/project/nexpylib/)
[![License](https://img.shields.io/github/license/babrandes/nexpylib.svg)](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[![PyPI version](https://img.shields.io/pypi/v/nexpylib.svg)](https://pypi.org/project/nexpylib/)\n[![Python versions](https://img.shields.io/pypi/pyversions/nexpylib.svg)](https://pypi.org/project/nexpylib/)\n[![License](https://img.shields.io/github/license/babrandes/nexpylib.svg)](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"
}
        
Elapsed time: 1.93603s