20 Commits

Author SHA1 Message Date
renovate[bot]
18020f3bc8 ⬆️ Upgrade src/dismoji/raw digest to 7876468 (#28)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-01 23:11:47 +02:00
7a42ead179 🔧 Update renovate incorrect base branch (#27) 2025-09-01 23:10:53 +02:00
1d9d14f1ed 🐛 Fix missing comma in renovate.json (#26) 2025-09-01 23:07:38 +02:00
cc7d78a47a feat: Update Renovate configuration and extend settings (#24) 2025-09-01 23:04:05 +02:00
renovate[bot]
fe3bcffa24 ⬆️ Upgrade actions/checkout action to v5 (#23)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 16:11:23 +02:00
renovate[bot]
b01368182f ⬆️ Upgrade hashicorp/setup-copywrite digest to 32f9f1c (#22)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-22 22:37:56 +02:00
9fb0c776d7 📝 Add acknowledgements section to README for API design inspiration (#20) 2025-05-29 14:44:52 +02:00
cfa8812081 🐛 Fix some complex emojis not being converted and enhance test coverage (#19) 2025-05-29 14:41:33 +02:00
34739a077c Refactor emojize and demojize functions to use shared replacement functions for improved performance (#18) 2025-05-29 13:52:50 +02:00
47aa6a3fc1 Add __all__ declaration to expose public API for emojize and demojize functions (#17) 2025-05-29 13:41:52 +02:00
ad98dd9a58 Implement demojize function for bidirectional emoji conversion (#16)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-29 13:38:56 +02:00
a1d2592ee1 ⬆️ Update subproject commit reference in dismoji/raw (#9) 2025-05-19 10:54:14 +02:00
6dc46f06d6 Optimize memory usage by removing EMOJIS variable after mapping (#10) 2025-05-19 10:51:33 +02:00
8af0deea07 🔧 Add pydocstyle convention and clean up pyproject.toml (#11) 2025-05-19 10:48:59 +02:00
2014fb4a61 Fix emoji pattern to work without spaces and enhance test coverage for emojize function (#8) 2025-05-04 01:35:32 +02:00
e1fa04ad70 Lock uv.lock (#7) 2025-05-04 01:01:27 +02:00
57720ff191 Allow broader python versions in pyproject my bad (#6) 2025-05-04 00:55:44 +02:00
b40ac78ae5 Remove unnecessary json5 from dependencies (#3) 2025-05-04 00:51:47 +02:00
3ba10846a7 Improve project metadata (#2) 2025-05-04 00:48:55 +02:00
8d957198b9 Fix missing submodules in publish action checkout (#1) 2025-05-04 00:39:57 +02:00
9 changed files with 238 additions and 62 deletions

View File

@@ -9,7 +9,9 @@ jobs:
runs-on: ubuntu-latest
environment: pypi
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
submodules: true
- name: "Install uv"
uses: astral-sh/setup-uv@v6

View File

@@ -9,9 +9,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Copywrite
uses: hashicorp/setup-copywrite@5e3e8a26d7b9f8a508848ad0a069dfd2f7aa5339
uses: hashicorp/setup-copywrite@32f9f1c86f661b8a51100768976a06f1b281a035
- name: Check Header Compliance
run: copywrite headers --plan --config .copywrite.hcl
@@ -35,7 +35,7 @@ jobs:
name: "Python 3.13"
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
submodules: true
@@ -75,7 +75,7 @@ jobs:
name: ${{ matrix.name }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: "Install uv"
uses: astral-sh/setup-uv@v6

View File

@@ -12,7 +12,8 @@
<!-- end badges -->
A Python library for converting Discord emoji names to their Unicode equivalents.
A Python library for converting Discord emoji names to their Unicode equivalents and
vice versa.
</div>
@@ -30,10 +31,10 @@ A Python library for converting Discord emoji names to their Unicode equivalents
## Overview
dismoji is a lightweight Python library that provides a simple way to convert Discord
emoji names to their Unicode equivalents. With just a single function call, you can
transform text containing Discord-style emoji codes (like `:smile:`) into text with
actual Unicode emoji characters (like "😄").
Dismoji is a lightweight Python library that provides a simple way to convert Discord
emoji names to their Unicode equivalents and vice versa. With just two function calls,
you can transform text containing Discord-style emoji codes (like `:smile:`) into text
with actual Unicode emoji characters (like "😄") and back again.
This library uses
[Paillat-dev/discord-emojis](https://github.com/Paillat-dev/discord-emojis) as the
@@ -56,16 +57,23 @@ import dismoji
text = "Hello, :wave: I'm excited! :partying_face:"
converted_text = dismoji.emojize(text)
print(converted_text) # Output: "Hello, 👋 I'm excited! 🥳"
# Convert Unicode emojis back to Discord emoji names
emoji_text = "Hello, 👋 I'm excited! 🥳"
named_text = dismoji.demojize(emoji_text)
print(named_text) # Output: "Hello, :wave: I'm excited! :partying_face:"
```
## Features
- **Simple API**: Just one function to remember - `dismoji.emojize()`
- **Simple API**: Just two functions to remember - `dismoji.emojize()` and
`dismoji.demojize()`
- **Discord Compatible**: Supports Discord's emoji naming conventions
- **Comprehensive**: Includes all standard emojis available on Discord
- **Type Safe**: Fully type-annotated for better IDE integration
- **Zero Dependencies**: Lightweight with no external dependencies
- **Fast**: Optimized for quick emoji replacement
- **Bidirectional**: Convert between emoji names and characters in both directions
## Getting Help
@@ -94,6 +102,10 @@ If you encounter issues or have questions about dismoji:
- **HashiCorp Copywrite**: For managing license headers
- **basedpyright**: For type checking
## Acknowledgements
- [`emoji`](https://pypi.org/project/emoji/) as inspiration for the API design
## License
MIT License - Copyright (c) 2025 Paillat-dev

View File

@@ -5,12 +5,12 @@ build-backend = "hatchling.build"
[project]
name = "dismoji"
dynamic = ["version", "urls", "readme"]
description = "***"
description = "A Python library for converting Discord emoji names to their Unicode equivalents."
authors = [
{ name = "Paillat-dev", email = "me@paillat.dev" }
]
license = "MIT"
requires-python = "==3.12.*"
requires-python = ">=3.9,<3.14"
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
@@ -25,9 +25,7 @@ classifiers = [
"Operating System :: OS Independent",
]
keywords = ["discord", "bot", "emojis", "emoji"]
dependencies = [
"json5>=0.12.0",
]
dependencies = []
[dependency-groups]
dev = [
@@ -122,6 +120,7 @@ exclude = [
"src/dismoji/_version.py"
]
[tool.ruff.lint]
select = ["ALL"]
per-file-ignores = { "examples/**/*" = ["INP001", "ARG002", "T201"], "tests/**/*" = ["S101"], "src/dismoji/_version.py" = ["I001", "Q000", "UP005", "UP006", "UP035"] }
@@ -153,6 +152,7 @@ extend-ignore = [
"C901",
"ISC003" # conflicts with basedpyright reportImplicitStringConcatenation
]
pydocstyle.convention = "google"
[tool.uv.sources]
py-cord = { git = "https://github.com/Pycord-Development/pycord", rev = "c0c0b7c58f7b489983a159f5e0eea2c0dab0b0c8" }

View File

@@ -1,25 +1,18 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"baseBranches": ["master"],
"labels": ["deps"],
"ignorePaths": ["requirements.txt"],
"commitMessagePrefix": "⬆️",
"commitMessageAction": "Upgrade",
"packageRules": [
{
"updateTypes": ["pin"],
"commitMessagePrefix": "📌",
"commitMessageAction": "Pin"
},
{
"updateTypes": ["rollback"],
"commitMessagePrefix": "⬇️",
"commitMessageAction": "Downgrade"
},
{
"matchDatasources": ["pypi"],
"addLabels": ["pypi"]
}
]
"extends": [
"local>nicebots-xyz/renovate-config",
":semanticPrefixFixDepsChoreOthers",
":dependencyDashboard"
],
"git-submodules": {
"enabled": true
},
"forkProcessing": "enabled",
"baseBranchPatterns": [
"master"
],
"lockFileMaintenance": {
"enabled": true
}
}

View File

@@ -12,9 +12,32 @@ EMOJIS_PATH = Path(__file__).parent / "raw" / "build" / "emojis.json"
with EMOJIS_PATH.open("r", encoding="utf-8") as f:
EMOJIS = json.load(f)
EMOJI_MAPPING: dict[str, str] = {k: EMOJIS["emojis"][v]["surrogates"] for k, v in EMOJIS["nameToEmoji"].items()}
_VARIATION_SELECTOR = "\ufe0f" # We remove this as it is not needed by discord and causes issues with tests
EMOJI_MAPPING: dict[str, str] = {
k: EMOJIS["emojis"][v]["surrogates"].replace(_VARIATION_SELECTOR, "") for k, v in EMOJIS["nameToEmoji"].items()
}
EMOJI_PATTERN = re.compile(r"(?<!\w):([a-zA-Z0-9_-]+):(?!\w)")
REVERSE_EMOJI_MAPPING: dict[str, str] = {}
for emoji_index_str, emoji_index in sorted(EMOJIS["surrogateToEmoji"].items(), key=lambda x: len(x[0]), reverse=True):
# Get the first name in the list as the preferred name
e = EMOJIS["emojis"][emoji_index]
# If it has multiple diversity parents, use the last name because it is the most specific one
# e.g. :handshake_light_skin_tone_dark_skin_tone: vs :handshake_tone1_tone5:
REVERSE_EMOJI_MAPPING[emoji_index_str] = e["names"][-1 if e.get("hasMultiDiversityParent") else 0]
del EMOJIS, _VARIATION_SELECTOR # Clean up to save memory
EMOJI_PATTERN = re.compile(r":([\w+-]+):")
EMOJI_CHARS_PATTERN = re.compile("|".join(map(re.escape, REVERSE_EMOJI_MAPPING.keys())))
def _replace(match: re.Match[str]) -> str:
emoji_name = match.group(1)
if emoji_name in EMOJI_MAPPING:
return EMOJI_MAPPING[emoji_name]
return match.group(0)
def emojize(s: str) -> str:
@@ -27,11 +50,30 @@ def emojize(s: str) -> str:
str: The input string with emoji names replaced by emoji characters.
"""
return EMOJI_PATTERN.sub(_replace, s)
def replace(match: re.Match[str]) -> str:
emoji_name = match.group(1)
if emoji_name in EMOJI_MAPPING:
return EMOJI_MAPPING[emoji_name]
return match.group(0)
return EMOJI_PATTERN.sub(replace, s)
def _reverse_replace(match: re.Match[str]) -> str:
emoji = match.group(0)
return f":{REVERSE_EMOJI_MAPPING[emoji]}:"
def demojize(s: str) -> str:
"""Convert a string with emoji characters to a string with emoji names.
Args:
s (str): The input string containing emoji characters.
Returns:
str: The input string with emoji characters replaced by emoji names.
"""
return EMOJI_CHARS_PATTERN.sub(_reverse_replace, s)
__all__ = (
"EMOJI_MAPPING",
"REVERSE_EMOJI_MAPPING",
"demojize",
"emojize",
)

View File

@@ -1,7 +1,26 @@
# Copyright (c) Paillat-dev
# SPDX-License-Identifier: MIT
from dismoji import emojize
from dismoji import EMOJI_MAPPING, REVERSE_EMOJI_MAPPING, demojize, emojize
def are_equal(a: str, b: str) -> bool:
"""Check if two emojis are equal.
Allows for comparing emojis with modifiers even when they are in different orders.
Args:
a (str): First emoji string.
b (str): Second emoji string.
Returns:
bool: True if the emojis are equal, False otherwise.
"""
if len(a) != len(b):
return False
if len(a) == 1:
return a == b
return a[0] == b[0] and set(a[1:]) == set(b[1:])
def test_basic() -> None:
@@ -41,3 +60,74 @@ def test_multiple_emojis() -> None:
def test_complex_sentence() -> None:
"""Test emojize function with a complex sentence."""
assert emojize("Hello :wave:, what's up? :smile: :white_check_mark: :smile:") == "Hello 👋, what's up? 😄 ✅ 😄"
def test_spaces() -> None:
"""Test emojize function with spaces."""
space_tests = [
("Hello :smile::smile:", "Hello 😄😄"),
("Hii what's up :wave:?", "Hii what's up 👋?"),
("Hello:wave: :smile:", "Hello👋 😄"),
("Hellooo :wave:hru?", "Hellooo 👋hru?"),
("Hii:wave:hru?", "Hii👋hru?"),
]
for input_str, expected_output in space_tests:
assert emojize(input_str) == expected_output
def test_emoji_with_special_characters() -> None:
"""Test emojize function with special characters."""
special_char_tests = [
("Hello :smile:!", "Hello 😄!"),
("Hello :smile:?", "Hello 😄?"),
("Hello :smile::smile:!", "Hello 😄😄!"),
("Hello :smile::smile:?", "Hello 😄😄?"),
("Hello :smile::smile::smile:!", "Hello 😄😄😄!"),
("Hello :smile::smile::smile:?", "Hello 😄😄😄?"),
]
for input_str, expected_output in special_char_tests:
assert emojize(input_str) == expected_output
def test_emojize_all() -> None:
for name, emoji in EMOJI_MAPPING.items():
assert are_equal(emojize(f":{name}:"), emoji)
def test_demojize_basic() -> None:
"""Test basic functionality of demojize function."""
assert demojize("Hello 😄") == "Hello :smile:"
def test_demojize_no_match() -> None:
"""Test demojize function with no matches."""
assert demojize("Hello world") == "Hello world"
def test_demojize_multiple_emojis() -> None:
"""Test demojize function with multiple emojis."""
assert demojize("😄 👋") == ":smile: :wave:"
def test_demojize_complex_sentence() -> None:
"""Test demojize function with a complex sentence."""
assert demojize("Hello 👋, what's up? 😄 ✅ 😄") == "Hello :wave:, what's up? :smile: :white_check_mark: :smile:"
def test_demojize_surrogate() -> None:
"""Test demojize function with surrogate pairs."""
surrogate_pairs = [
("🫱🏻‍🫲🏿", ":handshake_light_skin_tone_dark_skin_tone:"),
("🫱🏿‍🫲🏻", ":handshake_dark_skin_tone_light_skin_tone:"),
("🫱🏽‍🫲🏻", ":handshake_medium_skin_tone_light_skin_tone:"),
("🫱🏼‍🫲🏿", ":handshake_medium_light_skin_tone_dark_skin_tone:"),
("🫱🏾‍🫲🏻", ":handshake_medium_dark_skin_tone_light_skin_tone:"),
]
for surrogate, emoji_name in surrogate_pairs:
assert demojize(surrogate) == emoji_name
def test_demojize_all() -> None:
for emoji, name in REVERSE_EMOJI_MAPPING.items():
assert demojize(emoji) == f":{name}:"

65
uv.lock generated
View File

@@ -1,6 +1,6 @@
version = 1
revision = 1
requires-python = "==3.12.*"
requires-python = ">=3.9, <3.14"
[[package]]
name = "basedpyright"
@@ -26,9 +26,6 @@ wheels = [
[[package]]
name = "dismoji"
source = { editable = "." }
dependencies = [
{ name = "json5" },
]
[package.dev-dependencies]
dev = [
@@ -39,7 +36,6 @@ dev = [
]
[package.metadata]
requires-dist = [{ name = "json5", specifier = ">=0.12.0" }]
[package.metadata.requires-dev]
dev = [
@@ -49,6 +45,15 @@ dev = [
{ name = "ruff", specifier = ">=0.9.9" },
]
[[package]]
name = "exceptiongroup"
version = "1.2.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 },
]
[[package]]
name = "iniconfig"
version = "2.1.0"
@@ -58,15 +63,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 },
]
[[package]]
name = "json5"
version = "0.12.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/12/be/c6c745ec4c4539b25a278b70e29793f10382947df0d9efba2fa09120895d/json5-0.12.0.tar.gz", hash = "sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a", size = 51907 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/41/9f/3500910d5a98549e3098807493851eeef2b89cdd3032227558a104dfe926/json5-0.12.0-py3-none-any.whl", hash = "sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db", size = 36079 },
]
[[package]]
name = "nodejs-wheel-binaries"
version = "22.14.0"
@@ -107,9 +103,11 @@ version = "8.3.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
{ name = "iniconfig" },
{ name = "packaging" },
{ name = "pluggy" },
{ name = "tomli", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 }
wheels = [
@@ -149,3 +147,42 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/42/46/8997872bc44d43df986491c18d4418f1caff03bc47b7f381261d62c23442/ruff-0.11.6-py3-none-win_amd64.whl", hash = "sha256:cce85721d09c51f3b782c331b0abd07e9d7d5f775840379c640606d3159cae0e", size = 11558592 },
{ url = "https://files.pythonhosted.org/packages/d7/6a/65fecd51a9ca19e1477c3879a7fda24f8904174d1275b419422ac00f6eee/ruff-0.11.6-py3-none-win_arm64.whl", hash = "sha256:3567ba0d07fb170b1b48d944715e3294b77f5b7679e8ba258199a250383ccb79", size = 10682766 },
]
[[package]]
name = "tomli"
version = "2.2.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 },
{ url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 },
{ url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 },
{ url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 },
{ url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 },
{ url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 },
{ url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 },
{ url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 },
{ url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 },
{ url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 },
{ url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 },
{ url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 },
{ url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 },
{ url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 },
{ url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 },
{ url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 },
{ url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 },
{ url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 },
{ url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 },
{ url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 },
{ url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 },
{ url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 },
{ url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 },
{ url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 },
{ url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 },
{ url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 },
{ url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 },
{ url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 },
{ url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 },
{ url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 },
{ url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 },
]