61 lines
2.0 KiB
Python
61 lines
2.0 KiB
Python
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)
|