Fastest domain extractor library written in C++ with python binding.
First and complete library for parsing url in C++ and Python and Command Line
About The Project
liburlparser is a powerful domain extractor library written in C++ with Python bindings. It provides efficient URL parsing capabilities for both C++ and Python, making it a valuable tool for projects that involve working with web addresses.
Features
Here are some key features of liburlparser:
-
Multiple Language Support:
- liburlparser can be used in multiple programming languages, including
Python,C++, andShell. - It offers an intuitive interface that remains consistent across both C++ and Python.
- liburlparser can be used in multiple programming languages, including
-
Clean Code Design:
- The library provides separate classes for each concept:
Url, andHostname/IPv4/IPv6for whatever a URL's host actually is (RFC 3986 defines a host as either a domain name or an IP address, never both - liburlparser mirrors that directly instead of forcing IP addresses through domain-name-shaped fields). - This separation allows for cleaner and more organized code when dealing with URLs.
- The library provides separate classes for each concept:
-
Public Suffix List Support:
- liburlparser supports known combinatorial suffixes (e.g., "ac.ir") using the public_suffix_list.
- It can also handle unknown suffixes (e.g., "comm" in "google.comm").
-
Automatic Public Suffix List Updates:
- Before each build and deployment, liburlparser updates the public_suffix_list automatically.
-
Hostname Properties:
- The
Hostnameclass includes properties such as subdomain, domain, domain name, and suffix.
- The
-
IPv4 / IPv6 Support:
IPv4/IPv6addresses used as a URL's host are recognized and parsed as such - not run through domain-name logic. Both support integer conversion and arithmetic (+,-,+=,-=, increment/decrement).
-
URL Properties:
- The
Urlclass provides properties like protocol, userinfo, host (classified asHostname/IPv4/IPv6), port, path, query parameters, and fragment.
- The
Usage
Command Line
python -m liburlparser --help # show help section
python -m liburlparser --version # show version
python -m liburlparser --url "https://mail.google.com/about" | jq #return as json
python -m liburlparser --host "mail.google.com" | jq # return as json
Python
you can use liburlparser so intutively
all of classes has help section
import liburlparser
help(liburlparser)
print(liburlparser.__version__)
from liburlparser import Url, Hostname, IPv4, IPv6
help(Url)
help(Hostname)
parse url and host
from liburlparser import Url, Hostname, Host
## parse url:
url = Url("https://ee.aut.ac.ir/#id") # parse all part of url
print(url, url.host_text, url.fragment, url.host, url.to_dict(), url.to_json())
## url.host is a Hostname, IPv4, or IPv6 object - whichever this URL's host
## actually is (an IP address has no "domain"/"suffix", so it's simply not
## forced through Hostname at all)
host = url.host # a Hostname, here: ee.aut.ac.ir
# or
host = Hostname("ee.aut.ac.ir")
# or
host = Hostname.from_url("https://ee.aut.ac.ir/#id") # the fastest way for parsing host from url
print(host, host.domain, host.suffix, host.to_dict(), host.to_json())
## for a host you don't know in advance is a domain or an IP, use Host():
host2 = Host("192.168.1.1") # is_ipv4() -> True
host3 = Host("ee.aut.ac.ir") # is_hostname() -> True
print(host2.is_ipv4(), host2, int(host2.get_ipv4())) # True 192.168.1.1 3232235777
print(host3.is_hostname(), host3, host3.get_hostname().domain) # True ee.aut.ac.ir aut
IPv4/IPv6 addresses support integer conversion and arithmetic:
from liburlparser import IPv4, IPv6
ip = IPv4("192.168.1.1")
print(int(ip)) # 3232235777
print(ip + 1) # 192.168.1.2
print(ip - IPv4("192.168.1.0")) # 1 (distance between two addresses)
ip6 = IPv6("2001:db8::1")
print(ip6.high64, ip6.low64)
print(ip6 + 1) # 2001:db8::2
Also there is some helping api to get better performance for some small tasks
# if you need to extract the host of url as a string without any parsing
host_str = Url.extract_host("https://ee.aut.ac.ir/about") # very fast
C++
there is some examples in examples folder
#include "urlparser.h"
...
/// for parsing url
urlparser::url url("https://ee.aut.ac.ir/about");
std::string_view host_text = url.host_text(); // the raw host text, unclassified
/// url.host() is a urlparser::host (hostname/ipv4/ipv6, whichever this
/// URL's host actually is)
if (auto* h = url.host().try_hostname()) {
std::cout << h->domain() << "." << h->suffix();
}
/// for parsing a host you already have (or a full URL) directly:
urlparser::hostname host("ee.aut.ac.ir");
// or
urlparser::hostname host2 = urlparser::hostname::from_url("https://ee.aut.ac.ir/about");
// or, when you don't know in advance whether it's a domain or an IP:
urlparser::host classified = urlparser::host::from_url("http://192.168.1.1/about"); // -> is_ipv4() true
you can see all methods in python we can use in c++ very easily
Installation
C++:
build steps:
# 1. Clone the repository with submodules (recursive)
# --recursive is essential to download third-party libs like googletest
git clone --recursive https://github.com/mohammadraziei/liburlparser
cd liburlparser
# 2. Configure the project
# -B build tells CMake to create a 'build' directory and generate files there
cmake -B build
# 3. Build the project
# --build abstracts the underlying build tool (Make, Ninja, MSBuild, etc.)
cmake --build build --config Debug
# 4. Run examples
# Note: On Windows, the path might be ./build/Debug/example.exe
./build/example
# 5. Make install
# --install handles the installation process
sudo cmake --install build
Python and Command Line:
Be aware that it required python>=3.8
Installation
from source
To install from source, you must ensure all submodules are cloned:
# 1. Clone recursively to get third-party dependencies
git clone --recursive https://github.com/mohammadraziei/liburlparser
cd liburlparser
# 2. Install using pip
pip install .
# Optional: If you want to see build logs
pip install . -v
pip by pypi
pip install liburlparser
Or
pip by git
pip install git+https://github.com/mohammadraziei/liburlparser
Or
manually
git clone https://github.com/mohammadraziei/liburlparser
pip install ./liburlparser
Performance
Extract From Host
Tests were run on a file containing 10 million random domains from various top-level domains (Mar. 13rd 2022)
| Library | Function | Time |
|---|---|---|
| liburlparser | liburlparser.Hostname | 1.12s |
| PyDomainExtractor | pydomainextractor.extract | 1.50s |
| publicsuffix2 | publicsuffix2.get_sld | 9.92s |
| tldextract | __call__ | 29.23s |
| tld | tld.parse_tld | 34.48s |
Extract From URL
The test was conducted on a file containing 1 million random urls (Mar. 13rd 2022)
| Library | Function | Time |
|---|---|---|
| liburlparser | liburlparser.Hostname.from_url | 2.10s |
| PyDomainExtractor | pydomainextractor.extract_from_url | 2.24s |
| publicsuffix2 | publicsuffix2.get_sld | 10.84s |
| tldextract | __call__ | 36.04s |
| tld | tld.parse_tld | 57.87s |
License
Distributed under the MIT License. See LICENSE for more information.
Stats
Contact
Project Link:
Metadata
Release files for liburlparser 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| liburlparser-2.0.0.tar.gz | 279.3 kB | Details |
Built distributions (wheels)
Total release size: 8.3 MB
Release files / liburlparser-2.0.0.tar.gz
| Download URL | liburlparser-2.0.0.tar.gz |
|---|---|
| Size | 279.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ded07a6ec8ba4b293d8d0e47cb37976cdc87f294d457ed57b09597985c61acaf
|
|
BLAKE2b-256 checksum How to use checksums |
8c242482704f1959636071f6304b165c1ca1f28139a133ac0577a433916427a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp312-cp312-win_amd64.whl
| Download URL | liburlparser-2.0.0-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 229.3 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
d306368c4c0a8f0c0a8f5a099fa19c1aa502b80b42bb67faee81555adcfb35f7
|
|
BLAKE2b-256 checksum How to use checksums |
dec784548f1e341ec93948cb87e58176da7674f8b5cd05dab042b7e06b75e0e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp312-cp312-win32.whl
| Download URL | liburlparser-2.0.0-cp312-cp312-win32.whl |
|---|---|
| Size | 213.5 kB |
| Tags | CPython 3.12 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
ff0942da7a6b6e2d7be7e4b36706cf1c844d41f9e29bcd5c185d4b2ec9f5ee2d
|
|
BLAKE2b-256 checksum How to use checksums |
118265f347ff12beeef26accf767cf329471244d7d97858f44d27ff854eab0e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl
| Download URL | liburlparser-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 676.4 kB |
| Tags | CPython 3.12 Linux musl 1.2+ x86-64 |
|
SHA-256 checksum How to use checksums |
228587be4ab8b65049aedcdb347f64392c5f3ad152d2f78a525c528bfe3d3270
|
|
BLAKE2b-256 checksum How to use checksums |
04bc8080193734b0d80144af5523618a7c2017963e1054af40d2bd71b90e2c1e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp312-cp312-musllinux_1_2_i686.whl
| Download URL | liburlparser-2.0.0-cp312-cp312-musllinux_1_2_i686.whl |
|---|---|
| Size | 720.6 kB |
| Tags | CPython 3.12 Linux musl 1.2+ x86-32 |
|
SHA-256 checksum How to use checksums |
134043c55597ef3b3408a140880f3c3987365853a590418d18265e10fb1cafa3
|
|
BLAKE2b-256 checksum How to use checksums |
b7126497b24a965814807cf4a2f26dd85283201930b695a2ab24b3623fb50fd0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | liburlparser-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 215.8 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
d6f0203714d81eddaa60f65420fcd21509d4fd394aae39c4c8709f39c8be5b91
|
|
BLAKE2b-256 checksum How to use checksums |
3b76b23493cf967c6906d1f7aa7cd82bca9ca0550acf263407821ba1f80eccec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
| Download URL | liburlparser-2.0.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl |
|---|---|
| Size | 221.2 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-32 |
|
SHA-256 checksum How to use checksums |
ffbcbeb37748423e73659eedeb2d8bca624fd9db9dac6298527dc8496322b622
|
|
BLAKE2b-256 checksum How to use checksums |
e252b96e968944bbf75c4d112c321ef97e13ab7666f8aaa0e591e84a146039d2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp312-cp312-macosx_10_13_universal2.whl
| Download URL | liburlparser-2.0.0-cp312-cp312-macosx_10_13_universal2.whl |
|---|---|
| Size | 384.8 kB |
| Tags | CPython 3.12 macOS 10.13+ universal2 (ARM64, x86-64) |
|
SHA-256 checksum How to use checksums |
eca93484db0bfcc5c4ec8453eeab4654151c243183f382f628e73ac6a443be73
|
|
BLAKE2b-256 checksum How to use checksums |
1a282a6044f5f1ece55da11ba532b85421d1e93dbdc826501c735f6069ae9d53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp311-cp311-win_amd64.whl
| Download URL | liburlparser-2.0.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 229.6 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
0f3aef9ca5c7fccc0930ecee0710bbb0085d32c1a3ba5b439dd4a4c66849c2f0
|
|
BLAKE2b-256 checksum How to use checksums |
f15e14517c557dd7f7cff35be232e38f0ffce6c88fbccd914170d90ef2204071
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp311-cp311-win32.whl
| Download URL | liburlparser-2.0.0-cp311-cp311-win32.whl |
|---|---|
| Size | 214.2 kB |
| Tags | CPython 3.11 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
d864949aca96ececcf97b98935a11e62002ded10c25229a003ddace7f6d21480
|
|
BLAKE2b-256 checksum How to use checksums |
23b80e3c9d1bcbd59845a2991dc89279559d37fe70dd6db30a4d5ea3cc430b04
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl
| Download URL | liburlparser-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 680.8 kB |
| Tags | CPython 3.11 Linux musl 1.2+ x86-64 |
|
SHA-256 checksum How to use checksums |
d9a36d03517384c357b0dbf31685018c4a5ae18f5f63ff3ea7841dd35368a4a9
|
|
BLAKE2b-256 checksum How to use checksums |
f9512cdf58a41156b9454bc57b8842eeb6059675c56ed92877aa7465999ecfb3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp311-cp311-musllinux_1_2_i686.whl
| Download URL | liburlparser-2.0.0-cp311-cp311-musllinux_1_2_i686.whl |
|---|---|
| Size | 725.1 kB |
| Tags | CPython 3.11 Linux musl 1.2+ x86-32 |
|
SHA-256 checksum How to use checksums |
3ef2e607547e0d393b92b35b3894e7e0503bb923c17d4ffef5844956535abcca
|
|
BLAKE2b-256 checksum How to use checksums |
aab255dd60dfd3c9a04fffa52b683273d90a3b1b4d33e78c4568af62e296c6ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | liburlparser-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 219.2 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
b6b9d362e7ddc6ef80d582f2151dc0d1b91a288700f9764720e4280c49233719
|
|
BLAKE2b-256 checksum How to use checksums |
597b885a6409135fd43e263c63a0733fb415410e5f930d3ba9ccb4ac663aa095
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl
| Download URL | liburlparser-2.0.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl |
|---|---|
| Size | 226.0 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-32 |
|
SHA-256 checksum How to use checksums |
74a0868d99d4c39480fb744a52035de8ac524b099aa0bc64d1c3ce36550d3bb9
|
|
BLAKE2b-256 checksum How to use checksums |
3a75191f40d8c10165e28b6efe84a363191be924b752d2c36c8350212c861688
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp311-cp311-macosx_10_13_universal2.whl
| Download URL | liburlparser-2.0.0-cp311-cp311-macosx_10_13_universal2.whl |
|---|---|
| Size | 386.2 kB |
| Tags | CPython 3.11 macOS 10.13+ universal2 (ARM64, x86-64) |
|
SHA-256 checksum How to use checksums |
39566dfcfba15949b632ca2b9edcdb8f027db07fffc5f3a10e72e143e27dc09d
|
|
BLAKE2b-256 checksum How to use checksums |
bc96c44773fc0345f85645788ad551e817bf5c988c4d88e81c66495300713b7e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp310-cp310-win_amd64.whl
| Download URL | liburlparser-2.0.0-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 229.3 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
7c597e9304ff1b7395cca7cba9405e8d659660c157ee46b2c7c0c4a67e8c50fb
|
|
BLAKE2b-256 checksum How to use checksums |
7f358d291dd7b78c40e62c36b700f9068dab75af4d1be56550d634c3a71336e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp310-cp310-win32.whl
| Download URL | liburlparser-2.0.0-cp310-cp310-win32.whl |
|---|---|
| Size | 214.0 kB |
| Tags | CPython 3.10 Windows x86-32 |
|
SHA-256 checksum How to use checksums |
cca4ba084016624430ee6961e3a3d8da498ead4af5c84db7bc28589af03ff988
|
|
BLAKE2b-256 checksum How to use checksums |
46ea1cbc22d78812969031cae9c9e15e615c4561d5ac3cfef8ee09b314670e2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl
| Download URL | liburlparser-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 681.0 kB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 |
|
SHA-256 checksum How to use checksums |
632c7f7c20dbb105ef5343f4179b45acd9b533b3c965b39b3a918ec8b5f8a6fe
|
|
BLAKE2b-256 checksum How to use checksums |
4c1f8d7f3e22ded108e184a35eedf29350785c35c6a9a307f369894f323d5971
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp310-cp310-musllinux_1_2_i686.whl
| Download URL | liburlparser-2.0.0-cp310-cp310-musllinux_1_2_i686.whl |
|---|---|
| Size | 726.2 kB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-32 |
|
SHA-256 checksum How to use checksums |
4d9fadb8434652c6ef779de9b983f811a7e60366f9b2f9ae1c9d7b7bfd0b2df5
|
|
BLAKE2b-256 checksum How to use checksums |
fca9f24ddcbf4b10d7bd66097d8ecf60373c340bf1acd298b111961ffa644e8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | liburlparser-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 219.5 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
1bc9aaeeab84bbf002c0d2c8b4a4b7bde366a78e6aeeabec5a0a58cd848e1218
|
|
BLAKE2b-256 checksum How to use checksums |
a3c4a4fcccabbeb03bba37837ea754b0db9261d296e9bc29ec2b220f8360a4cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl
| Download URL | liburlparser-2.0.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl |
|---|---|
| Size | 226.6 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-32 |
|
SHA-256 checksum How to use checksums |
6bce3ec9e72c77bf09a0f052dcb4a03b8fe6b8aae5bbaa061197256e44d88eb6
|
|
BLAKE2b-256 checksum How to use checksums |
6d0e8114d538ddbae5943cb208a5e43730aff314ea50abe4d700c6372eb2f332
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / liburlparser-2.0.0-cp310-cp310-macosx_10_13_universal2.whl
| Download URL | liburlparser-2.0.0-cp310-cp310-macosx_10_13_universal2.whl |
|---|---|
| Size | 386.7 kB |
| Tags | CPython 3.10 macOS 10.13+ universal2 (ARM64, x86-64) |
|
SHA-256 checksum How to use checksums |
593e765858c420e9deb9819de259affb8e6410a544957f3298cd48b81e739a19
|
|
BLAKE2b-256 checksum How to use checksums |
6705eb7f844072c67a9081f57c6ae4ebc63d53eb3e58586209b48ff0a8af1e78
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|