udsonip


Nameudsonip JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummaryEnhanced UDS-on-IP integration library providing seamless multi-ECU support
upload_time2025-10-25 08:18:49
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseMIT
keywords doip uds automotive diagnostics iso13400 iso14229
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # python-udsonip

**Enhanced UDS-on-IP Integration Library**

> **Note:** Install via `pip install udsonip` (package name without the `python-` prefix)

`udsonip` is a high-level Python library that seamlessly integrates [python-doipclient](https://github.com/jacobschaer/python-doipclient) and [python-udsoncan](https://github.com/pylessard/python-udsoncan) to provide enhanced multi-ECU support, improved ergonomics, and advanced features for automotive diagnostics over DoIP (Diagnostics over Internet Protocol).

---

**πŸ“– Documentation:**
- **For Users:** This README (installation, usage, examples)
- **For Contributors:** See [CONTRIBUTING.md](CONTRIBUTING.md) (setup, testing, contribution guidelines)
- **Project Status:** See [DEVELOPMENT.md](DEVELOPMENT.md) (features, roadmap, architecture)

## Features

- 🎯 **Dynamic Target Address Support** - Runtime switching between ECU addresses
- πŸ”„ **Multi-ECU Management** - Single connection managing multiple ECUs with context managers
- πŸ” **Auto-Discovery** - Automatic ECU enumeration and discovery
- πŸ“‘ **Enhanced Session Management** - Per-ECU session tracking and persistence
- πŸ› οΈ **Simplified API** - Less boilerplate, sensible defaults

## Installation

```bash
pip install udsonip
```

## Quick Start

### Single ECU Communication

```python
from udsonip import UdsOnIpClient

# Simple single-ECU client
client = UdsOnIpClient('192.168.1.10', 0x00E0)
response = client.read_data_by_identifier(0xF190)  # Read VIN
print(f"VIN: {response.data.decode()}")
client.close()
```

### Multi-ECU Communication

```python
from udsonip import DoIPMultiECUClient

# Multi-ECU manager
manager = DoIPMultiECUClient('192.168.1.10')
manager.add_ecu('engine', 0x00E0)
manager.add_ecu('transmission', 0x00E1)

# Switch between ECUs seamlessly
with manager.ecu('engine') as ecu:
    vin = ecu.read_data_by_identifier(0xF190)

with manager.ecu('transmission') as ecu:
    status = ecu.read_data_by_identifier(0x1234)
```

### Auto-Discovery

```python
from udsonip import discover_ecus

# Discover all ECUs on the network
ecus = discover_ecus(timeout=5.0)
for ecu in ecus:
    print(f"Found ECU: {ecu.ip} @ {ecu.logical_address:#x}")
    
# Connect to discovered ECU
client = ecus[0].connect()
```

### Advanced Usage - Dynamic Target Switching

```python
from udsonip import UdsOnIpClient

client = UdsOnIpClient(
    ecu_ip='192.168.1.10',
    ecu_address=0x00E0,
    auto_reconnect=True,
    keep_alive=True,
)

# Dynamic target address switching
client.target_address = 0x00E1
response = client.tester_present()

client.target_address = 0x00E2
response = client.read_data_by_identifier(0xF190)
```

## Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Your Application            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         udsonip Layer               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚ UdsOnIpClientβ”‚  β”‚ MultiECU Mgr β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚         β”‚                  β”‚        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚    UdsOnIpConnection          β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  python-udsoncan   β”‚  β”‚doipclient   β”‚
β”‚  (UDS Protocol)    β”‚  β”‚(DoIP Trans) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

## Key Components

- **UdsOnIpConnection** - Enhanced connector with dynamic address support
- **UdsOnIpClient** - Unified client wrapping both libraries
- **DoIPMultiECUClient** - Multi-ECU manager with context switching
- **discover_ecus()** - ECU discovery utilities

## Why udsonip?

### Before (using libraries separately):

```python
from doipclient import DoIPClient
from udsoncan.client import Client
from udsoncan.connections import BaseConnection

# Manual setup required - 20+ lines of boilerplate
doip_client = DoIPClient('192.168.1.10', 0x00E0)
doip_client.connect()

class DoIPConnection(BaseConnection):
    def __init__(self, doip_client):
        self._doip = doip_client
    
    def send(self, data):
        self._doip.send_diagnostic(data)
    
    def wait_frame(self, timeout=None):
        return self._doip.receive_diagnostic(timeout)

connection = DoIPConnection(doip_client)
uds_client = Client(connection)

# Finally use UDS client
response = uds_client.read_data_by_identifier(0xF190)
```

### After (using udsonip):

```python
from udsonip import UdsOnIpClient

# Just 2 lines!
client = UdsOnIpClient('192.168.1.10', 0x00E0)
response = client.read_data_by_identifier(0xF190)
```

**Result: 90% less code, 100% more readable!** πŸŽ‰

## Requirements

- Python >= 3.7
- python-doipclient >= 1.1.7
- python-udsoncan >= 1.21

## API Reference

### UdsOnIpClient

Main client for single ECU communication.

```python
client = UdsOnIpClient(
    ecu_ip='192.168.1.10',
    ecu_address=0x00E0,
    client_ip=None,           # Auto-detect
    auto_reconnect=False,
    keep_alive=False,
)
```

**Key Methods:**
- `read_data_by_identifier(did)` - Read data by identifier
- `write_data_by_identifier(did, data)` - Write data
- `tester_present()` - Send tester present
- `diagnostic_session_control(session)` - Change diagnostic session
- `ecu_reset(reset_type)` - Reset ECU
- `close()` - Close connection

### DoIPMultiECUClient

Manager for multiple ECUs on the same gateway.

```python
manager = DoIPMultiECUClient('192.168.1.10')
manager.add_ecu('engine', 0x00E0)
manager.add_ecu('transmission', 0x00E1)

with manager.ecu('engine') as ecu:
    # Use ecu like UdsOnIpClient
    vin = ecu.read_data_by_identifier(0xF190)
```

### Discovery Functions

```python
from udsonip import discover_ecus, ECUInfo

# Discover all ECUs
ecus = discover_ecus(interface=None, timeout=5.0)

# Connect to discovered ECU
client = ecus[0].connect()
```

## Learning Resources

- **DoIP Standard:** ISO 13400 (Diagnostics over Internet Protocol)
- **UDS Standard:** ISO 14229 (Unified Diagnostic Services)
- **python-doipclient:** https://github.com/jacobschaer/python-doipclient
- **python-udsoncan:** https://github.com/pylessard/python-udsoncan

## Contributing

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:
- Development environment setup
- Running tests
- Code style guidelines
- Contribution workflow

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Support & Community

- **Issues:** https://github.com/sirius-cc-wu/python-udsonip/issues
- **Documentation:** https://udsonip.readthedocs.io
- **Examples:** See `examples/` directory in the repository

## Acknowledgments

Built on top of:
- [python-doipclient](https://github.com/jacobschaer/python-doipclient) by Jacob Schaer
- [python-udsoncan](https://github.com/pylessard/python-udsoncan) by Pier-Yves Lessard

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "udsonip",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "doip, uds, automotive, diagnostics, iso13400, iso14229",
    "author": null,
    "author_email": "Sirius Wu <ccwu660601@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/4e/d6/2936b92208b7d38ef67bd980b13d7f24cccbc5888ff223d0c1c3d83dab85/udsonip-0.2.0.tar.gz",
    "platform": null,
    "description": "# python-udsonip\n\n**Enhanced UDS-on-IP Integration Library**\n\n> **Note:** Install via `pip install udsonip` (package name without the `python-` prefix)\n\n`udsonip` is a high-level Python library that seamlessly integrates [python-doipclient](https://github.com/jacobschaer/python-doipclient) and [python-udsoncan](https://github.com/pylessard/python-udsoncan) to provide enhanced multi-ECU support, improved ergonomics, and advanced features for automotive diagnostics over DoIP (Diagnostics over Internet Protocol).\n\n---\n\n**\ud83d\udcd6 Documentation:**\n- **For Users:** This README (installation, usage, examples)\n- **For Contributors:** See [CONTRIBUTING.md](CONTRIBUTING.md) (setup, testing, contribution guidelines)\n- **Project Status:** See [DEVELOPMENT.md](DEVELOPMENT.md) (features, roadmap, architecture)\n\n## Features\n\n- \ud83c\udfaf **Dynamic Target Address Support** - Runtime switching between ECU addresses\n- \ud83d\udd04 **Multi-ECU Management** - Single connection managing multiple ECUs with context managers\n- \ud83d\udd0d **Auto-Discovery** - Automatic ECU enumeration and discovery\n- \ud83d\udce1 **Enhanced Session Management** - Per-ECU session tracking and persistence\n- \ud83d\udee0\ufe0f **Simplified API** - Less boilerplate, sensible defaults\n\n## Installation\n\n```bash\npip install udsonip\n```\n\n## Quick Start\n\n### Single ECU Communication\n\n```python\nfrom udsonip import UdsOnIpClient\n\n# Simple single-ECU client\nclient = UdsOnIpClient('192.168.1.10', 0x00E0)\nresponse = client.read_data_by_identifier(0xF190)  # Read VIN\nprint(f\"VIN: {response.data.decode()}\")\nclient.close()\n```\n\n### Multi-ECU Communication\n\n```python\nfrom udsonip import DoIPMultiECUClient\n\n# Multi-ECU manager\nmanager = DoIPMultiECUClient('192.168.1.10')\nmanager.add_ecu('engine', 0x00E0)\nmanager.add_ecu('transmission', 0x00E1)\n\n# Switch between ECUs seamlessly\nwith manager.ecu('engine') as ecu:\n    vin = ecu.read_data_by_identifier(0xF190)\n\nwith manager.ecu('transmission') as ecu:\n    status = ecu.read_data_by_identifier(0x1234)\n```\n\n### Auto-Discovery\n\n```python\nfrom udsonip import discover_ecus\n\n# Discover all ECUs on the network\necus = discover_ecus(timeout=5.0)\nfor ecu in ecus:\n    print(f\"Found ECU: {ecu.ip} @ {ecu.logical_address:#x}\")\n    \n# Connect to discovered ECU\nclient = ecus[0].connect()\n```\n\n### Advanced Usage - Dynamic Target Switching\n\n```python\nfrom udsonip import UdsOnIpClient\n\nclient = UdsOnIpClient(\n    ecu_ip='192.168.1.10',\n    ecu_address=0x00E0,\n    auto_reconnect=True,\n    keep_alive=True,\n)\n\n# Dynamic target address switching\nclient.target_address = 0x00E1\nresponse = client.tester_present()\n\nclient.target_address = 0x00E2\nresponse = client.read_data_by_identifier(0xF190)\n```\n\n## Architecture\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\u2510\n\u2502         Your Application            \u2502\n\u2514\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n             \u2502\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\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         udsonip Layer               \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2502\n\u2502  \u2502 UdsOnIpClient\u2502  \u2502 MultiECU Mgr \u2502\u2502\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\u2502\n\u2502         \u2502                  \u2502        \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2502\n\u2502  \u2502    UdsOnIpConnection          \u2502\u2502\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\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\u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\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          \u2502\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  python-udsoncan   \u2502  \u2502doipclient   \u2502\n\u2502  (UDS Protocol)    \u2502  \u2502(DoIP Trans) \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n## Key Components\n\n- **UdsOnIpConnection** - Enhanced connector with dynamic address support\n- **UdsOnIpClient** - Unified client wrapping both libraries\n- **DoIPMultiECUClient** - Multi-ECU manager with context switching\n- **discover_ecus()** - ECU discovery utilities\n\n## Why udsonip?\n\n### Before (using libraries separately):\n\n```python\nfrom doipclient import DoIPClient\nfrom udsoncan.client import Client\nfrom udsoncan.connections import BaseConnection\n\n# Manual setup required - 20+ lines of boilerplate\ndoip_client = DoIPClient('192.168.1.10', 0x00E0)\ndoip_client.connect()\n\nclass DoIPConnection(BaseConnection):\n    def __init__(self, doip_client):\n        self._doip = doip_client\n    \n    def send(self, data):\n        self._doip.send_diagnostic(data)\n    \n    def wait_frame(self, timeout=None):\n        return self._doip.receive_diagnostic(timeout)\n\nconnection = DoIPConnection(doip_client)\nuds_client = Client(connection)\n\n# Finally use UDS client\nresponse = uds_client.read_data_by_identifier(0xF190)\n```\n\n### After (using udsonip):\n\n```python\nfrom udsonip import UdsOnIpClient\n\n# Just 2 lines!\nclient = UdsOnIpClient('192.168.1.10', 0x00E0)\nresponse = client.read_data_by_identifier(0xF190)\n```\n\n**Result: 90% less code, 100% more readable!** \ud83c\udf89\n\n## Requirements\n\n- Python >= 3.7\n- python-doipclient >= 1.1.7\n- python-udsoncan >= 1.21\n\n## API Reference\n\n### UdsOnIpClient\n\nMain client for single ECU communication.\n\n```python\nclient = UdsOnIpClient(\n    ecu_ip='192.168.1.10',\n    ecu_address=0x00E0,\n    client_ip=None,           # Auto-detect\n    auto_reconnect=False,\n    keep_alive=False,\n)\n```\n\n**Key Methods:**\n- `read_data_by_identifier(did)` - Read data by identifier\n- `write_data_by_identifier(did, data)` - Write data\n- `tester_present()` - Send tester present\n- `diagnostic_session_control(session)` - Change diagnostic session\n- `ecu_reset(reset_type)` - Reset ECU\n- `close()` - Close connection\n\n### DoIPMultiECUClient\n\nManager for multiple ECUs on the same gateway.\n\n```python\nmanager = DoIPMultiECUClient('192.168.1.10')\nmanager.add_ecu('engine', 0x00E0)\nmanager.add_ecu('transmission', 0x00E1)\n\nwith manager.ecu('engine') as ecu:\n    # Use ecu like UdsOnIpClient\n    vin = ecu.read_data_by_identifier(0xF190)\n```\n\n### Discovery Functions\n\n```python\nfrom udsonip import discover_ecus, ECUInfo\n\n# Discover all ECUs\necus = discover_ecus(interface=None, timeout=5.0)\n\n# Connect to discovered ECU\nclient = ecus[0].connect()\n```\n\n## Learning Resources\n\n- **DoIP Standard:** ISO 13400 (Diagnostics over Internet Protocol)\n- **UDS Standard:** ISO 14229 (Unified Diagnostic Services)\n- **python-doipclient:** https://github.com/jacobschaer/python-doipclient\n- **python-udsoncan:** https://github.com/pylessard/python-udsoncan\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:\n- Development environment setup\n- Running tests\n- Code style guidelines\n- Contribution workflow\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Support & Community\n\n- **Issues:** https://github.com/sirius-cc-wu/python-udsonip/issues\n- **Documentation:** https://udsonip.readthedocs.io\n- **Examples:** See `examples/` directory in the repository\n\n## Acknowledgments\n\nBuilt on top of:\n- [python-doipclient](https://github.com/jacobschaer/python-doipclient) by Jacob Schaer\n- [python-udsoncan](https://github.com/pylessard/python-udsoncan) by Pier-Yves Lessard\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Enhanced UDS-on-IP integration library providing seamless multi-ECU support",
    "version": "0.2.0",
    "project_urls": {
        "Documentation": "https://python-udsonip.readthedocs.io",
        "Homepage": "https://github.com/sirius-cc-wu/python-udsonip",
        "Issues": "https://github.com/sirius-cc-wu/python-udsonip/issues",
        "Repository": "https://github.com/sirius-cc-wu/python-udsonip"
    },
    "split_keywords": [
        "doip",
        " uds",
        " automotive",
        " diagnostics",
        " iso13400",
        " iso14229"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "352b6630114d9be51848bfb3eba61e6fbcc49967847877d95ec69e23e3c2525d",
                "md5": "252f5e8161464315042490078f44608a",
                "sha256": "2a562f4646813be74cfabf38e70c8e5f6002ba56856e51fa01ae8a5663dc52c4"
            },
            "downloads": -1,
            "filename": "udsonip-0.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "252f5e8161464315042490078f44608a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 13456,
            "upload_time": "2025-10-25T08:18:48",
            "upload_time_iso_8601": "2025-10-25T08:18:48.654829Z",
            "url": "https://files.pythonhosted.org/packages/35/2b/6630114d9be51848bfb3eba61e6fbcc49967847877d95ec69e23e3c2525d/udsonip-0.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "4ed62936b92208b7d38ef67bd980b13d7f24cccbc5888ff223d0c1c3d83dab85",
                "md5": "7ad2da94c3dc3c65c66a508c71a7b920",
                "sha256": "ecbabac23dc5e0de7eb4ae5923a376819705fcbb9afe78521f7fe17d47719819"
            },
            "downloads": -1,
            "filename": "udsonip-0.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "7ad2da94c3dc3c65c66a508c71a7b920",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 28190,
            "upload_time": "2025-10-25T08:18:49",
            "upload_time_iso_8601": "2025-10-25T08:18:49.909091Z",
            "url": "https://files.pythonhosted.org/packages/4e/d6/2936b92208b7d38ef67bd980b13d7f24cccbc5888ff223d0c1c3d83dab85/udsonip-0.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-25 08:18:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "sirius-cc-wu",
    "github_project": "python-udsonip",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "udsonip"
}
        
Elapsed time: 0.76704s