From abdaf80898c1cc8b147fa41ca9544dc71ba808b7 Mon Sep 17 00:00:00 2001 From: Masa Kato Date: Mon, 18 May 2026 21:13:21 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9B=20fix(assets):=20extract=20Arc?= =?UTF-8?q?hitecture-Group-Icons=20from=20AWS=20icon=20ZIP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The download_aws_icons.py ZIP filter only extracted 48px SVGs, missing the Architecture-Group-Icons directory which uses 32px. As a result, icons referenced by ARCH_GROUP_DEFS (AWS-Cloud-logo, Region, VPC, public/private-subnet, Auto-Scaling-group, Account, etc.) were absent from assets/aws/ on a fresh install, causing arch-group elements to fail with `Asset not found: AWS-Cloud-logo_32`. - Extract _should_extract() helper that allows 32px in Architecture-Group-Icons paths and 48px elsewhere - Add unit tests for _should_extract and _classify_type covering service / resource / category / group classifications --- skill/scripts/download_aws_icons.py | 18 +++++++-- tests/test_download_aws_icons.py | 63 +++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 tests/test_download_aws_icons.py diff --git a/skill/scripts/download_aws_icons.py b/skill/scripts/download_aws_icons.py index b40758ed..f58e9818 100644 --- a/skill/scripts/download_aws_icons.py +++ b/skill/scripts/download_aws_icons.py @@ -94,6 +94,19 @@ def _classify_type(filename: str, zip_path: str) -> str: return "general" +def _should_extract(zip_path: str) -> bool: + """Decide whether a SVG entry in the icon ZIP should be extracted. + + Service / Resource / Category icons use the 48px size; Architecture + Group icons (e.g. AWS-Cloud-logo, Region, VPC) use 32px. + """ + if not zip_path.endswith(".svg"): + return False + if "Architecture-Group-Icons" in zip_path: + return "_32" in zip_path + return "_48" in zip_path + + def _name_from_filename(filename: str) -> str: """Extract human-readable name from icon filename. @@ -159,10 +172,7 @@ def main() -> None: for info in zf.infolist(): if info.is_dir(): continue - # Only extract 48px SVGs (standard size) - if not info.filename.endswith(".svg"): - continue - if "_48" not in info.filename: + if not _should_extract(info.filename): continue filename = Path(info.filename).name diff --git a/tests/test_download_aws_icons.py b/tests/test_download_aws_icons.py new file mode 100644 index 00000000..27eb783d --- /dev/null +++ b/tests/test_download_aws_icons.py @@ -0,0 +1,63 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +"""Tests for scripts.download_aws_icons — ZIP filtering and classification.""" + +from scripts.download_aws_icons import _classify_type, _should_extract + + +class TestShouldExtract: + def test_service_48_extracted(self): + assert _should_extract("Architecture-Service-Icons_01302026/Arch_Compute/48/Arch_AWS-Lambda_48.svg") + + def test_resource_48_extracted(self): + assert _should_extract("Resource-Icons_01302026/Res_Compute/Res_AWS-Lambda_48_Light.svg") + + def test_category_48_extracted(self): + assert _should_extract("Architecture-Category-Icons_01302026/Arch-Category_Compute_48.svg") + + def test_group_32_extracted(self): + assert _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32.svg") + + def test_group_32_dark_variant_extracted(self): + assert _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32_Dark.svg") + + def test_group_48_not_extracted(self): + # Group icons live at 32px only; reject any stray 48 in the group dir. + assert not _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_48.svg") + + def test_service_32_not_extracted(self): + # Service icons live at 48px in this script; reject 32 in non-group dirs. + assert not _should_extract("Architecture-Service-Icons_01302026/Arch_Compute/32/Arch_AWS-Lambda_32.svg") + + def test_non_svg_not_extracted(self): + assert not _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32.png") + + +class TestClassifyType: + def test_group_path_classified_as_group(self): + result = _classify_type( + "AWS-Cloud-logo_32.svg", + "Architecture-Group-Icons_01302026/AWS-Cloud-logo_32.svg", + ) + assert result == "group" + + def test_service_classified_as_service(self): + result = _classify_type( + "Arch_AWS-Lambda_48.svg", + "Architecture-Service-Icons_01302026/Arch_Compute/48/Arch_AWS-Lambda_48.svg", + ) + assert result == "service" + + def test_resource_classified_as_resource(self): + result = _classify_type( + "Res_AWS-Lambda_48_Light.svg", + "Resource-Icons_01302026/Res_Compute/Res_AWS-Lambda_48_Light.svg", + ) + assert result == "resource" + + def test_category_classified_as_category(self): + result = _classify_type( + "Arch-Category_Compute_48.svg", + "Architecture-Category-Icons_01302026/Arch-Category_Compute_48.svg", + ) + assert result == "category" From 8d43a5b87668165b9581dfc5e6ebfbfa9e32abdd Mon Sep 17 00:00:00 2001 From: Masa Kato Date: Mon, 18 May 2026 21:39:37 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(download=5Faw?= =?UTF-8?q?s=5Ficons):=20rename=20=5Fshould=5Fextract=20to=20=5Fis=5Ftarge?= =?UTF-8?q?t=5Fentry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The neighboring helpers in this module (`_classify_type`, `_extract_category`, `_name_from_filename`, `_generate_tags`) all use a verb+object form. A boolean predicate fits better as `is_*` per PEP 8, and `_is_target_entry` reads naturally next to `_classify_type` since both classify a ZIP entry. Also reword the docstring as a predicate. --- skill/scripts/download_aws_icons.py | 6 +++--- tests/test_download_aws_icons.py | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/skill/scripts/download_aws_icons.py b/skill/scripts/download_aws_icons.py index f58e9818..2170d388 100644 --- a/skill/scripts/download_aws_icons.py +++ b/skill/scripts/download_aws_icons.py @@ -94,8 +94,8 @@ def _classify_type(filename: str, zip_path: str) -> str: return "general" -def _should_extract(zip_path: str) -> bool: - """Decide whether a SVG entry in the icon ZIP should be extracted. +def _is_target_entry(zip_path: str) -> bool: + """Return True if a ZIP entry is an icon variant we want to extract. Service / Resource / Category icons use the 48px size; Architecture Group icons (e.g. AWS-Cloud-logo, Region, VPC) use 32px. @@ -172,7 +172,7 @@ def main() -> None: for info in zf.infolist(): if info.is_dir(): continue - if not _should_extract(info.filename): + if not _is_target_entry(info.filename): continue filename = Path(info.filename).name diff --git a/tests/test_download_aws_icons.py b/tests/test_download_aws_icons.py index 27eb783d..970cda46 100644 --- a/tests/test_download_aws_icons.py +++ b/tests/test_download_aws_icons.py @@ -2,35 +2,35 @@ # SPDX-License-Identifier: MIT-0 """Tests for scripts.download_aws_icons — ZIP filtering and classification.""" -from scripts.download_aws_icons import _classify_type, _should_extract +from scripts.download_aws_icons import _classify_type, _is_target_entry -class TestShouldExtract: +class TestIsTargetEntry: def test_service_48_extracted(self): - assert _should_extract("Architecture-Service-Icons_01302026/Arch_Compute/48/Arch_AWS-Lambda_48.svg") + assert _is_target_entry("Architecture-Service-Icons_01302026/Arch_Compute/48/Arch_AWS-Lambda_48.svg") def test_resource_48_extracted(self): - assert _should_extract("Resource-Icons_01302026/Res_Compute/Res_AWS-Lambda_48_Light.svg") + assert _is_target_entry("Resource-Icons_01302026/Res_Compute/Res_AWS-Lambda_48_Light.svg") def test_category_48_extracted(self): - assert _should_extract("Architecture-Category-Icons_01302026/Arch-Category_Compute_48.svg") + assert _is_target_entry("Architecture-Category-Icons_01302026/Arch-Category_Compute_48.svg") def test_group_32_extracted(self): - assert _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32.svg") + assert _is_target_entry("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32.svg") def test_group_32_dark_variant_extracted(self): - assert _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32_Dark.svg") + assert _is_target_entry("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32_Dark.svg") def test_group_48_not_extracted(self): # Group icons live at 32px only; reject any stray 48 in the group dir. - assert not _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_48.svg") + assert not _is_target_entry("Architecture-Group-Icons_01302026/AWS-Cloud-logo_48.svg") def test_service_32_not_extracted(self): # Service icons live at 48px in this script; reject 32 in non-group dirs. - assert not _should_extract("Architecture-Service-Icons_01302026/Arch_Compute/32/Arch_AWS-Lambda_32.svg") + assert not _is_target_entry("Architecture-Service-Icons_01302026/Arch_Compute/32/Arch_AWS-Lambda_32.svg") def test_non_svg_not_extracted(self): - assert not _should_extract("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32.png") + assert not _is_target_entry("Architecture-Group-Icons_01302026/AWS-Cloud-logo_32.png") class TestClassifyType: