pynnex

PynneX

PynneX is a lightweight, pure-Python signal/slot library that provides thread-safe, asyncio-compatible event handling. It enables clean decoupling of components, seamless thread-to-thread communication, and flexible asynchronous/synchronous slot handling.

Key Features

Why PynneX?

Modern Python applications often rely on asynchronous operations and multi-threading. Traditional event frameworks either require large external dependencies or lack seamless async/thread support. PynneX provides:

Key Benefits

Async-Ready

Thread-Safe by Design

Flexible Slots

Robust Testing & Examples

Installation

PynneX requires Python 3.10 or higher. This requirement ensures stable asyncio operations, as Python 3.10 introduced important improvements including:

git clone https://github.com/nexconnectio/pynnex.git
cd pynnex
pip install -e .

For development (includes tests and linting tools):

pip install -e ".[dev]

Quick Start

Basic Example

from pynnex import with_signals, signal, slot

@with_signals
class Counter:
    def __init__(self):
        self.count = 0
    
    @signal
    def count_changed(self):
        pass
    
    def increment(self):
        self.count += 1
        self.count_changed.emit(self.count)

@with_signals
class Display:
    @slot
    async def on_count_changed(self, value):
        print(f"Count is now: {value}")

# Connect and use
counter = Counter()
display = Display()
counter.count_changed.connect(display, display.on_count_changed)
counter.increment()  # Will print: "Count is now: 1"

Asynchronous Slot Example

@with_signals
class AsyncDisplay:
    @slot
    async def on_count_changed(self, value):
        await asyncio.sleep(1)  # Simulate async operation
        print(f"Count updated to: {value}")

# Usage in async context
async def main():
    counter = Counter()
    display = AsyncDisplay()
    
    counter.count_changed.connect(display, display.on_count_changed)
    counter.increment()
    
    # Wait for async processing
    await asyncio.sleep(1.1)

asyncio.run(main())

Core Concepts

Signals and Slots

Thread Safety and Connection Types

PynneX automatically detects whether the signal emission and slot execution occur in the same thread or different threads:

This mechanism frees you from manually dispatching calls across threads.

Worker Threads

For background work, PynneX provides a @nx_with_worker decorator that:

Worker Example

from pynnex import with_worker, signal

@with_worker
class DataProcessor:
    @signal
    def processing_done(self):
        """Emitted when processing completes"""

    async def run(self, *args, **kwargs):
        # The main entry point for the worker thread’s event loop
        # Wait for tasks or stopping signal
        await self.wait_for_stop()

    async def process_data(self, data):
        # Perform heavy computation in the worker thread
        result = await heavy_computation(data)
        self.processing_done.emit(result)

processor = DataProcessor()
processor.start()

# Queue a task to run in the worker thread:
processor.queue_task(processor.process_data(some_data))

# Stop the worker gracefully
processor.stop()

From Basics to Practical Use Cases

We’ve expanded PynneX’s examples to guide you from simple demos to full-fledged applications. Each example has its own GitHub link with fully commented code.

For detailed explanations, code walkthroughs, and architecture diagrams of these examples, check out our Examples Documentation.

Basic Signal/Slot Examples

Multi-Threading and Workers

Stock Monitor (Console & GUI)

Stock Monitor Console

Stock Monitor Console: Real-time price updates, alert configuration, and notification history in action

Stock Monitor UI

Stock Monitor UI: Real-time price updates, alert configuration, and notification history in action

Together, these examples highlight PynneX’s versatility—covering everything from quick demos to production-like patterns with threads, queues, and reactive UI updates.

Documentation and Example

Get Started

  1. Visit the GitHub Repository
    • Find installation instructions, usage docs, and a variety of real-world examples.
  2. Try the Python Release
    • Run pip install pynnex (requires Python 3.10+).
    • Check out the docs and examples in the repository’s examples/ folder.
  3. Contribute / Give Feedback
    • We appreciate your thoughts on the current Python version.
    • We welcome contributions! Please read our Contributing Guidelines before submitting PRs.

License

PynneX is licensed under the MIT License. See LICENSE for details.