Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/launchpad/artifacts/apple/zipped_xcarchive.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class AssetCatalogElement:
idiom: str | None = None
colorspace: str | None = None
content_hash: str | None = None
scale: int | None = None


@dataclass
Expand Down Expand Up @@ -479,6 +480,7 @@ def _parse_asset_element(self, item: dict[str, Any], parent_path: Path) -> Asset
idiom = item.get("idiom")
colorspace = item.get("colorspace")
content_hash = item.get("contentHash")
scale = item.get("scale")

file_extension = Path(filename).suffix.lower()
if filename and file_extension in {".png", ".jpg", ".jpeg", ".heic", ".heif", ".pdf", ".svg"}:
Expand All @@ -501,6 +503,7 @@ def _parse_asset_element(self, item: dict[str, Any], parent_path: Path) -> Asset
idiom=idiom,
colorspace=colorspace,
content_hash=content_hash,
scale=scale,
)

def _parse_and_cache_all_binaries(self, binary_paths: List[Path]) -> None:
Expand Down
3 changes: 2 additions & 1 deletion src/launchpad/size/models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class FileInfo(BaseModel):
# Asset catalog specific fields
idiom: str | None = Field(default=None, exclude=True, description="Device idiom for asset catalog images")
colorspace: str | None = Field(default=None, exclude=True, description="Color space for asset catalog images")
scale: int | None = Field(default=None, exclude=True, description="Scale factor for asset catalog images")


class ComponentType(IntEnum):
Expand Down Expand Up @@ -153,6 +154,6 @@ class BaseAnalysisResults(BaseModel):

def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary with serializable datetime."""
data = self.model_dump()
data = self.model_dump(exclude_none=True)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rbro112 this is the fix to not have path: null or misc: null included in the treemap data when passed to the frontend

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, I think we might need support in the backend/frontend to ensure we parse these all properly, can you just do an E2E test to make sure downstream size processing related code either responds gracefully to missing fields or uncover any potential errors?

data["generated_at"] = self.generated_at.isoformat()
return data
9 changes: 9 additions & 0 deletions src/launchpad/size/models/treemap.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ class TreemapType(str, Enum):
UNMAPPED = "unmapped"


class TreemapElementMisc(BaseModel):
"""Miscellaneous metadata for treemap elements."""

model_config = ConfigDict(frozen=True)

scale: int | None = Field(None, description="Scale factor for asset catalog images (1, 2, 3)")


# Mapping from file types to TreemapType
FILE_TYPE_TO_TREEMAP_TYPE: dict[str, TreemapType] = {
# Binary types
Expand Down Expand Up @@ -120,6 +128,7 @@ class TreemapElement(BaseModel):
is_dir: bool = Field(False, description="Whether this element represents a directory")
""" Some files (like zip files) are not directories but have children. """
children: List[TreemapElement] = Field(default_factory=list, description="Child elements")
misc: TreemapElementMisc | None = Field(None, description="Optional miscellaneous data for this element")


class TreemapResults(BaseModel):
Expand Down
8 changes: 7 additions & 1 deletion src/launchpad/size/treemap/default_file_element_builder.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import os

from launchpad.size.models.common import FileInfo
from launchpad.size.models.treemap import TreemapElement
from launchpad.size.models.treemap import TreemapElement, TreemapElementMisc
from launchpad.size.treemap.treemap_element_builder import TreemapElementBuilder
from launchpad.utils.file_utils import to_nearest_block_size


class DefaultFileElementBuilder(TreemapElementBuilder):
def build_element(self, file_info: FileInfo, display_name: str) -> TreemapElement:
size = to_nearest_block_size(file_info.size, self.filesystem_block_size)

misc = None
if file_info.scale is not None:
misc = TreemapElementMisc(scale=file_info.scale)

return TreemapElement(
name=display_name,
size=size,
type=file_info.treemap_type,
path=file_info.path,
is_dir=False,
children=[self.build_element(child, os.path.basename(child.path)) for child in file_info.children],
misc=misc,
)
1 change: 1 addition & 0 deletions src/launchpad/size/utils/file_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ def _analyze_asset_catalog(xcarchive: ZippedXCArchive, relative_path: Path) -> L
children=[],
idiom=element.idiom,
colorspace=element.colorspace,
scale=element.scale,
)
)
return result
Expand Down
7 changes: 7 additions & 0 deletions web/src/types/treemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ export enum TreemapType {
UNMAPPED = "unmapped",
}

export interface TreemapElementMisc {
/** Scale factor for asset catalog images (1, 2, 3) */
scale?: number;
}

export interface TreemapElement {
/** Display name of the element */
name: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might need to separate out these FE changes first as the deploys could get out of sync, especially if we need to make more fields optional

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in this case we're OK since the only stuff we're adding is optional on both ends, so even if one of them deploys before the other, it shouldn't matter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(oh and fwiw this is in launchpad, but i know what you mean)

Expand All @@ -53,6 +58,8 @@ export interface TreemapElement {
path?: string;
/** Whether this element represents a directory */
is_dir: boolean;
/** Optional miscellaneous data for this element */
misc?: TreemapElementMisc;
/** Child elements */
children: TreemapElement[];
}
Expand Down
Loading