105 lines
5.3 KiB
Python
105 lines
5.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Audit issue 66's appearance baking and initial-outfit boundary."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
import re
|
|
|
|
import generate_api_shims
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
APPEARANCE = ROOT / "crates" / "libremetaverse" / "src" / "appearance_manager.rs"
|
|
BAKER = ROOT / "crates" / "libremetaverse" / "src" / "appearance_baker.rs"
|
|
PROVIDER = ROOT / "crates" / "libremetaverse" / "src" / "baking_texture_provider.rs"
|
|
OUTFIT = ROOT / "crates" / "libremetaverse" / "src" / "initial_outfit.rs"
|
|
ASSETS = ROOT / "crates" / "libremetaverse" / "src" / "asset_models.rs"
|
|
BAKER_TESTS = ROOT / "crates" / "libremetaverse" / "src" / "appearance_baker_semantics.rs"
|
|
VISUAL_TESTS = ROOT / "crates" / "libremetaverse" / "tests" / "generated_catalogs.rs"
|
|
COMPAT = ROOT / "tests" / "compat" / "tests" / "appearance_semantics.rs"
|
|
DOC = ROOT / "docs" / "appearance.md"
|
|
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
|
|
|
|
REQUIRED_TYPES = {
|
|
"T:LibreMetaverse.AppearanceManager",
|
|
"T:LibreMetaverse.Appearance.InitialOutfit",
|
|
"T:LibreMetaverse.Appearance.InitialOutfit.InitialOutfitProgress",
|
|
"T:LibreMetaverse.Appearance.InitialOutfitHandler",
|
|
"T:LibreMetaverse.GridClientBakingTextureProvider",
|
|
"T:LibreMetaverse.Imaging.Baker",
|
|
}
|
|
|
|
REQUIRED_MEMBERS = {
|
|
"M:LibreMetaverse.AppearanceManager.DecodeWearableParams(LibreMetaverse.AppearanceManager.WearableData,LibreMetaverse.AppearanceManager.TextureData[]@)",
|
|
"M:LibreMetaverse.AppearanceManager.MakeAppearancePacket",
|
|
"M:LibreMetaverse.AppearanceManager.RequestCachedBakes",
|
|
"M:LibreMetaverse.AppearanceManager.RequestSetAppearance(System.Boolean)",
|
|
"M:LibreMetaverse.AppearanceManager.ServerBakingRegion",
|
|
"M:LibreMetaverse.GridClientBakingTextureProvider.RequestTextureAsync(LibreMetaverse.UUID,System.Threading.CancellationToken)",
|
|
"M:LibreMetaverse.Imaging.Baker.Bake",
|
|
"M:LibreMetaverse.Imaging.Baker.LoadResourceLayer(System.String)",
|
|
"M:LibreMetaverse.Appearance.InitialOutfit.CopyFolderAsync(LibreMetaverse.InventoryFolder,LibreMetaverse.UUID,System.Threading.CancellationToken,System.IProgress{LibreMetaverse.Appearance.InitialOutfit.InitialOutfitProgress})",
|
|
"M:LibreMetaverse.Appearance.InitialOutfit.SetInitialOutfitAsync(System.String,System.Threading.CancellationToken,System.IProgress{LibreMetaverse.Appearance.InitialOutfit.InitialOutfitProgress})",
|
|
}
|
|
|
|
|
|
def require_markers(path: Path, markers: tuple[str, ...]) -> None:
|
|
text = path.read_text()
|
|
missing = [marker for marker in markers if marker not in text]
|
|
if missing:
|
|
raise SystemExit(f"{path.name}: audit evidence missing: " + ", ".join(missing))
|
|
|
|
|
|
def main() -> None:
|
|
native = set(generate_api_shims.NATIVE_TYPES) | set(generate_api_shims.NATIVE_DECLARATIONS)
|
|
missing_types = sorted(REQUIRED_TYPES - native)
|
|
if missing_types:
|
|
raise SystemExit("issue 66 native types missing: " + ", ".join(missing_types))
|
|
missing_members = sorted(REQUIRED_MEMBERS - set(generate_api_shims.NATIVE_MEMBER_BODIES))
|
|
if missing_members:
|
|
raise SystemExit("issue 66 native members missing: " + ", ".join(missing_members))
|
|
for source in (APPEARANCE, BAKER, PROVIDER, OUTFIT, ASSETS):
|
|
if STUB_RE.search(source.read_text()):
|
|
raise SystemExit(f"issue 66 owned Rust stubs remain in {source.name}")
|
|
|
|
require_markers(APPEARANCE, (
|
|
"baked_texture_hash", "wearable_bake_map", "AgentCachedTextureResponse",
|
|
"AgentWearablesRequest", "AgentWearablesUpdate", "MAX_COF_ENTRIES",
|
|
"RebakeAvatarTextures", "tokio::sync::Semaphore::new(5)",
|
|
"tokio::sync::Semaphore::new(6)", "native_server_bake",
|
|
"old_visual_parameters", "appearance_packet_contains_all_bakes",
|
|
"legacy_wearables_packet_preserves_valid_item_asset_and_type_fields",
|
|
))
|
|
require_markers(BAKER, (
|
|
"CLASSIC_BAKE_SIZE", "EYE_BAKE_SIZE", "self.textures.len() >= 60", "head_color.tga",
|
|
"head_skingrain.tga", "apply_parameter_mask", "output.bump",
|
|
"native_deep_clone", '#[cfg(feature = "jpeg2000")]',
|
|
))
|
|
require_markers(PROVIDER, ("ClientWeakHandle", "request_image", "native_decode_image"))
|
|
require_markers(OUTFIT, (
|
|
"MAX_FOLDERS", "Phase::Counting", "Phase::Copying", "Phase::Applying",
|
|
"cleanup_folder", "compare_exchange", "native_replace_outfit",
|
|
"handler_dispose_is_idempotent",
|
|
))
|
|
require_markers(ASSETS, (
|
|
"native_from_asset", "parameters ", "textures ",
|
|
"wearable_parser_preserves_parameters_and_texture_indices",
|
|
))
|
|
require_markers(BAKER_TESTS, ("parity-case", "image.red[0]", "image.bump[0]"))
|
|
require_markers(VISUAL_TESTS, ("visual_catalog_matches_the_pinned_character_fixture", "672", "253"))
|
|
require_markers(COMPAT, ("baked_texture_hash", "wearable_bake_map", "texture_provider"))
|
|
require_markers(DOC, (
|
|
"all 11", "downloads and six baked-texture uploads",
|
|
"Counting`, `Copying`, `Applying`, then `Complete", "256-node",
|
|
"big-endian", "218 normal or 251", "UpdateAvatarAppearance",
|
|
))
|
|
print(
|
|
"issue 66 audit: native bake composition, bounded texture transport, cache/server/local "
|
|
"appearance paths, transactional initial outfit, documentation, and focused evidence are present"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|