Source code for xnatctl.models.resource
"""Resource model for XNAT resources (file collections)."""
from __future__ import annotations
from pydantic import Field
from .base import BaseModel, XNATResource
class ResourceFile(BaseModel):
"""Individual file within a resource."""
name: str = Field(..., alias="Name", description="File name")
size: int | None = Field(None, alias="Size", description="File size in bytes")
uri: str | None = Field(None, alias="URI", description="Download URI")
digest: str | None = Field(None, description="File checksum/digest")
content_type: str | None = Field(None, alias="content_type", description="MIME type")
collection: str | None = Field(None, alias="collection", description="Parent resource label")
@property
def size_mb(self) -> float:
"""Return file size in megabytes."""
if self.size:
return self.size / (1024 * 1024)
return 0.0
[docs]
class Resource(XNATResource):
"""XNAT resource (file collection)."""
format: str | None = Field(None, description="Resource format")
content: str | None = Field(None, description="Content type/description")
file_count: int | None = Field(None, alias="file_count", description="Number of files")
file_size: int | None = Field(None, alias="file_size", description="Total size in bytes")
category: str | None = Field(None, description="Resource category")
cacheable: bool | None = Field(None, description="Whether resource is cacheable")
# Parent references
session_id: str | None = Field(None, description="Parent session ID")
scan_id: str | None = Field(None, description="Parent scan ID (if scan-level)")
project: str | None = Field(None, description="Parent project ID")
[docs]
@classmethod
def table_columns(cls) -> list[str]:
"""Return columns for table output."""
return ["label", "format", "file_count", "file_size_display", "content"]
[docs]
def to_row(self, columns: list[str] | None = None) -> dict[str, str]:
"""Convert to row for table output."""
cols = columns or self.table_columns()
data = self.to_dict()
data["file_size_display"] = self.file_size_display
return {col: str(data.get(col, "")) for col in cols}
@property
def file_size_mb(self) -> float:
"""Return file size in megabytes."""
if self.file_size:
return self.file_size / (1024 * 1024)
return 0.0
@property
def file_size_display(self) -> str:
"""Return human-readable file size."""
if not self.file_size:
return ""
size = float(self.file_size)
for unit in ["B", "KB", "MB", "GB", "TB"]:
if size < 1024:
return f"{size:.1f} {unit}"
size /= 1024
return f"{size:.1f} PB"