feat: basically finish pkgconfig generation
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# Developer Notes
|
||||
|
||||
## Bump Version Up
|
||||
|
||||
TODO
|
||||
@@ -0,0 +1,35 @@
|
||||
# sarasacw-omrf-packer
|
||||
|
||||
All packer used properties are stored in target Rust manifest file as metadata style.
|
||||
There is an example about how to define them in `Cargo.toml`.
|
||||
|
||||
```toml
|
||||
[package.metadata.omrf]
|
||||
# Configures the minimum required sarasacw-omrf-packer version.
|
||||
# Trying to run with an older version causes an error.
|
||||
# This property is optional. If there is no specification, no version constraint is applied.
|
||||
min_version = "1.0.0"
|
||||
|
||||
[package.metadata.omrf.headers]
|
||||
assets = [
|
||||
# `from` is the relative path to directory where this Cargo.toml is.
|
||||
# `to` is the relative path to `include` directory which is the subdirectory of installation directory.
|
||||
# Blank `to` means that put it directly in `include` directory.
|
||||
{ from = "cbindgen/my_crate.h", to = "" },
|
||||
{ from = "cbindgen/our_crate.h", to = "SomePrefix" },
|
||||
# `from` support UNIX style pathname pattern expansion.
|
||||
# It will find the toppest immutable component of given pattern.
|
||||
# In this exmaple, this toppest immutable component is `pattern/with`.
|
||||
# And use that as the root directory and put found files to `to` directory
|
||||
# with preserving directory hierarchy.
|
||||
{ from = "pattern/with/**/*", to = "" }
|
||||
{ from = "pattern/with/**/*", to = "AllInOne" }
|
||||
]
|
||||
|
||||
[package.metadata.omrf.cmake]
|
||||
|
||||
|
||||
[package.metadata.omrf.pkgconfig]
|
||||
|
||||
|
||||
```
|
||||
|
||||
@@ -10,6 +10,7 @@ requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"jinja2==3.1.6",
|
||||
"semver>=3.0.4",
|
||||
"tomli>=2.4.1",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
from .archiver import pack
|
||||
from .cargo import get_artifacts
|
||||
from .cli import Cli, parse
|
||||
from .cmake import render as render_cmake
|
||||
from .pkgconfig import render as render_pkgconfig
|
||||
import logging
|
||||
from . import cli
|
||||
from .archiver import Archiver
|
||||
from .metadata import Metadata
|
||||
from .renders.cmake import CMakeProperties, CMakeRender
|
||||
|
||||
|
||||
def main() -> None:
|
||||
cli = parse()
|
||||
get_artifacts(cli.manifest_path)
|
||||
render_cmake(cli.output_dir)
|
||||
render_pkgconfig(cli.output_dir)
|
||||
pack(cli.output_dir, cli.output_dir + ".zip")
|
||||
# parse command line arguments
|
||||
opts = cli.parse()
|
||||
# setup logging
|
||||
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO)
|
||||
|
||||
# build metadata
|
||||
metadata = Metadata(opts.manifest)
|
||||
|
||||
|
||||
# create distribution
|
||||
with Archiver(opts.dist_dir, opts.dist_zip) as archiver:
|
||||
pass
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
|
||||
def get_metadata(manifest_path: str) -> dict:
|
||||
cmd = [
|
||||
"cargo",
|
||||
"metadata",
|
||||
"--format-version=1",
|
||||
f"--manifest-path={manifest_path}",
|
||||
]
|
||||
proc = subprocess.Popen(
|
||||
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
stdout, _ = proc.communicate()
|
||||
return json.loads(stdout)
|
||||
|
||||
|
||||
def get_artifacts(manifest_path: str) -> list[str]:
|
||||
metadata = get_metadata(manifest_path)
|
||||
target_directory = metadata["target_directory"]
|
||||
return [target_directory]
|
||||
@@ -0,0 +1,60 @@
|
||||
import json
|
||||
import subprocess
|
||||
from typing import Any
|
||||
from pathlib import Path
|
||||
import tomli
|
||||
|
||||
|
||||
# YYC MARK:
|
||||
# We use `tomli` with at least 2.4.0 version by design.
|
||||
# Considering that Cargo has approve the change allowing TOML 1.1 syntax in `Cargo.toml`,
|
||||
# Python embedded `toml` package, which only support TOML 1.0 syntax until Python 3.15,
|
||||
# is not suit for parsing `Cargo.toml` in future.
|
||||
# So we use the upstream of official `toml` package, i.e. `tomli` as our solution.
|
||||
# And according to the document if `tomli`, the version starting support TOML 1.1 syntax is 2.4.0.
|
||||
|
||||
_TOKEN_PACKAGES: str = "packages"
|
||||
_TOKEN_PACKAGE_MANIFEST_PATH: str = "manifest_path"
|
||||
_TOKEN_TARGET_DIRECTORY: str = "target_directory"
|
||||
|
||||
|
||||
class Metadata:
|
||||
__cargo_toml_path: Path
|
||||
__cargo_metadata: dict[str, Any]
|
||||
__cargo_toml: dict[str, Any]
|
||||
|
||||
def __init__(self, cargo_toml: Path) -> None:
|
||||
self.__cargo_toml_path = cargo_toml
|
||||
self.__cargo_toml = Metadata.__extract_cargo_toml(cargo_toml)
|
||||
self.__cargo_metadata = Metadata.__extract_cargo_metadata(cargo_toml)
|
||||
|
||||
@staticmethod
|
||||
def __extract_cargo_toml(cargo_toml: Path) -> dict[str, Any]:
|
||||
with open(cargo_toml, "rb") as f:
|
||||
return tomli.load(f)
|
||||
|
||||
@staticmethod
|
||||
def __extract_cargo_metadata(cargo_toml: Path) -> dict[str, Any]:
|
||||
cmd = [
|
||||
"cargo",
|
||||
"metadata",
|
||||
"--no-deps",
|
||||
"--format-version",
|
||||
"1",
|
||||
"--manifest-path",
|
||||
str(cargo_toml),
|
||||
]
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
try:
|
||||
stdout, stderr = proc.communicate(timeout=10)
|
||||
except subprocess.TimeoutExpired:
|
||||
proc.kill()
|
||||
proc.communicate()
|
||||
raise RuntimeError("fail to fetch cargo metadata: timed out")
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(
|
||||
"fail to fetch cargo metadata: "
|
||||
+ stderr.decode("utf-8", errors="ignore")
|
||||
)
|
||||
else:
|
||||
return json.loads(stdout)
|
||||
@@ -65,9 +65,9 @@ class CMakeProperties:
|
||||
"bad target name component in CMake. consider manually specifying it"
|
||||
)
|
||||
if self.artifact_dll == "":
|
||||
raise ValueError("bad artifact dll file name")
|
||||
raise ValueError("bad artifact dll file name in CMake")
|
||||
if self.artifact_lib == "":
|
||||
raise ValueError("bad artifact lib file name")
|
||||
raise ValueError("bad artifact lib file name in CMake")
|
||||
if self.version.prerelease is not None or self.version.build is not None:
|
||||
raise ValueError(
|
||||
"unsupported semantic version components (prerelease or build) in CMake"
|
||||
|
||||
@@ -1,21 +1,90 @@
|
||||
"""Renderer for pkg-config package files.
|
||||
|
||||
Generates the ``<pkg>.pc`` file consumed by the ``pkg-config`` tool so that the
|
||||
distributed Rust FFI library can be located and linked by downstream build
|
||||
systems. The data fed to the template is carried by
|
||||
:class:`PkgConfigProperties`, and :class:`PkgConfigRender` performs the
|
||||
rendering on top of :class:`renders.common.BaseRender`.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from . import common
|
||||
from semver import Version
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PkgConfigProperties:
|
||||
pass
|
||||
"""Inputs required to render the pkg-config ``.pc`` file.
|
||||
|
||||
A frozen dataclass validated in :meth:`__post_init__`; once constructed, an
|
||||
instance is guaranteed to hold only values that are safe to substitute into
|
||||
the ``.pc`` template.
|
||||
"""
|
||||
|
||||
name: str
|
||||
"""Human-readable name of the library or package.
|
||||
|
||||
This is purely descriptive; the ``pkg-config`` tool itself resolves
|
||||
packages by the file name of the ``.pc`` file, not by this field.
|
||||
"""
|
||||
description: str
|
||||
"""Brief description of the package."""
|
||||
|
||||
artifact: str
|
||||
"""Name of the build artifact.
|
||||
|
||||
``pkg-config`` uses this value to determine which dynamic library to link.
|
||||
For an artifact named ``XXX``, it looks for ``libXXX.so`` on Linux and
|
||||
``XXX.lib`` or ``libXXX.dll.a`` on Windows.
|
||||
"""
|
||||
|
||||
version: Version
|
||||
"""Version of the library. Must not carry a prerelease or build component."""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Validate the fields after construction.
|
||||
|
||||
:raises ValueError: if the name or description is blank, or the
|
||||
version carries a prerelease or build component (unsupported in
|
||||
pkg-config).
|
||||
"""
|
||||
if self.name == "":
|
||||
raise ValueError("unexpected blank name of pkg-config")
|
||||
if self.description == "":
|
||||
raise ValueError("unexpected blank description of pkg-config")
|
||||
if self.version.prerelease is not None or self.version.build is not None:
|
||||
raise ValueError(
|
||||
"unsupported semantic version components (prerelease or build) in pkg-config"
|
||||
)
|
||||
|
||||
|
||||
class PkgConfigRender:
|
||||
"""Renderer that turns :class:`PkgConfigProperties` into a ``.pc`` file.
|
||||
|
||||
Wraps a :class:`renders.common.BaseRender` and exposes :meth:`render` to
|
||||
emit the package configuration file.
|
||||
"""
|
||||
|
||||
__render: common.BaseRender
|
||||
__properties: PkgConfigProperties
|
||||
|
||||
def __init__(self, properties: PkgConfigProperties) -> None:
|
||||
"""Create the renderer with its Jinja2 backend and bound properties.
|
||||
|
||||
:param properties: Validated inputs reused by :meth:`render`.
|
||||
"""
|
||||
self.__render = common.BaseRender()
|
||||
self.__properties = properties
|
||||
|
||||
def render(self) -> str:
|
||||
payload: dict[str, Any] = {}
|
||||
"""Render the ``<pkg>.pc`` file.
|
||||
|
||||
:returns: The rendered ``.pc`` content as a string.
|
||||
"""
|
||||
payload: dict[str, Any] = {
|
||||
"name": self.__properties.name,
|
||||
"description": self.__properties.description,
|
||||
"artifact": self.__properties.artifact,
|
||||
}
|
||||
return self.__render.render("XXX.pc.jinja", payload)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{#
|
||||
Utilize ${pcfiledir} to fetch the directory where current .pc file is.
|
||||
And back to parent twice to obtain the installation directory.
|
||||
-#}
|
||||
prefix=${pcfiledir}/../..
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: {{ name }}
|
||||
Description: {{ description }}
|
||||
Version: {{ version }}
|
||||
Libs: -L${libdir} -l{{ artifact }}
|
||||
Cflags: -I${includedir}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from pathlib import Path
|
||||
from semver import Version
|
||||
|
||||
VERSION: Version = Version(1, 0, 0)
|
||||
"""The current version of sarasacw-omrf-packer"""
|
||||
|
||||
def get_root_dir() -> Path:
|
||||
return Path(__file__).resolve().parent
|
||||
|
||||
Generated
+38
@@ -73,12 +73,14 @@ source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "jinja2" },
|
||||
{ name = "semver" },
|
||||
{ name = "tomli" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "jinja2", specifier = "==3.1.6" },
|
||||
{ name = "semver", specifier = ">=3.0.4" },
|
||||
{ name = "tomli", specifier = ">=2.4.1" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -89,3 +91,39 @@ sdist = { url = "https://files.pythonhosted.org/packages/72/d1/d3159231aec234a59
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/24/4d91e05817e92e3a61c8a21e08fd0f390f5301f1c448b137c57c4bc6e543/semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746", size = 17912, upload-time = "2025-01-24T13:19:24.949Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user