py-udp-rust


Namepy-udp-rust JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummaryHigh-performance UDP networking library for Python with Rust backend
upload_time2025-08-04 09:41:47
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseMIT
keywords udp networking rust async socket server client
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # py-udp

High-performance UDP networking library for Python with Rust backend.

## Architecture

This project uses PyO3 to create a Python extension module from Rust code:

1. **Rust Implementation** - Core UDP functionality implemented in Rust using Tokio
2. **PyO3 Bindings** - Python bindings created with PyO3
3. **Python API** - User-friendly Python interface

### Why This Architecture?

- **Performance**: Core networking implemented in Rust for maximum performance
- **Safety**: Rust's memory safety and zero-cost abstractions
- **Integration**: Seamless Python integration through PyO3
- **Modern**: Uses Tokio for efficient async I/O

## Features

- **High Performance**: Core networking implemented in Rust for maximum performance
- **Easy to Use**: Simple Python API for UDP server and client operations
- **Async Support**: Built on Tokio runtime for efficient async I/O
- **Type Safe**: Full type hints and error handling
- **Cross Platform**: Works on Windows, macOS, and Linux
- **Message Handlers**: Flexible callback system for processing incoming messages
- **Thread Safety**: Safe concurrent access with proper synchronization

## Installation

### Prerequisites

- Python 3.12+
- Rust (latest stable version)
- Cargo (comes with Rust)
- uv (recommended package manager)

### Build and Install

1. Clone the repository:
```bash
git clone <repository-url>
cd py-udp
```

2. Build and install the package:
```bash
uv run maturin develop
```

### Alternative: Using the Build Script

```bash
uv run python build.py
```

This script will:
- Check prerequisites
- Install maturin
- Build the Rust extension
- Install the Python package
- Run tests

## Quick Start

### UDP Server

```python
from py_udp import UdpServer, MessageHandler

class MyHandler(MessageHandler):
    def __call__(self, data: bytes, source_address: str):
        print(f"Received from {source_address}: {data.decode()}")
        # Process the message...

# Create and start server
server = UdpServer(host="127.0.0.1", port=8888)
server.bind()
server.set_message_handler(MyHandler())
server.start()

# Keep server running
import time
while server.is_running():
    time.sleep(1)
```

### UDP Client

```python
from py_udp import UdpClient

# Create client
client = UdpClient()
client.bind()

# Send message
message = "Hello, UDP!".encode('utf-8')
bytes_sent = client.send_to(message, "127.0.0.1", 8888)
print(f"Sent {bytes_sent} bytes")

# Receive response
data, source = client.recv_from()
print(f"Received from {source}: {data.decode()}")
```

## Examples

### Echo Server

The echo server example demonstrates how to create a UDP server that responds to incoming messages:

```python
#!/usr/bin/env python3
"""
UDP Server Example

This example demonstrates how to create a UDP server that echoes back
received messages with additional information.
"""

import time
from py_udp import UdpServer, MessageHandler


class EchoHandler(MessageHandler):
    """Echo handler that responds to incoming messages."""
    
    def __init__(self, server: UdpServer):
        self.server = server
        self.message_count = 0
    
    def __call__(self, data, source_address: str) -> None:
        """Handle incoming message and send response."""
        # Convert data to bytes if it's a list
        if isinstance(data, list):
            data = bytes(data)
            
        self.message_count += 1
        
        # Decode message
        try:
            message = data.decode('utf-8')
        except UnicodeDecodeError:
            message = f"<binary data: {len(data)} bytes>"
        
        print(f"[{self.message_count}] Received from {source_address}: {message}")
        
        # Create response
        response = f"Echo #{self.message_count}: {message}"
        response_data = response.encode('utf-8')
        
        # Send response using the server's send_to method
        try:
            bytes_sent = self.server.send_to(response_data, source_address)
            print(f"Sent {bytes_sent} bytes to {source_address}")
        except Exception as e:
            print(f"Error sending response: {e}")


def main():
    """Run UDP echo server."""
    print("Starting UDP Echo Server...")
    
    # Create server
    server = UdpServer(host="127.0.0.1", port=8888)
    
    # Bind to address
    server.bind()
    print(f"Server bound to {server.address}")
    
    # Set message handler
    handler = EchoHandler(server)
    server.set_message_handler(handler)
    
    # Start server
    server.start()
    print("Server started. Press Ctrl+C to stop.")
    
    try:
        # Keep server running
        while server.is_running():
            time.sleep(1)
    except KeyboardInterrupt:
        print("\nStopping server...")
        server.stop()
        print("Server stopped.")


if __name__ == "__main__":
    main()
```

Run the echo server example:

```bash
uv run python examples/server_example.py
```

### Echo Client

The echo client example demonstrates how to create a UDP client that sends messages and receives responses:

```python
#!/usr/bin/env python3
"""
UDP Client Example

This example demonstrates how to create a UDP client that sends messages
to a server and receives responses.
"""

import time
import threading
from py_udp import UdpClient


def receive_messages(client: UdpClient):
    """Receive messages in a separate thread."""
    print("Starting message receiver...")
    
    while True:
        try:
            # Add a small delay to avoid busy waiting
            time.sleep(0.1)
            
            data, source = client.recv_from()
            # Convert data to bytes if it's a list
            if isinstance(data, list):
                data = bytes(data)
            message = data.decode('utf-8')
            print(f"Received from {source}: {message}")
        except Exception as e:
            # Don't break on timeout errors
            if "timeout" not in str(e).lower():
                print(f"Error receiving message: {e}")
                break


def main():
    """Run UDP client."""
    print("Starting UDP Client...")
    
    # Create client
    client = UdpClient(host="127.0.0.1", port=0)
    
    # Bind to random port
    client.bind()
    print(f"Client bound to {client.address}")
    
    # Start receiver thread
    receiver_thread = threading.Thread(
        target=receive_messages, 
        args=(client,), 
        daemon=True
    )
    receiver_thread.start()
    
    # Server address
    server_host = "127.0.0.1"
    server_port = 8888
    
    print(f"Connecting to server at {server_host}:{server_port}")
    print("Sending messages automatically...")
    
    try:
        message_count = 0
        while True:
            message_count += 1
            
            # Create test message
            message = f"Hello, UDP! #{message_count}"
            data = message.encode('utf-8')
            
            # Send message
            try:
                bytes_sent = client.send_to(data, server_host, server_port)
                print(f"Sent: {message} ({bytes_sent} bytes)")
            except Exception as e:
                print(f"Error sending message: {e}")
            
            # Wait before sending next message
            time.sleep(2)
    
    except KeyboardInterrupt:
        print("\nStopping client...")
    
    print("Client stopped.")


if __name__ == "__main__":
    main()
```

In another terminal, run the client:

```bash
uv run python examples/client_example.py
```

The client will automatically send messages every 2 seconds and display received responses.

## Development

### Project Structure

```
py-udp/
├── src/                   # Rust source code
│   └── lib.rs            # Main Rust implementation
├── py_udp/               # Python package
│   ├── __init__.py       # Python API
│   └── ...
├── examples/             # Usage examples
│   ├── server_example.py # Echo server example
│   └── client_example.py # Echo client example
├── tests/                # Python tests
├── Cargo.toml           # Rust project config
├── pyproject.toml       # Python package config
└── README.md
```

### Working with Rust Code

```bash
# Build Rust extension
uv run maturin develop

# Run Rust tests
cargo test

# Run specific test suites
cargo test --test test_udp        # Unit tests
cargo test --test integration_udp # Integration tests

# Run with debug output
RUST_LOG=debug cargo test

# Check code coverage
cargo tarpaulin --skip-clean
```

### Working with Python Package

```bash
# Install in development mode
uv run maturin develop

# Run Python tests
uv run pytest tests/

# Run tests with coverage
uv run pytest tests/ --cov=py_udp --cov-report=term-missing

# Run specific test classes
uv run pytest tests/ -k TestUdpServer
uv run pytest tests/ -k TestUdpClient

# Format code
uv run black .
uv run isort .
```

### Running Tests

#### Rust Tests

```bash
# Run all Rust tests (unit + integration)
cargo test

# Run only unit tests
cargo test --lib

# Run only integration tests
cargo test --test integration_udp
cargo test --test test_udp

# Run with debug output
RUST_LOG=debug cargo test
```

**Rust Test Coverage:**
- **Unit Tests**: 19 tests in `tests/test_udp.rs`
- **Integration Tests**: 10 tests in `tests/integration_udp.rs`
- **Coverage**: 33.08% (44/133 lines covered)

#### Python Tests

```bash
# Run Python tests
uv run pytest tests/

# Run with coverage report
uv run pytest tests/ --cov=py_udp --cov-report=term-missing

# Run with verbose output
uv run pytest tests/ -v
```

**Python Test Coverage:**
- **Total Tests**: 26 tests
- **Coverage**: 91% (83/91 lines covered)
- **Missing Lines**: 15-16, 79, 109, 127-130, 188

#### Test Structure

**Rust Tests (`tests/` directory):**
- `test_udp.rs` - Unit tests for core Rust functionality
  - Server/client creation and initialization
  - Binding and address validation
  - Error handling and edge cases
  - Basic UDP operations
- `integration_udp.rs` - Integration tests for UDP communication
  - Client-server echo communication
  - Invalid address handling
  - Multiple message sending
  - Server lifecycle management

**Python Tests (`tests/test_udp.py`):**
- `TestMessageHandler` - Message handler base class tests
- `TestUdpServer` - Server functionality tests
- `TestUdpClient` - Client functionality tests
- `TestConvenienceFunctions` - Utility function tests
- `TestUdpCommunication` - End-to-end communication tests

#### Coverage Analysis

**Rust Coverage (33.08%):**
- **Covered**: Basic initialization, binding, error handling
- **Uncovered**: Python GIL-dependent methods, async server logic, PyO3 wrappers
- **Limitations**: Python interpreter not available in Rust-only tests

**Python Coverage (91%):**
- **Covered**: All public API methods, error handling, communication
- **Missing**: Some edge cases and error conditions
- **Strength**: Full integration testing with real UDP communication

#### Coverage Commands

```bash
# Rust coverage with cargo-tarpaulin
cargo install cargo-tarpaulin
cargo tarpaulin --skip-clean
cargo tarpaulin --out Html --output-dir coverage

# Python coverage with pytest-cov
uv run pytest tests/ --cov=py_udp --cov-report=html
uv run pytest tests/ --cov=py_udp --cov-report=term-missing
```

## API Reference

### UdpServer

#### Constructor
```python
UdpServer(host: str = "0.0.0.0", port: int = 0)
```

#### Methods
- `bind(host: Optional[str] = None, port: Optional[int] = None) -> None`
  - Bind the server to a specific address and port
- `set_message_handler(handler: Union[MessageHandler, Callable]) -> None`
  - Set the message handler for processing incoming messages
- `start() -> None`
  - Start the server and begin listening for messages
- `stop() -> None`
  - Stop the server and clean up resources
- `is_running() -> bool`
  - Check if the server is currently running
- `send_to(data: bytes, address: str) -> int`
  - Send data to a specific address (host:port format)

#### Properties
- `address: Tuple[str, int]` - Server address

### UdpClient

#### Constructor
```python
UdpClient(host: str = "0.0.0.0", port: int = 0)
```

#### Methods
- `bind(host: Optional[str] = None, port: Optional[int] = None) -> None`
  - Bind the client to a specific address and port
- `send_to(data: bytes, host: str, port: int) -> int`
  - Send data to a specific host and port
- `recv_from() -> Tuple[bytes, str]`
  - Receive data from any address

#### Properties
- `address: Tuple[str, int]` - Client address

### MessageHandler

Base class for handling incoming UDP messages:

```python
class MyHandler(MessageHandler):
    def __call__(self, data: bytes, source_address: str) -> None:
        # Handle the message
        # data: received data as bytes
        # source_address: source address as string (host:port)
        pass
```

## Performance

The Rust backend provides significant performance improvements over pure Python implementations:

- **Lower Latency**: Direct system calls without Python GIL overhead
- **Higher Throughput**: Efficient async I/O with Tokio
- **Memory Efficiency**: Zero-copy operations where possible
- **Concurrent Processing**: True parallelism for multiple connections
- **Channel-based Communication**: Non-blocking message passing between Rust and Python

## Troubleshooting

### Common Issues

1. **Import Error**: Make sure the Rust extension is built with `uv run maturin develop`
2. **Permission Denied**: Check if the port is already in use or requires elevated privileges
3. **Build Errors**: Ensure you have the latest Rust toolchain installed
4. **Runtime Errors**: Make sure the server is started before calling `send_to()`

### Debug Mode

Enable debug logging for Rust:

```bash
export RUST_LOG=debug
cargo test
```

### Testing the Installation

Run a simple test to verify everything works:

```bash
uv run python -c "from py_udp import UdpServer, UdpClient; print('✅ Installation successful!')"
```

## License

MIT License - see LICENSE file for details.

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for both Rust and Python
5. Run tests and linting
6. Submit a pull request

### Development Workflow

1. **Rust Changes**: Work in `src/` directory
   - Add unit tests in `tests/test_udp.rs`
   - Add integration tests in `tests/integration_udp.rs`
   - Run `cargo test` to verify changes
   - Check coverage with `cargo tarpaulin`

2. **Python Changes**: Work in `py_udp/` directory
   - Add tests in `tests/test_udp.py`
   - Run `uv run pytest tests/` to verify changes
   - Check coverage with `uv run pytest tests/ --cov=py_udp`

3. **Integration**: Test both components work together
   - Run both Rust and Python test suites
   - Test examples in `examples/` directory
   - Verify end-to-end functionality

4. **Documentation**: Update README and docstrings
5. **Examples**: Update examples in `examples/` directory

### Code Style

- **Rust**: Follow Rust formatting guidelines with `cargo fmt`
- **Python**: Use Black for formatting and isort for imports
- **Documentation**: Keep docstrings up to date
- **Tests**: Maintain good test coverage for both Rust and Python 

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "py-udp-rust",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": "Ravil Shakerov <xellaopromaster@yandex.ru>",
    "keywords": "udp, networking, rust, async, socket, server, client",
    "author": null,
    "author_email": "Ravil Shakerov <xellaopromaster@yandex.ru>",
    "download_url": null,
    "platform": null,
    "description": "# py-udp\r\n\r\nHigh-performance UDP networking library for Python with Rust backend.\r\n\r\n## Architecture\r\n\r\nThis project uses PyO3 to create a Python extension module from Rust code:\r\n\r\n1. **Rust Implementation** - Core UDP functionality implemented in Rust using Tokio\r\n2. **PyO3 Bindings** - Python bindings created with PyO3\r\n3. **Python API** - User-friendly Python interface\r\n\r\n### Why This Architecture?\r\n\r\n- **Performance**: Core networking implemented in Rust for maximum performance\r\n- **Safety**: Rust's memory safety and zero-cost abstractions\r\n- **Integration**: Seamless Python integration through PyO3\r\n- **Modern**: Uses Tokio for efficient async I/O\r\n\r\n## Features\r\n\r\n- **High Performance**: Core networking implemented in Rust for maximum performance\r\n- **Easy to Use**: Simple Python API for UDP server and client operations\r\n- **Async Support**: Built on Tokio runtime for efficient async I/O\r\n- **Type Safe**: Full type hints and error handling\r\n- **Cross Platform**: Works on Windows, macOS, and Linux\r\n- **Message Handlers**: Flexible callback system for processing incoming messages\r\n- **Thread Safety**: Safe concurrent access with proper synchronization\r\n\r\n## Installation\r\n\r\n### Prerequisites\r\n\r\n- Python 3.12+\r\n- Rust (latest stable version)\r\n- Cargo (comes with Rust)\r\n- uv (recommended package manager)\r\n\r\n### Build and Install\r\n\r\n1. Clone the repository:\r\n```bash\r\ngit clone <repository-url>\r\ncd py-udp\r\n```\r\n\r\n2. Build and install the package:\r\n```bash\r\nuv run maturin develop\r\n```\r\n\r\n### Alternative: Using the Build Script\r\n\r\n```bash\r\nuv run python build.py\r\n```\r\n\r\nThis script will:\r\n- Check prerequisites\r\n- Install maturin\r\n- Build the Rust extension\r\n- Install the Python package\r\n- Run tests\r\n\r\n## Quick Start\r\n\r\n### UDP Server\r\n\r\n```python\r\nfrom py_udp import UdpServer, MessageHandler\r\n\r\nclass MyHandler(MessageHandler):\r\n    def __call__(self, data: bytes, source_address: str):\r\n        print(f\"Received from {source_address}: {data.decode()}\")\r\n        # Process the message...\r\n\r\n# Create and start server\r\nserver = UdpServer(host=\"127.0.0.1\", port=8888)\r\nserver.bind()\r\nserver.set_message_handler(MyHandler())\r\nserver.start()\r\n\r\n# Keep server running\r\nimport time\r\nwhile server.is_running():\r\n    time.sleep(1)\r\n```\r\n\r\n### UDP Client\r\n\r\n```python\r\nfrom py_udp import UdpClient\r\n\r\n# Create client\r\nclient = UdpClient()\r\nclient.bind()\r\n\r\n# Send message\r\nmessage = \"Hello, UDP!\".encode('utf-8')\r\nbytes_sent = client.send_to(message, \"127.0.0.1\", 8888)\r\nprint(f\"Sent {bytes_sent} bytes\")\r\n\r\n# Receive response\r\ndata, source = client.recv_from()\r\nprint(f\"Received from {source}: {data.decode()}\")\r\n```\r\n\r\n## Examples\r\n\r\n### Echo Server\r\n\r\nThe echo server example demonstrates how to create a UDP server that responds to incoming messages:\r\n\r\n```python\r\n#!/usr/bin/env python3\r\n\"\"\"\r\nUDP Server Example\r\n\r\nThis example demonstrates how to create a UDP server that echoes back\r\nreceived messages with additional information.\r\n\"\"\"\r\n\r\nimport time\r\nfrom py_udp import UdpServer, MessageHandler\r\n\r\n\r\nclass EchoHandler(MessageHandler):\r\n    \"\"\"Echo handler that responds to incoming messages.\"\"\"\r\n    \r\n    def __init__(self, server: UdpServer):\r\n        self.server = server\r\n        self.message_count = 0\r\n    \r\n    def __call__(self, data, source_address: str) -> None:\r\n        \"\"\"Handle incoming message and send response.\"\"\"\r\n        # Convert data to bytes if it's a list\r\n        if isinstance(data, list):\r\n            data = bytes(data)\r\n            \r\n        self.message_count += 1\r\n        \r\n        # Decode message\r\n        try:\r\n            message = data.decode('utf-8')\r\n        except UnicodeDecodeError:\r\n            message = f\"<binary data: {len(data)} bytes>\"\r\n        \r\n        print(f\"[{self.message_count}] Received from {source_address}: {message}\")\r\n        \r\n        # Create response\r\n        response = f\"Echo #{self.message_count}: {message}\"\r\n        response_data = response.encode('utf-8')\r\n        \r\n        # Send response using the server's send_to method\r\n        try:\r\n            bytes_sent = self.server.send_to(response_data, source_address)\r\n            print(f\"Sent {bytes_sent} bytes to {source_address}\")\r\n        except Exception as e:\r\n            print(f\"Error sending response: {e}\")\r\n\r\n\r\ndef main():\r\n    \"\"\"Run UDP echo server.\"\"\"\r\n    print(\"Starting UDP Echo Server...\")\r\n    \r\n    # Create server\r\n    server = UdpServer(host=\"127.0.0.1\", port=8888)\r\n    \r\n    # Bind to address\r\n    server.bind()\r\n    print(f\"Server bound to {server.address}\")\r\n    \r\n    # Set message handler\r\n    handler = EchoHandler(server)\r\n    server.set_message_handler(handler)\r\n    \r\n    # Start server\r\n    server.start()\r\n    print(\"Server started. Press Ctrl+C to stop.\")\r\n    \r\n    try:\r\n        # Keep server running\r\n        while server.is_running():\r\n            time.sleep(1)\r\n    except KeyboardInterrupt:\r\n        print(\"\\nStopping server...\")\r\n        server.stop()\r\n        print(\"Server stopped.\")\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    main()\r\n```\r\n\r\nRun the echo server example:\r\n\r\n```bash\r\nuv run python examples/server_example.py\r\n```\r\n\r\n### Echo Client\r\n\r\nThe echo client example demonstrates how to create a UDP client that sends messages and receives responses:\r\n\r\n```python\r\n#!/usr/bin/env python3\r\n\"\"\"\r\nUDP Client Example\r\n\r\nThis example demonstrates how to create a UDP client that sends messages\r\nto a server and receives responses.\r\n\"\"\"\r\n\r\nimport time\r\nimport threading\r\nfrom py_udp import UdpClient\r\n\r\n\r\ndef receive_messages(client: UdpClient):\r\n    \"\"\"Receive messages in a separate thread.\"\"\"\r\n    print(\"Starting message receiver...\")\r\n    \r\n    while True:\r\n        try:\r\n            # Add a small delay to avoid busy waiting\r\n            time.sleep(0.1)\r\n            \r\n            data, source = client.recv_from()\r\n            # Convert data to bytes if it's a list\r\n            if isinstance(data, list):\r\n                data = bytes(data)\r\n            message = data.decode('utf-8')\r\n            print(f\"Received from {source}: {message}\")\r\n        except Exception as e:\r\n            # Don't break on timeout errors\r\n            if \"timeout\" not in str(e).lower():\r\n                print(f\"Error receiving message: {e}\")\r\n                break\r\n\r\n\r\ndef main():\r\n    \"\"\"Run UDP client.\"\"\"\r\n    print(\"Starting UDP Client...\")\r\n    \r\n    # Create client\r\n    client = UdpClient(host=\"127.0.0.1\", port=0)\r\n    \r\n    # Bind to random port\r\n    client.bind()\r\n    print(f\"Client bound to {client.address}\")\r\n    \r\n    # Start receiver thread\r\n    receiver_thread = threading.Thread(\r\n        target=receive_messages, \r\n        args=(client,), \r\n        daemon=True\r\n    )\r\n    receiver_thread.start()\r\n    \r\n    # Server address\r\n    server_host = \"127.0.0.1\"\r\n    server_port = 8888\r\n    \r\n    print(f\"Connecting to server at {server_host}:{server_port}\")\r\n    print(\"Sending messages automatically...\")\r\n    \r\n    try:\r\n        message_count = 0\r\n        while True:\r\n            message_count += 1\r\n            \r\n            # Create test message\r\n            message = f\"Hello, UDP! #{message_count}\"\r\n            data = message.encode('utf-8')\r\n            \r\n            # Send message\r\n            try:\r\n                bytes_sent = client.send_to(data, server_host, server_port)\r\n                print(f\"Sent: {message} ({bytes_sent} bytes)\")\r\n            except Exception as e:\r\n                print(f\"Error sending message: {e}\")\r\n            \r\n            # Wait before sending next message\r\n            time.sleep(2)\r\n    \r\n    except KeyboardInterrupt:\r\n        print(\"\\nStopping client...\")\r\n    \r\n    print(\"Client stopped.\")\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    main()\r\n```\r\n\r\nIn another terminal, run the client:\r\n\r\n```bash\r\nuv run python examples/client_example.py\r\n```\r\n\r\nThe client will automatically send messages every 2 seconds and display received responses.\r\n\r\n## Development\r\n\r\n### Project Structure\r\n\r\n```\r\npy-udp/\r\n\u251c\u2500\u2500 src/                   # Rust source code\r\n\u2502   \u2514\u2500\u2500 lib.rs            # Main Rust implementation\r\n\u251c\u2500\u2500 py_udp/               # Python package\r\n\u2502   \u251c\u2500\u2500 __init__.py       # Python API\r\n\u2502   \u2514\u2500\u2500 ...\r\n\u251c\u2500\u2500 examples/             # Usage examples\r\n\u2502   \u251c\u2500\u2500 server_example.py # Echo server example\r\n\u2502   \u2514\u2500\u2500 client_example.py # Echo client example\r\n\u251c\u2500\u2500 tests/                # Python tests\r\n\u251c\u2500\u2500 Cargo.toml           # Rust project config\r\n\u251c\u2500\u2500 pyproject.toml       # Python package config\r\n\u2514\u2500\u2500 README.md\r\n```\r\n\r\n### Working with Rust Code\r\n\r\n```bash\r\n# Build Rust extension\r\nuv run maturin develop\r\n\r\n# Run Rust tests\r\ncargo test\r\n\r\n# Run specific test suites\r\ncargo test --test test_udp        # Unit tests\r\ncargo test --test integration_udp # Integration tests\r\n\r\n# Run with debug output\r\nRUST_LOG=debug cargo test\r\n\r\n# Check code coverage\r\ncargo tarpaulin --skip-clean\r\n```\r\n\r\n### Working with Python Package\r\n\r\n```bash\r\n# Install in development mode\r\nuv run maturin develop\r\n\r\n# Run Python tests\r\nuv run pytest tests/\r\n\r\n# Run tests with coverage\r\nuv run pytest tests/ --cov=py_udp --cov-report=term-missing\r\n\r\n# Run specific test classes\r\nuv run pytest tests/ -k TestUdpServer\r\nuv run pytest tests/ -k TestUdpClient\r\n\r\n# Format code\r\nuv run black .\r\nuv run isort .\r\n```\r\n\r\n### Running Tests\r\n\r\n#### Rust Tests\r\n\r\n```bash\r\n# Run all Rust tests (unit + integration)\r\ncargo test\r\n\r\n# Run only unit tests\r\ncargo test --lib\r\n\r\n# Run only integration tests\r\ncargo test --test integration_udp\r\ncargo test --test test_udp\r\n\r\n# Run with debug output\r\nRUST_LOG=debug cargo test\r\n```\r\n\r\n**Rust Test Coverage:**\r\n- **Unit Tests**: 19 tests in `tests/test_udp.rs`\r\n- **Integration Tests**: 10 tests in `tests/integration_udp.rs`\r\n- **Coverage**: 33.08% (44/133 lines covered)\r\n\r\n#### Python Tests\r\n\r\n```bash\r\n# Run Python tests\r\nuv run pytest tests/\r\n\r\n# Run with coverage report\r\nuv run pytest tests/ --cov=py_udp --cov-report=term-missing\r\n\r\n# Run with verbose output\r\nuv run pytest tests/ -v\r\n```\r\n\r\n**Python Test Coverage:**\r\n- **Total Tests**: 26 tests\r\n- **Coverage**: 91% (83/91 lines covered)\r\n- **Missing Lines**: 15-16, 79, 109, 127-130, 188\r\n\r\n#### Test Structure\r\n\r\n**Rust Tests (`tests/` directory):**\r\n- `test_udp.rs` - Unit tests for core Rust functionality\r\n  - Server/client creation and initialization\r\n  - Binding and address validation\r\n  - Error handling and edge cases\r\n  - Basic UDP operations\r\n- `integration_udp.rs` - Integration tests for UDP communication\r\n  - Client-server echo communication\r\n  - Invalid address handling\r\n  - Multiple message sending\r\n  - Server lifecycle management\r\n\r\n**Python Tests (`tests/test_udp.py`):**\r\n- `TestMessageHandler` - Message handler base class tests\r\n- `TestUdpServer` - Server functionality tests\r\n- `TestUdpClient` - Client functionality tests\r\n- `TestConvenienceFunctions` - Utility function tests\r\n- `TestUdpCommunication` - End-to-end communication tests\r\n\r\n#### Coverage Analysis\r\n\r\n**Rust Coverage (33.08%):**\r\n- **Covered**: Basic initialization, binding, error handling\r\n- **Uncovered**: Python GIL-dependent methods, async server logic, PyO3 wrappers\r\n- **Limitations**: Python interpreter not available in Rust-only tests\r\n\r\n**Python Coverage (91%):**\r\n- **Covered**: All public API methods, error handling, communication\r\n- **Missing**: Some edge cases and error conditions\r\n- **Strength**: Full integration testing with real UDP communication\r\n\r\n#### Coverage Commands\r\n\r\n```bash\r\n# Rust coverage with cargo-tarpaulin\r\ncargo install cargo-tarpaulin\r\ncargo tarpaulin --skip-clean\r\ncargo tarpaulin --out Html --output-dir coverage\r\n\r\n# Python coverage with pytest-cov\r\nuv run pytest tests/ --cov=py_udp --cov-report=html\r\nuv run pytest tests/ --cov=py_udp --cov-report=term-missing\r\n```\r\n\r\n## API Reference\r\n\r\n### UdpServer\r\n\r\n#### Constructor\r\n```python\r\nUdpServer(host: str = \"0.0.0.0\", port: int = 0)\r\n```\r\n\r\n#### Methods\r\n- `bind(host: Optional[str] = None, port: Optional[int] = None) -> None`\r\n  - Bind the server to a specific address and port\r\n- `set_message_handler(handler: Union[MessageHandler, Callable]) -> None`\r\n  - Set the message handler for processing incoming messages\r\n- `start() -> None`\r\n  - Start the server and begin listening for messages\r\n- `stop() -> None`\r\n  - Stop the server and clean up resources\r\n- `is_running() -> bool`\r\n  - Check if the server is currently running\r\n- `send_to(data: bytes, address: str) -> int`\r\n  - Send data to a specific address (host:port format)\r\n\r\n#### Properties\r\n- `address: Tuple[str, int]` - Server address\r\n\r\n### UdpClient\r\n\r\n#### Constructor\r\n```python\r\nUdpClient(host: str = \"0.0.0.0\", port: int = 0)\r\n```\r\n\r\n#### Methods\r\n- `bind(host: Optional[str] = None, port: Optional[int] = None) -> None`\r\n  - Bind the client to a specific address and port\r\n- `send_to(data: bytes, host: str, port: int) -> int`\r\n  - Send data to a specific host and port\r\n- `recv_from() -> Tuple[bytes, str]`\r\n  - Receive data from any address\r\n\r\n#### Properties\r\n- `address: Tuple[str, int]` - Client address\r\n\r\n### MessageHandler\r\n\r\nBase class for handling incoming UDP messages:\r\n\r\n```python\r\nclass MyHandler(MessageHandler):\r\n    def __call__(self, data: bytes, source_address: str) -> None:\r\n        # Handle the message\r\n        # data: received data as bytes\r\n        # source_address: source address as string (host:port)\r\n        pass\r\n```\r\n\r\n## Performance\r\n\r\nThe Rust backend provides significant performance improvements over pure Python implementations:\r\n\r\n- **Lower Latency**: Direct system calls without Python GIL overhead\r\n- **Higher Throughput**: Efficient async I/O with Tokio\r\n- **Memory Efficiency**: Zero-copy operations where possible\r\n- **Concurrent Processing**: True parallelism for multiple connections\r\n- **Channel-based Communication**: Non-blocking message passing between Rust and Python\r\n\r\n## Troubleshooting\r\n\r\n### Common Issues\r\n\r\n1. **Import Error**: Make sure the Rust extension is built with `uv run maturin develop`\r\n2. **Permission Denied**: Check if the port is already in use or requires elevated privileges\r\n3. **Build Errors**: Ensure you have the latest Rust toolchain installed\r\n4. **Runtime Errors**: Make sure the server is started before calling `send_to()`\r\n\r\n### Debug Mode\r\n\r\nEnable debug logging for Rust:\r\n\r\n```bash\r\nexport RUST_LOG=debug\r\ncargo test\r\n```\r\n\r\n### Testing the Installation\r\n\r\nRun a simple test to verify everything works:\r\n\r\n```bash\r\nuv run python -c \"from py_udp import UdpServer, UdpClient; print('\u2705 Installation successful!')\"\r\n```\r\n\r\n## License\r\n\r\nMIT License - see LICENSE file for details.\r\n\r\n## Contributing\r\n\r\n1. Fork the repository\r\n2. Create a feature branch\r\n3. Make your changes\r\n4. Add tests for both Rust and Python\r\n5. Run tests and linting\r\n6. Submit a pull request\r\n\r\n### Development Workflow\r\n\r\n1. **Rust Changes**: Work in `src/` directory\r\n   - Add unit tests in `tests/test_udp.rs`\r\n   - Add integration tests in `tests/integration_udp.rs`\r\n   - Run `cargo test` to verify changes\r\n   - Check coverage with `cargo tarpaulin`\r\n\r\n2. **Python Changes**: Work in `py_udp/` directory\r\n   - Add tests in `tests/test_udp.py`\r\n   - Run `uv run pytest tests/` to verify changes\r\n   - Check coverage with `uv run pytest tests/ --cov=py_udp`\r\n\r\n3. **Integration**: Test both components work together\r\n   - Run both Rust and Python test suites\r\n   - Test examples in `examples/` directory\r\n   - Verify end-to-end functionality\r\n\r\n4. **Documentation**: Update README and docstrings\r\n5. **Examples**: Update examples in `examples/` directory\r\n\r\n### Code Style\r\n\r\n- **Rust**: Follow Rust formatting guidelines with `cargo fmt`\r\n- **Python**: Use Black for formatting and isort for imports\r\n- **Documentation**: Keep docstrings up to date\r\n- **Tests**: Maintain good test coverage for both Rust and Python \n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "High-performance UDP networking library for Python with Rust backend",
    "version": "0.2.0",
    "project_urls": {
        "Changelog": "https://github.com/DaymaNKinG990/py-udp/blob/main/CHANGELOG.md",
        "Documentation": "https://github.com/DaymaNKinG990/py-udp#readme",
        "Homepage": "https://github.com/DaymaNKinG990/py-udp",
        "Issues": "https://github.com/DaymaNKinG990/py-udp/issues",
        "Repository": "https://github.com/DaymaNKinG990/py-udp"
    },
    "split_keywords": [
        "udp",
        " networking",
        " rust",
        " async",
        " socket",
        " server",
        " client"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5d088cdd38b6b9e7016fc0fbf8f1ce725db4229cea2a8b5457a277a99722e73d",
                "md5": "45ea95f2267bb50d3ac50c746deaa827",
                "sha256": "d73d5a9d0002bd213e4fc0cb4e9a0c1c250afcf140def3e70eac6befb0bfe276"
            },
            "downloads": -1,
            "filename": "py_udp_rust-0.2.0-cp312-cp312-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "45ea95f2267bb50d3ac50c746deaa827",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.12",
            "size": 346495,
            "upload_time": "2025-08-04T09:41:47",
            "upload_time_iso_8601": "2025-08-04T09:41:47.344618Z",
            "url": "https://files.pythonhosted.org/packages/5d/08/8cdd38b6b9e7016fc0fbf8f1ce725db4229cea2a8b5457a277a99722e73d/py_udp_rust-0.2.0-cp312-cp312-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-04 09:41:47",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "DaymaNKinG990",
    "github_project": "py-udp",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "py-udp-rust"
}
        
Elapsed time: 2.01795s