PySIPio


NamePySIPio JSON
Version 1.8.0 PyPI version JSON
download
home_pageNone
SummaryPython SIP Library for Custom VoIP Solutions
upload_time2024-11-17 15:35:35
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords sip voip session initiation protocol voice over ip telephony communication udp async asynchronous call handling pbx ivr interactive voice response
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <p align="center">
  <img src="https://raw.githubusercontent.com/moha-abdi/pysip/main/.github/images/banner.png" alt="PySIP Logo" style="display: block; margin: 0 auto; width: 50%;">
</p>
<p align="center">
  <b>Python SIP Library for Custom VoIP Solutions</b>
</p>

**PySIP** is an asynchronous Python library designed to simplify working with the Session Initiation Protocol (SIP) for VoIP communication. Whether you're building automated call systems, interactive voice response (IVR) menus, or any SIP-based application, PySIP gives you the flexibility to create and manage SIP accounts, handle calls, and implement custom logic with ease.

## ✨ **Features**

<table style="width: 100%; border-collapse: separate; border-spacing: 0 10px;">
  <tr>
    <th style="text-align: left; padding: 10px 0;">Feature</th>
    <th style="text-align: left; padding: 10px 0;">Description</th>
  </tr>
  <tr>
    <td style="padding: 10px; font-weight: bold;">
      Complete SIP Account Management
    </td>
    <td style="padding: 10px; border-radius: 0 6px 6px 0;">
      Easily create, register, and manage SIP accounts.
    </td>
  </tr>
  <tr>
    <td style="padding: 10px; font-weight: bold;">
      Custom Call Flows
    </td>
    <td style="padding: 10px; border-radius: 0 6px 6px 0;">
      Write scripts to automate call flows with your own business logic.
    </td>
  </tr> 
  <tr>
    <td style="padding: 10px; font-weight: bold;">
      UDP Transport Layer
    </td>
    <td style="padding: 10px; border-radius: 0 6px 6px 0;">
      Asynchronous, efficient UDP transport for sending and receiving SIP messages.
    </td>
  </tr>
  <tr>
    <td style="padding: 10px; font-weight: bold;">
      Flexible Call Handling
    </td>
    <td style="padding: 10px; border-radius: 0 6px 6px 0;">
      Handle incoming and outgoing SIP calls, play messages, and gather user input.
    </td>
  </tr>
  <tr>
    <td style="padding: 10px; font-weight: bold;">
      Fully Extensible
    </td>
    <td style="padding: 10px; border-radius: 0 6px 6px 0;">
      Includes an example bot for appointment booking, but you can easily write any SIP-based automation you need.
    </td>
  </tr>
</table>

## 📚 **Table of Contents**

1. [Installation](#-installation)
2. [Project Structure](#-project-structure)
3. [Getting Started](#-getting-started)
4. [Detailed Usage](#-detailed-usage)
   - [SIP Account](#sip-account)
   - [Call Handling](#call-handling)
   - [UDP Transport](#udp-transport)
5. [Example Script](#-example-script)
6. [Creating Your Custom SIP Scripts](#-creating-your-custom-sip-scripts)
7. [Contributing](#-contributing)

---

## 🚀 **Installation**

### Option 1: Install from PyPI

You can install PySIP directly from PyPI using pip:

```bash
pip install PySIPio
```

> [!CAUTION]
> Note that the package name on PyPI is `PySIPio` and not `PySIP`

### Option 2: Install from source

#### Step 1: Clone the repository

```bash
git clone https://github.com/moha-abdi/PySIP.git
cd PySIP
```

#### Step 2: Install dependencies

Ensure you have Python 3.8+ installed. Install the required dependencies using:

```bash
pip install -r requirements.txt
```

---

## 📁 **Project Structure**

The project is structured to provide a clean separation between the core SIP library and any custom scripts you want to write. Here's an overview of the project layout:


```
PySIP/
│
├── PySIP/                     # Core library files
│   ├── sip_account.py          # SIP account management
│   ├── sip_core.py             # SIP message parsing and handling
│   ├── udp_handler.py          # Asynchronous UDP transport for SIP
│
├── scripts/                    # Example custom scripts
│   └── appointment_booking_bot.py  # Example bot for appointment booking
│
├── test.py                     # Example usage of PySIP for testing
├── requirements.txt            # Project dependencies
├── .env.example                # Example environment configuration
└── README.md                   # Project documentation
```

---

## 🏁 **Getting Started**

### Step 1: Environment Setup

Create a `.env` file in your working directory to store your SIP account credentials and server details:

```bash
SIP_USERNAME=your_sip_username
SIP_PASSWORD=your_sip_password
SIP_SERVER=your_sip_server
```

### Step 2: Setting Up a SIP Account

A SIP account is essential for handling calls. To start, you need to create an instance of the `SipAccount` class, which requires your SIP credentials (username, password, and server). Here's how to do it:

```python
from PySIP.sip_account import SipAccount
import os
from dotenv import load_dotenv

# Load SIP credentials from .env file
load_dotenv()

account = SipAccount(
    os.environ["SIP_USERNAME"],
    os.environ["SIP_PASSWORD"],
    os.environ["SIP_SERVER"],
)
```

### Step 3: Registering the Account

Once the `SipAccount` is created, the next step is to register it with the SIP server:

```python
await account.register()
```

This sends a SIP `REGISTER` request to the server to activate the account. Once registered, you can make calls or listen for incoming calls.

---

## 📘 **Detailed Usage**

### SIP Account

The `SipAccount` class is at the core of PySIP. It handles all account-related tasks such as registration, making calls, and unregistering from the SIP server.

#### **Instantiating a SIP Account**:

```python
account = SipAccount(username, password, server)
```

#### **Registering**:

Call the `register()` method to register the SIP account with the server:

```python
await account.register()
```

#### **Making Calls**:

The `make_call(destination)` method initiates a call to the destination number:

```python
call = account.make_call("destination_number")
```

#### **Handling Incoming Calls**:

Use the `on_incoming_call` decorator to define a function that will handle incoming calls:

```python
@account.on_incoming_call
async def handle_incoming_call(call: SipCall):
    await call.accept()  # or call.reject() or call.busy()
    await call.call_handler.say("Thank you for calling us!")
    await call.call_handler.hangup()
```

#### **Unregistering**:

When you're done, unregister the account to gracefully close the session:

```python
await account.unregister()
```

### Call Handling

The `CallHandler` is responsible for handling the call flow. It allows you to say messages, gather input from the caller, or transfer the call.

#### **Playing a message to the caller**:

```python
await call_handler.say("Welcome to our service.")
```

#### **Gathering user input**:

Use `gather()` to gather input from the user, such as pressing a digit:

```python
dtmf_key = await call_handler.gather(length=1, timeout=5)
```

#### **Transferring the call**:

You can forward the call to another number:

```python
await call_handler.transfer_to("1234567890")
```

#### **Accepting, Rejecting, or Setting Busy for Incoming Calls**:

For incoming calls, you can use the following methods:

```python
await call.accept()  # Accept the incoming call
await call.reject()  # Reject the incoming call
await call.busy()    # Mark the line as busy for the incoming call
```

### UDP Transport


The `UdpHandler` is an internal module that manages the asynchronous sending and receiving of SIP messages over the network.

#### **Sending a message**:

The `send_message()` method sends a UDP message to the SIP server or peer:

```python
self.transport.sendto(message)
```

#### **Receiving a datagram**:

The `datagram_received()` method handles incoming messages, placing them in a queue for processing:

```python
self.data_q.put_nowait(data)
```


---

## 🔍 **Example Script**

To demonstrate PySIP in action, we've provided a basic example of an appointment booking bot. This bot allows callers to book appointments via a phone call.


```python
import asyncio
from PySIP.sip_account import SipAccount
from scripts.appointment_booking_bot import appointment_booking_bot
from dotenv import load_dotenv
import os

# Load environment variables
load_dotenv()

# Initialize SIP account with credentials from .env file
account = SipAccount(
    os.environ["SIP_USERNAME"],
    os.environ["SIP_PASSWORD"],
    os.environ["SIP_SERVER"],
)

@account.on_incoming_call
async def handle_incoming_call(call: SipCall):
    await call.accept()
    await call.call_handler.say("We have received your call successfully")

async def main():
    # Register the SIP account
    await account.register()

    # Make a call to a test number (e.g., '111')
    call = account.make_call("111")
    call_task = asyncio.create_task(call.start())

    # Run the appointment booking bot
    await appointment_booking_bot(call.call_handler, customer_name="John")

    # Wait for the call to complete, then unregister
    await call_task
    await account.unregister()

if __name__ == "__main__":
    asyncio.run(main())
```


---

## 🛠 **Creating Your Custom SIP Scripts**

While the appointment booking bot is just one example, **PySIP** is designed to let you create any SIP-based automation or custom script that fits your needs.

To create your own script:

1. **Create a Python file** in the `scripts/` directory.
2. **Write your custom call logic** using the `CallHandler` class to control the call flow.
3. **Use the `SipAccount` to register and make calls** as demonstrated in the example script.

---

## 🤝 **Contributing**

Contributions are welcome! If you would like to contribute to the development of PySIP, feel free to open issues or submit pull requests.

---

<p align="center">Made with ❤️ by Moha Abdi</p>

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "PySIPio",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "SIP, VoIP, Session Initiation Protocol, Voice over IP, telephony, communication, UDP, async, asynchronous, call handling, PBX, IVR, interactive voice response",
    "author": null,
    "author_email": "Moha Abdi <mohaa6052@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/b2/90/ec3f296ea4cd10a846a2c7576501c417c4d3ce630690d46d3d54289fb447/pysipio-1.8.0.tar.gz",
    "platform": null,
    "description": "<p align=\"center\">\r\n  <img src=\"https://raw.githubusercontent.com/moha-abdi/pysip/main/.github/images/banner.png\" alt=\"PySIP Logo\" style=\"display: block; margin: 0 auto; width: 50%;\">\r\n</p>\r\n<p align=\"center\">\r\n  <b>Python SIP Library for Custom VoIP Solutions</b>\r\n</p>\r\n\r\n**PySIP** is an asynchronous Python library designed to simplify working with the Session Initiation Protocol (SIP) for VoIP communication. Whether you're building automated call systems, interactive voice response (IVR) menus, or any SIP-based application, PySIP gives you the flexibility to create and manage SIP accounts, handle calls, and implement custom logic with ease.\r\n\r\n## \u2728 **Features**\r\n\r\n<table style=\"width: 100%; border-collapse: separate; border-spacing: 0 10px;\">\r\n  <tr>\r\n    <th style=\"text-align: left; padding: 10px 0;\">Feature</th>\r\n    <th style=\"text-align: left; padding: 10px 0;\">Description</th>\r\n  </tr>\r\n  <tr>\r\n    <td style=\"padding: 10px; font-weight: bold;\">\r\n      Complete SIP Account Management\r\n    </td>\r\n    <td style=\"padding: 10px; border-radius: 0 6px 6px 0;\">\r\n      Easily create, register, and manage SIP accounts.\r\n    </td>\r\n  </tr>\r\n  <tr>\r\n    <td style=\"padding: 10px; font-weight: bold;\">\r\n      Custom Call Flows\r\n    </td>\r\n    <td style=\"padding: 10px; border-radius: 0 6px 6px 0;\">\r\n      Write scripts to automate call flows with your own business logic.\r\n    </td>\r\n  </tr> \r\n  <tr>\r\n    <td style=\"padding: 10px; font-weight: bold;\">\r\n      UDP Transport Layer\r\n    </td>\r\n    <td style=\"padding: 10px; border-radius: 0 6px 6px 0;\">\r\n      Asynchronous, efficient UDP transport for sending and receiving SIP messages.\r\n    </td>\r\n  </tr>\r\n  <tr>\r\n    <td style=\"padding: 10px; font-weight: bold;\">\r\n      Flexible Call Handling\r\n    </td>\r\n    <td style=\"padding: 10px; border-radius: 0 6px 6px 0;\">\r\n      Handle incoming and outgoing SIP calls, play messages, and gather user input.\r\n    </td>\r\n  </tr>\r\n  <tr>\r\n    <td style=\"padding: 10px; font-weight: bold;\">\r\n      Fully Extensible\r\n    </td>\r\n    <td style=\"padding: 10px; border-radius: 0 6px 6px 0;\">\r\n      Includes an example bot for appointment booking, but you can easily write any SIP-based automation you need.\r\n    </td>\r\n  </tr>\r\n</table>\r\n\r\n## \ud83d\udcda **Table of Contents**\r\n\r\n1. [Installation](#-installation)\r\n2. [Project Structure](#-project-structure)\r\n3. [Getting Started](#-getting-started)\r\n4. [Detailed Usage](#-detailed-usage)\r\n   - [SIP Account](#sip-account)\r\n   - [Call Handling](#call-handling)\r\n   - [UDP Transport](#udp-transport)\r\n5. [Example Script](#-example-script)\r\n6. [Creating Your Custom SIP Scripts](#-creating-your-custom-sip-scripts)\r\n7. [Contributing](#-contributing)\r\n\r\n---\r\n\r\n## \ud83d\ude80 **Installation**\r\n\r\n### Option 1: Install from PyPI\r\n\r\nYou can install PySIP directly from PyPI using pip:\r\n\r\n```bash\r\npip install PySIPio\r\n```\r\n\r\n> [!CAUTION]\r\n> Note that the package name on PyPI is `PySIPio` and not `PySIP`\r\n\r\n### Option 2: Install from source\r\n\r\n#### Step 1: Clone the repository\r\n\r\n```bash\r\ngit clone https://github.com/moha-abdi/PySIP.git\r\ncd PySIP\r\n```\r\n\r\n#### Step 2: Install dependencies\r\n\r\nEnsure you have Python 3.8+ installed. Install the required dependencies using:\r\n\r\n```bash\r\npip install -r requirements.txt\r\n```\r\n\r\n---\r\n\r\n## \ud83d\udcc1 **Project Structure**\r\n\r\nThe project is structured to provide a clean separation between the core SIP library and any custom scripts you want to write. Here's an overview of the project layout:\r\n\r\n\r\n```\r\nPySIP/\r\n\u2502\r\n\u251c\u2500\u2500 PySIP/                     # Core library files\r\n\u2502   \u251c\u2500\u2500 sip_account.py          # SIP account management\r\n\u2502   \u251c\u2500\u2500 sip_core.py             # SIP message parsing and handling\r\n\u2502   \u251c\u2500\u2500 udp_handler.py          # Asynchronous UDP transport for SIP\r\n\u2502\r\n\u251c\u2500\u2500 scripts/                    # Example custom scripts\r\n\u2502   \u2514\u2500\u2500 appointment_booking_bot.py  # Example bot for appointment booking\r\n\u2502\r\n\u251c\u2500\u2500 test.py                     # Example usage of PySIP for testing\r\n\u251c\u2500\u2500 requirements.txt            # Project dependencies\r\n\u251c\u2500\u2500 .env.example                # Example environment configuration\r\n\u2514\u2500\u2500 README.md                   # Project documentation\r\n```\r\n\r\n---\r\n\r\n## \ud83c\udfc1 **Getting Started**\r\n\r\n### Step 1: Environment Setup\r\n\r\nCreate a `.env` file in your working directory to store your SIP account credentials and server details:\r\n\r\n```bash\r\nSIP_USERNAME=your_sip_username\r\nSIP_PASSWORD=your_sip_password\r\nSIP_SERVER=your_sip_server\r\n```\r\n\r\n### Step 2: Setting Up a SIP Account\r\n\r\nA SIP account is essential for handling calls. To start, you need to create an instance of the `SipAccount` class, which requires your SIP credentials (username, password, and server). Here's how to do it:\r\n\r\n```python\r\nfrom PySIP.sip_account import SipAccount\r\nimport os\r\nfrom dotenv import load_dotenv\r\n\r\n# Load SIP credentials from .env file\r\nload_dotenv()\r\n\r\naccount = SipAccount(\r\n    os.environ[\"SIP_USERNAME\"],\r\n    os.environ[\"SIP_PASSWORD\"],\r\n    os.environ[\"SIP_SERVER\"],\r\n)\r\n```\r\n\r\n### Step 3: Registering the Account\r\n\r\nOnce the `SipAccount` is created, the next step is to register it with the SIP server:\r\n\r\n```python\r\nawait account.register()\r\n```\r\n\r\nThis sends a SIP `REGISTER` request to the server to activate the account. Once registered, you can make calls or listen for incoming calls.\r\n\r\n---\r\n\r\n## \ud83d\udcd8 **Detailed Usage**\r\n\r\n### SIP Account\r\n\r\nThe `SipAccount` class is at the core of PySIP. It handles all account-related tasks such as registration, making calls, and unregistering from the SIP server.\r\n\r\n#### **Instantiating a SIP Account**:\r\n\r\n```python\r\naccount = SipAccount(username, password, server)\r\n```\r\n\r\n#### **Registering**:\r\n\r\nCall the `register()` method to register the SIP account with the server:\r\n\r\n```python\r\nawait account.register()\r\n```\r\n\r\n#### **Making Calls**:\r\n\r\nThe `make_call(destination)` method initiates a call to the destination number:\r\n\r\n```python\r\ncall = account.make_call(\"destination_number\")\r\n```\r\n\r\n#### **Handling Incoming Calls**:\r\n\r\nUse the `on_incoming_call` decorator to define a function that will handle incoming calls:\r\n\r\n```python\r\n@account.on_incoming_call\r\nasync def handle_incoming_call(call: SipCall):\r\n    await call.accept()  # or call.reject() or call.busy()\r\n    await call.call_handler.say(\"Thank you for calling us!\")\r\n    await call.call_handler.hangup()\r\n```\r\n\r\n#### **Unregistering**:\r\n\r\nWhen you're done, unregister the account to gracefully close the session:\r\n\r\n```python\r\nawait account.unregister()\r\n```\r\n\r\n### Call Handling\r\n\r\nThe `CallHandler` is responsible for handling the call flow. It allows you to say messages, gather input from the caller, or transfer the call.\r\n\r\n#### **Playing a message to the caller**:\r\n\r\n```python\r\nawait call_handler.say(\"Welcome to our service.\")\r\n```\r\n\r\n#### **Gathering user input**:\r\n\r\nUse `gather()` to gather input from the user, such as pressing a digit:\r\n\r\n```python\r\ndtmf_key = await call_handler.gather(length=1, timeout=5)\r\n```\r\n\r\n#### **Transferring the call**:\r\n\r\nYou can forward the call to another number:\r\n\r\n```python\r\nawait call_handler.transfer_to(\"1234567890\")\r\n```\r\n\r\n#### **Accepting, Rejecting, or Setting Busy for Incoming Calls**:\r\n\r\nFor incoming calls, you can use the following methods:\r\n\r\n```python\r\nawait call.accept()  # Accept the incoming call\r\nawait call.reject()  # Reject the incoming call\r\nawait call.busy()    # Mark the line as busy for the incoming call\r\n```\r\n\r\n### UDP Transport\r\n\r\n\r\nThe `UdpHandler` is an internal module that manages the asynchronous sending and receiving of SIP messages over the network.\r\n\r\n#### **Sending a message**:\r\n\r\nThe `send_message()` method sends a UDP message to the SIP server or peer:\r\n\r\n```python\r\nself.transport.sendto(message)\r\n```\r\n\r\n#### **Receiving a datagram**:\r\n\r\nThe `datagram_received()` method handles incoming messages, placing them in a queue for processing:\r\n\r\n```python\r\nself.data_q.put_nowait(data)\r\n```\r\n\r\n\r\n---\r\n\r\n## \ud83d\udd0d **Example Script**\r\n\r\nTo demonstrate PySIP in action, we've provided a basic example of an appointment booking bot. This bot allows callers to book appointments via a phone call.\r\n\r\n\r\n```python\r\nimport asyncio\r\nfrom PySIP.sip_account import SipAccount\r\nfrom scripts.appointment_booking_bot import appointment_booking_bot\r\nfrom dotenv import load_dotenv\r\nimport os\r\n\r\n# Load environment variables\r\nload_dotenv()\r\n\r\n# Initialize SIP account with credentials from .env file\r\naccount = SipAccount(\r\n    os.environ[\"SIP_USERNAME\"],\r\n    os.environ[\"SIP_PASSWORD\"],\r\n    os.environ[\"SIP_SERVER\"],\r\n)\r\n\r\n@account.on_incoming_call\r\nasync def handle_incoming_call(call: SipCall):\r\n    await call.accept()\r\n    await call.call_handler.say(\"We have received your call successfully\")\r\n\r\nasync def main():\r\n    # Register the SIP account\r\n    await account.register()\r\n\r\n    # Make a call to a test number (e.g., '111')\r\n    call = account.make_call(\"111\")\r\n    call_task = asyncio.create_task(call.start())\r\n\r\n    # Run the appointment booking bot\r\n    await appointment_booking_bot(call.call_handler, customer_name=\"John\")\r\n\r\n    # Wait for the call to complete, then unregister\r\n    await call_task\r\n    await account.unregister()\r\n\r\nif __name__ == \"__main__\":\r\n    asyncio.run(main())\r\n```\r\n\r\n\r\n---\r\n\r\n## \ud83d\udee0 **Creating Your Custom SIP Scripts**\r\n\r\nWhile the appointment booking bot is just one example, **PySIP** is designed to let you create any SIP-based automation or custom script that fits your needs.\r\n\r\nTo create your own script:\r\n\r\n1. **Create a Python file** in the `scripts/` directory.\r\n2. **Write your custom call logic** using the `CallHandler` class to control the call flow.\r\n3. **Use the `SipAccount` to register and make calls** as demonstrated in the example script.\r\n\r\n---\r\n\r\n## \ud83e\udd1d **Contributing**\r\n\r\nContributions are welcome! If you would like to contribute to the development of PySIP, feel free to open issues or submit pull requests.\r\n\r\n---\r\n\r\n<p align=\"center\">Made with \u2764\ufe0f by Moha Abdi</p>\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python SIP Library for Custom VoIP Solutions",
    "version": "1.8.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/moha-abdi/PySIP/issues",
        "Homepage": "https://github.com/moha-abdi/PySIP"
    },
    "split_keywords": [
        "sip",
        " voip",
        " session initiation protocol",
        " voice over ip",
        " telephony",
        " communication",
        " udp",
        " async",
        " asynchronous",
        " call handling",
        " pbx",
        " ivr",
        " interactive voice response"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0392284a98e0d15e495dbe8e3bd8c667ead1dfd6e4d4539d0e1ce8d3ce7e6d76",
                "md5": "ea240057ebbdb1429fba64de8e902a47",
                "sha256": "73afc04e1cea58d8da5032012da611f724fb0cfdbdaa6d3892386de2574d48df"
            },
            "downloads": -1,
            "filename": "PySIPio-1.8.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ea240057ebbdb1429fba64de8e902a47",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 50987,
            "upload_time": "2024-11-17T15:35:33",
            "upload_time_iso_8601": "2024-11-17T15:35:33.131173Z",
            "url": "https://files.pythonhosted.org/packages/03/92/284a98e0d15e495dbe8e3bd8c667ead1dfd6e4d4539d0e1ce8d3ce7e6d76/PySIPio-1.8.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b290ec3f296ea4cd10a846a2c7576501c417c4d3ce630690d46d3d54289fb447",
                "md5": "9a16f4d834a402be34da8bfdfc51d2d7",
                "sha256": "777d62346eb03bc2c36dfbf34a385b99fe732f740ca3337b9496fc0ed64945e8"
            },
            "downloads": -1,
            "filename": "pysipio-1.8.0.tar.gz",
            "has_sig": false,
            "md5_digest": "9a16f4d834a402be34da8bfdfc51d2d7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 48066,
            "upload_time": "2024-11-17T15:35:35",
            "upload_time_iso_8601": "2024-11-17T15:35:35.243142Z",
            "url": "https://files.pythonhosted.org/packages/b2/90/ec3f296ea4cd10a846a2c7576501c417c4d3ce630690d46d3d54289fb447/pysipio-1.8.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-17 15:35:35",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "moha-abdi",
    "github_project": "PySIP",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "pysipio"
}
        
Elapsed time: 0.37516s