chio


Namechio JSON
Version 1.1.20 PyPI version JSON
download
home_pageNone
SummaryA python library for serializing and deserializing bancho packets.
upload_time2025-08-08 00:46:10
maintainerNone
docs_urlNone
authorLekuru
requires_pythonNone
licenseNone
keywords osu osugame python bancho
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# Chio

![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Lekuruu/chio.py/.github%2Fworkflows%2Fbuild.yml)
![PyPI - Downloads](https://img.shields.io/pypi/dm/chio)
![GitHub License](https://img.shields.io/github/license/Lekuruu/chio.py)

**Chio (Bancho I/O)** is a python library for serializing and deserializing bancho packets, with support for all versions of osu! that use bancho (2008-2025).

It was made with the intention of documenting everything about the bancho protocol, and to provide a base for server frameworks, since the packet handling part is most often the annoying part.  
Having *any* client be able to connect to it is a very sweet addition on top, if you are interested in those as well.

**If you wish to use this library, I would appreciate some credit for my work. Thanks!**

## Usage

This library requires an installation of python **3.8** or higher.  
You can install the library with pip:

```shell
pip install chio
```

Or you can also install it from source directly, if preferred:

```shell
pip install git+https://github.com/Lekuruu/chio.py
```

Here is a very basic example of how to use this library, and how to get a client to log in:

```python
import chio

# Chio expects you to have the `chio.Stream` class
# implemented, i.e. it needs a `read()` and `write()`
# function to work properly
stream = chio.Stream()

# The client version is how chio determines what
# protocol to use. This one can be parsed through the
# initial login request, that the client makes.
client_version = 20140127

# Chio has combined the user presence, stats and status
# into one class, to support more clients. You are also
# able to provide your own player class, as long as you
# have the same fields added on to it.
info = chio.UserInfo(
    id=2,
    name="peppy",
    presence=chio.UserPresence(),
    stats=chio.UserStats(),
    status=chio.UserStatus()
)

# Select a client protocol to use for encoding/decoding
io = chio.select_client(client_version)

# Send the users information (userId, presence & stats)
io.write_packet(stream, chio.PacketType.BanchoLoginReply, info.id)
io.write_packet(stream, chio.PacketType.BanchoUserPresence, info)
io.write_packet(stream, chio.PacketType.BanchoUserStats, info)

# Force client to join #osu
io.write_packet(stream, chio.PacketType.BanchoChannelJoinSuccess, "#osu")

# Send a message in #osu from BanchoBot
io.write_packet(
    stream,
    chio.PacketType.BanchoMessage,
    chio.Message(content="Hello, World!", sender="BanchoBot", target="#osu")
)

packet, data = io.read_packet(stream)
print(f"Received packet '{packet.name}' with {data}.")
```

You can also read & write from bytes directly, for example when using HTTP clients instead of TCP clients:

```python
encoded = io.write_packet_to_bytes(chio.PacketType.BanchoLoginReply, info.id)
packet, data = io.read_packet_from_bytes(b"...")
```

If you are using **asyncio**, you may want to use the `read_packet_async` & `write_packet_async` functions respectively for asynchronous usage.
This feature is currently untested, but should work in theory. If you encounter any bugs with it, don't be afraid to report them.

```python
encoded = await io.write_packet_async(stream, chio.PacketType.BanchoLoginReply, info.id)
packet, data = await io.read_packet_async(stream)
```

### Patching

You are able to overwrite specifc packet readers/writers, with the `chio.patch` decorator.
As an example, to patch the `BanchoUserStats` packet inside of `b20120723`:

```python
@chio.patch(PacketType.BanchoUserStats, 20120723)
def write_user_stats(cls, info: UserInfo):
    stream = MemoryStream()
    write_s32(stream, info.id)
    stream.write(cls.write_status_update(info.status))
    write_u64(stream, info.stats.rscore)
    write_f32(stream, info.stats.accuracy)
    write_u32(stream, info.stats.playcount)
    write_u64(stream, info.stats.tscore)
    write_u32(stream, info.stats.rank)
    write_u16(stream, info.stats.pp)
    yield PacketType.BanchoUserStats, stream.data
```

Additionally, it's possible to set a certain slot size & protocol version for each version:

```python
# Set protocol version to 10 for b20120818
chio.set_protocol_version(10, 20120818)

# Override slot size to 32 for b20160404
chio.set_slot_size(32, 20160404)
```

### Datatypes

Depending on the packet you send or receive, you will need to account for different datatypes.  
Here is a list of them for each packet:

|             Packet             |                Type                 |
|:------------------------------:|:-----------------------------------:|
|         OsuUserStatus          |          `chio.UserStatus`          |
|           OsuMessage           |           `chio.Message`            |
|            OsuExit             |         `bool` (IsUpdating)         |
|     OsuStatusUpdateRequest     |                 N/A                 |
|            OsuPong             |                 N/A                 |
|        BanchoLoginReply        | `int` (UserId) or `chio.LoginError` |
|         BanchoMessage          |           `chio.Message`            |
|           BanchoPing           |                 N/A                 |
|    BanchoIrcChangeUsername     | `str` (old name), `str` (new name)  |
|         BanchoIrcQuit          |          `str` (Username)           |
|        BanchoUserStats         |           `chio.UserInfo`           |
|         BanchoUserQuit         |           `chio.UserQuit`           |
|     BanchoSpectatorJoined      |           `int` (UserId)            |
|      BanchoSpectatorLeft       |           `int` (UserId)            |
|      BanchoSpectateFrames      |      `chio.ReplayFrameBundle`       |
|       OsuStartSpectating       |           `int` (UserId)            |
|       OsuStopSpectating        |           `int` (UserId)            |
|       OsuSpectateFrames        |      `chio.ReplayFrameBundle`       |
|      BanchoVersionUpdate       |                 N/A                 |
|         OsuErrorReport         |          `str` (Exception)          |
|        OsuCantSpectate         |                 N/A                 |
|  BanchoSpectatorCantSpectate   |           `int` (UserId)            |
|       BanchoGetAttention       |                 N/A                 |
|         BanchoAnnounce         |           `str` (Message)           |
|       OsuPrivateMessage        |           `chio.Message`            |
|       BanchoMatchUpdate        |            `chio.Match`             |
|         BanchoMatchNew         |            `chio.Match`             |
|       BanchoMatchDisband       |           `int` (MatchId)           |
|          OsuLobbyPart          |                 N/A                 |
|          OsuLobbyJoin          |                 N/A                 |
|         OsuMatchCreate         |            `chio.Match`             |
|          OsuMatchJoin          |           `int` (MatchId)           |
|          OsuMatchPart          |                 N/A                 |
|        BanchoLobbyJoin         |           `int` (UserId)            |
|        BanchoLobbyPart         |           `int` (UserId)            |
|     BanchoMatchJoinSuccess     |            `chio.Match`             |
|      BanchoMatchJoinFail       |                 N/A                 |
|       OsuMatchChangeSlot       |           `int` (SlotId)            |
|         OsuMatchReady          |                 N/A                 |
|          OsuMatchLock          |           `int` (SlotId)            |
|     OsuMatchChangeSettings     |            `chio.Match`             |
|  BanchoFellowSpectatorJoined   |           `int` (UserId)            |
|   BanchoFellowSpectatorLeft    |           `int` (UserId)            |
|         OsuMatchStart          |                 N/A                 |
|        BanchoMatchStart        |            `chio.Match`             |
|      OsuMatchScoreUpdate       |          `chio.ScoreFrame`          |
|     BanchoMatchScoreUpdate     |          `chio.ScoreFrame`          |
|        OsuMatchComplete        |                 N/A                 |
|    BanchoMatchTransferHost     |                 N/A                 |
|       OsuMatchChangeMods       |             `chio.Mods`             |
|      OsuMatchLoadComplete      |                 N/A                 |
|  BanchoMatchAllPlayersLoaded   |                 N/A                 |
|       OsuMatchNoBeatmap        |                 N/A                 |
|        OsuMatchNotReady        |                 N/A                 |
|         OsuMatchFailed         |                 N/A                 |
|    BanchoMatchPlayerFailed     |           `int` (SlotId)            |
|      BanchoMatchComplete       |                 N/A                 |
|       OsuMatchHasBeatmap       |                 N/A                 |
|      OsuMatchSkipRequest       |                 N/A                 |
|        BanchoMatchSkip         |                 N/A                 |
|         OsuChannelJoin         |        `str` (Channel Name)         |
|    BanchoChannelJoinSuccess    |        `str` (Channel Name)         |
|     BanchoChannelAvailable     |           `chio.Channel`            |
|      BanchoChannelRevoked      |        `str` (Channel Name)         |
| BanchoChannelAvailableAutojoin |           `chio.Channel`            |
|     OsuBeatmapInfoRequest      |      `chio.BeatmapInfoRequest`      |
|     BanchoBeatmapInfoReply     |       `chio.BeatmapInfoReply`       |
|      OsuMatchTransferHost      |           `int` (SlotId)            |
|     BanchoLoginPermissions     |     `chio.Permissions` or `int`     |
|       BanchoFriendsList        |             `list[int]`             |
|         OsuFriendsAdd          |           `int` (UserId)            |
|        OsuFriendsRemove        |           `int` (UserId)            |
|   BanchoProtocolNegotiation    |            N/A or `int`             |
|       BanchoTitleUpdate        |         `chio.TitleUpdate`          |
|       OsuMatchChangeTeam       |                 N/A                 |
|        OsuChannelLeave         |        `str` (Channel Name)         |
|       OsuReceiveUpdates        |        `chio.PresenceFilter`        |
|         BanchoMonitor          |                 N/A                 |
|    BanchoMatchPlayerSkipped    |           `int` (SlotId)            |
|      OsuSetIrcAwayMessage      |           `chio.Message`            |
|       BanchoUserPresence       |           `chio.UserInfo`           |
|      OsuUserStatsRequest       |             `list[int]`             |
|         BanchoRestart          |  `int` (Retry After Milliseconds)   |
|           OsuInvite            |           `int` (UserId)            |
|          BanchoInvite          |           `chio.Message`            |
|     OsuMatchChangePassword     |            `chio.Match`             |
|   BanchoMatchChangePassword    |        `str` (New Password)         |
|       BanchoSilenceInfo        |    `int` (Locked Until Seconds)     |
|     OsuTournamentMatchInfo     |           `int` (MatchId)           |
|       BanchoUserSilenced       |           `int` (UserId)            |
|    BanchoUserPresenceSingle    |           `int` (UserId)            |
|    BanchoUserPresenceBundle    |        `list[int]` (UserIDs)        |
|       OsuPresenceRequest       |        `list[int]` (UserIDs)        |
|     OsuPresenceRequestAll      |                 N/A                 |
|     OsuChangeFriendOnlyDms     |      `bool` (Enabled/Disabled)      |
|      BanchoUserDmsBlocked      |           `chio.Message`            |
|     BanchoTargetIsSilenced     |           `chio.Message`            |
|   BanchoVersionUpdateForced    |                 N/A                 |
|       BanchoSwitchServer       |       `int` (After Idle Time)       |
|    BanchoAccountRestricted     |                 N/A                 |
|           BanchoRTX            |           `str` (Message)           |
|        BanchoMatchAbort        |                 N/A                 |
|  BanchoSwitchTournamentServer  |           `str` (Server)            |
| OsuTournamentJoinMatchChannel  |           `int` (MatchId)           |
| OsuTournamentLeaveMatchChannel |           `int` (MatchId)           |

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "chio",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "osu, osugame, python, bancho",
    "author": "Lekuru",
    "author_email": "contact@lekuru.xyz",
    "download_url": "https://files.pythonhosted.org/packages/8f/f6/32eea7aaa6fd835403235c1540ddda386662186bf015ef5d2f854f0d61c5/chio-1.1.20.tar.gz",
    "platform": null,
    "description": "\n# Chio\n\n![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Lekuruu/chio.py/.github%2Fworkflows%2Fbuild.yml)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/chio)\n![GitHub License](https://img.shields.io/github/license/Lekuruu/chio.py)\n\n**Chio (Bancho I/O)** is a python library for serializing and deserializing bancho packets, with support for all versions of osu! that use bancho (2008-2025).\n\nIt was made with the intention of documenting everything about the bancho protocol, and to provide a base for server frameworks, since the packet handling part is most often the annoying part.  \nHaving *any* client be able to connect to it is a very sweet addition on top, if you are interested in those as well.\n\n**If you wish to use this library, I would appreciate some credit for my work. Thanks!**\n\n## Usage\n\nThis library requires an installation of python **3.8** or higher.  \nYou can install the library with pip:\n\n```shell\npip install chio\n```\n\nOr you can also install it from source directly, if preferred:\n\n```shell\npip install git+https://github.com/Lekuruu/chio.py\n```\n\nHere is a very basic example of how to use this library, and how to get a client to log in:\n\n```python\nimport chio\n\n# Chio expects you to have the `chio.Stream` class\n# implemented, i.e. it needs a `read()` and `write()`\n# function to work properly\nstream = chio.Stream()\n\n# The client version is how chio determines what\n# protocol to use. This one can be parsed through the\n# initial login request, that the client makes.\nclient_version = 20140127\n\n# Chio has combined the user presence, stats and status\n# into one class, to support more clients. You are also\n# able to provide your own player class, as long as you\n# have the same fields added on to it.\ninfo = chio.UserInfo(\n    id=2,\n    name=\"peppy\",\n    presence=chio.UserPresence(),\n    stats=chio.UserStats(),\n    status=chio.UserStatus()\n)\n\n# Select a client protocol to use for encoding/decoding\nio = chio.select_client(client_version)\n\n# Send the users information (userId, presence & stats)\nio.write_packet(stream, chio.PacketType.BanchoLoginReply, info.id)\nio.write_packet(stream, chio.PacketType.BanchoUserPresence, info)\nio.write_packet(stream, chio.PacketType.BanchoUserStats, info)\n\n# Force client to join #osu\nio.write_packet(stream, chio.PacketType.BanchoChannelJoinSuccess, \"#osu\")\n\n# Send a message in #osu from BanchoBot\nio.write_packet(\n    stream,\n    chio.PacketType.BanchoMessage,\n    chio.Message(content=\"Hello, World!\", sender=\"BanchoBot\", target=\"#osu\")\n)\n\npacket, data = io.read_packet(stream)\nprint(f\"Received packet '{packet.name}' with {data}.\")\n```\n\nYou can also read & write from bytes directly, for example when using HTTP clients instead of TCP clients:\n\n```python\nencoded = io.write_packet_to_bytes(chio.PacketType.BanchoLoginReply, info.id)\npacket, data = io.read_packet_from_bytes(b\"...\")\n```\n\nIf you are using **asyncio**, you may want to use the `read_packet_async` & `write_packet_async` functions respectively for asynchronous usage.\nThis feature is currently untested, but should work in theory. If you encounter any bugs with it, don't be afraid to report them.\n\n```python\nencoded = await io.write_packet_async(stream, chio.PacketType.BanchoLoginReply, info.id)\npacket, data = await io.read_packet_async(stream)\n```\n\n### Patching\n\nYou are able to overwrite specifc packet readers/writers, with the `chio.patch` decorator.\nAs an example, to patch the `BanchoUserStats` packet inside of `b20120723`:\n\n```python\n@chio.patch(PacketType.BanchoUserStats, 20120723)\ndef write_user_stats(cls, info: UserInfo):\n    stream = MemoryStream()\n    write_s32(stream, info.id)\n    stream.write(cls.write_status_update(info.status))\n    write_u64(stream, info.stats.rscore)\n    write_f32(stream, info.stats.accuracy)\n    write_u32(stream, info.stats.playcount)\n    write_u64(stream, info.stats.tscore)\n    write_u32(stream, info.stats.rank)\n    write_u16(stream, info.stats.pp)\n    yield PacketType.BanchoUserStats, stream.data\n```\n\nAdditionally, it's possible to set a certain slot size & protocol version for each version:\n\n```python\n# Set protocol version to 10 for b20120818\nchio.set_protocol_version(10, 20120818)\n\n# Override slot size to 32 for b20160404\nchio.set_slot_size(32, 20160404)\n```\n\n### Datatypes\n\nDepending on the packet you send or receive, you will need to account for different datatypes.  \nHere is a list of them for each packet:\n\n|             Packet             |                Type                 |\n|:------------------------------:|:-----------------------------------:|\n|         OsuUserStatus          |          `chio.UserStatus`          |\n|           OsuMessage           |           `chio.Message`            |\n|            OsuExit             |         `bool` (IsUpdating)         |\n|     OsuStatusUpdateRequest     |                 N/A                 |\n|            OsuPong             |                 N/A                 |\n|        BanchoLoginReply        | `int` (UserId) or `chio.LoginError` |\n|         BanchoMessage          |           `chio.Message`            |\n|           BanchoPing           |                 N/A                 |\n|    BanchoIrcChangeUsername     | `str` (old name), `str` (new name)  |\n|         BanchoIrcQuit          |          `str` (Username)           |\n|        BanchoUserStats         |           `chio.UserInfo`           |\n|         BanchoUserQuit         |           `chio.UserQuit`           |\n|     BanchoSpectatorJoined      |           `int` (UserId)            |\n|      BanchoSpectatorLeft       |           `int` (UserId)            |\n|      BanchoSpectateFrames      |      `chio.ReplayFrameBundle`       |\n|       OsuStartSpectating       |           `int` (UserId)            |\n|       OsuStopSpectating        |           `int` (UserId)            |\n|       OsuSpectateFrames        |      `chio.ReplayFrameBundle`       |\n|      BanchoVersionUpdate       |                 N/A                 |\n|         OsuErrorReport         |          `str` (Exception)          |\n|        OsuCantSpectate         |                 N/A                 |\n|  BanchoSpectatorCantSpectate   |           `int` (UserId)            |\n|       BanchoGetAttention       |                 N/A                 |\n|         BanchoAnnounce         |           `str` (Message)           |\n|       OsuPrivateMessage        |           `chio.Message`            |\n|       BanchoMatchUpdate        |            `chio.Match`             |\n|         BanchoMatchNew         |            `chio.Match`             |\n|       BanchoMatchDisband       |           `int` (MatchId)           |\n|          OsuLobbyPart          |                 N/A                 |\n|          OsuLobbyJoin          |                 N/A                 |\n|         OsuMatchCreate         |            `chio.Match`             |\n|          OsuMatchJoin          |           `int` (MatchId)           |\n|          OsuMatchPart          |                 N/A                 |\n|        BanchoLobbyJoin         |           `int` (UserId)            |\n|        BanchoLobbyPart         |           `int` (UserId)            |\n|     BanchoMatchJoinSuccess     |            `chio.Match`             |\n|      BanchoMatchJoinFail       |                 N/A                 |\n|       OsuMatchChangeSlot       |           `int` (SlotId)            |\n|         OsuMatchReady          |                 N/A                 |\n|          OsuMatchLock          |           `int` (SlotId)            |\n|     OsuMatchChangeSettings     |            `chio.Match`             |\n|  BanchoFellowSpectatorJoined   |           `int` (UserId)            |\n|   BanchoFellowSpectatorLeft    |           `int` (UserId)            |\n|         OsuMatchStart          |                 N/A                 |\n|        BanchoMatchStart        |            `chio.Match`             |\n|      OsuMatchScoreUpdate       |          `chio.ScoreFrame`          |\n|     BanchoMatchScoreUpdate     |          `chio.ScoreFrame`          |\n|        OsuMatchComplete        |                 N/A                 |\n|    BanchoMatchTransferHost     |                 N/A                 |\n|       OsuMatchChangeMods       |             `chio.Mods`             |\n|      OsuMatchLoadComplete      |                 N/A                 |\n|  BanchoMatchAllPlayersLoaded   |                 N/A                 |\n|       OsuMatchNoBeatmap        |                 N/A                 |\n|        OsuMatchNotReady        |                 N/A                 |\n|         OsuMatchFailed         |                 N/A                 |\n|    BanchoMatchPlayerFailed     |           `int` (SlotId)            |\n|      BanchoMatchComplete       |                 N/A                 |\n|       OsuMatchHasBeatmap       |                 N/A                 |\n|      OsuMatchSkipRequest       |                 N/A                 |\n|        BanchoMatchSkip         |                 N/A                 |\n|         OsuChannelJoin         |        `str` (Channel Name)         |\n|    BanchoChannelJoinSuccess    |        `str` (Channel Name)         |\n|     BanchoChannelAvailable     |           `chio.Channel`            |\n|      BanchoChannelRevoked      |        `str` (Channel Name)         |\n| BanchoChannelAvailableAutojoin |           `chio.Channel`            |\n|     OsuBeatmapInfoRequest      |      `chio.BeatmapInfoRequest`      |\n|     BanchoBeatmapInfoReply     |       `chio.BeatmapInfoReply`       |\n|      OsuMatchTransferHost      |           `int` (SlotId)            |\n|     BanchoLoginPermissions     |     `chio.Permissions` or `int`     |\n|       BanchoFriendsList        |             `list[int]`             |\n|         OsuFriendsAdd          |           `int` (UserId)            |\n|        OsuFriendsRemove        |           `int` (UserId)            |\n|   BanchoProtocolNegotiation    |            N/A or `int`             |\n|       BanchoTitleUpdate        |         `chio.TitleUpdate`          |\n|       OsuMatchChangeTeam       |                 N/A                 |\n|        OsuChannelLeave         |        `str` (Channel Name)         |\n|       OsuReceiveUpdates        |        `chio.PresenceFilter`        |\n|         BanchoMonitor          |                 N/A                 |\n|    BanchoMatchPlayerSkipped    |           `int` (SlotId)            |\n|      OsuSetIrcAwayMessage      |           `chio.Message`            |\n|       BanchoUserPresence       |           `chio.UserInfo`           |\n|      OsuUserStatsRequest       |             `list[int]`             |\n|         BanchoRestart          |  `int` (Retry After Milliseconds)   |\n|           OsuInvite            |           `int` (UserId)            |\n|          BanchoInvite          |           `chio.Message`            |\n|     OsuMatchChangePassword     |            `chio.Match`             |\n|   BanchoMatchChangePassword    |        `str` (New Password)         |\n|       BanchoSilenceInfo        |    `int` (Locked Until Seconds)     |\n|     OsuTournamentMatchInfo     |           `int` (MatchId)           |\n|       BanchoUserSilenced       |           `int` (UserId)            |\n|    BanchoUserPresenceSingle    |           `int` (UserId)            |\n|    BanchoUserPresenceBundle    |        `list[int]` (UserIDs)        |\n|       OsuPresenceRequest       |        `list[int]` (UserIDs)        |\n|     OsuPresenceRequestAll      |                 N/A                 |\n|     OsuChangeFriendOnlyDms     |      `bool` (Enabled/Disabled)      |\n|      BanchoUserDmsBlocked      |           `chio.Message`            |\n|     BanchoTargetIsSilenced     |           `chio.Message`            |\n|   BanchoVersionUpdateForced    |                 N/A                 |\n|       BanchoSwitchServer       |       `int` (After Idle Time)       |\n|    BanchoAccountRestricted     |                 N/A                 |\n|           BanchoRTX            |           `str` (Message)           |\n|        BanchoMatchAbort        |                 N/A                 |\n|  BanchoSwitchTournamentServer  |           `str` (Server)            |\n| OsuTournamentJoinMatchChannel  |           `int` (MatchId)           |\n| OsuTournamentLeaveMatchChannel |           `int` (MatchId)           |\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A python library for serializing and deserializing bancho packets.",
    "version": "1.1.20",
    "project_urls": null,
    "split_keywords": [
        "osu",
        " osugame",
        " python",
        " bancho"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "68ce46ff179cb7e4ebe35e6420e32f15eb01a954c8b28e6a81abb3af7253af9d",
                "md5": "36fbbfe0fa433bce3d1886d20df0201f",
                "sha256": "c7aa42cc9a137001bd34372279cc0305e30dc390961a1a8c86705d7a36091d77"
            },
            "downloads": -1,
            "filename": "chio-1.1.20-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "36fbbfe0fa433bce3d1886d20df0201f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 69957,
            "upload_time": "2025-08-08T00:46:09",
            "upload_time_iso_8601": "2025-08-08T00:46:09.296309Z",
            "url": "https://files.pythonhosted.org/packages/68/ce/46ff179cb7e4ebe35e6420e32f15eb01a954c8b28e6a81abb3af7253af9d/chio-1.1.20-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8ff632eea7aaa6fd835403235c1540ddda386662186bf015ef5d2f854f0d61c5",
                "md5": "5f0f7706a115c52461ece68d1a77f814",
                "sha256": "33f682d278d78e9eb8d87f7ad87f9d378c5d96307a718036069a50b452604e61"
            },
            "downloads": -1,
            "filename": "chio-1.1.20.tar.gz",
            "has_sig": false,
            "md5_digest": "5f0f7706a115c52461ece68d1a77f814",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 40050,
            "upload_time": "2025-08-08T00:46:10",
            "upload_time_iso_8601": "2025-08-08T00:46:10.492709Z",
            "url": "https://files.pythonhosted.org/packages/8f/f6/32eea7aaa6fd835403235c1540ddda386662186bf015ef5d2f854f0d61c5/chio-1.1.20.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-08 00:46:10",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "chio"
}
        
Elapsed time: 0.58414s