Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
30 changes: 17 additions & 13 deletions newton/_src/viewer/viewer_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ def _get_serialization_format(file_path: str) -> str:
return "json"
elif ext == ".bin":
if not HAS_CBOR2:
raise ImportError("cbor2 library is required for .bin files. Install with: pip install 'cbor2>=5.7.0,<6'")
raise ImportError("cbor2 library is required for .bin files. Install with: pip install 'cbor2>=5.7.0'")
return "cbor2"
else:
raise ValueError(f"Unsupported file extension '{ext}'. Supported extensions: .json, .bin")
Expand Down Expand Up @@ -614,8 +614,9 @@ def transfer_to_model(source_dict, target_obj, post_load_init_callback=None, _pa
if not hasattr(target_obj, "__dict__"):
return

# Handle case where source_dict is not a dict (primitive value)
if not isinstance(source_dict, dict):
# Handle case where source_dict is not a mapping (primitive value).
# Use Mapping to support cbor2 6.x frozendict.
if not isinstance(source_dict, Mapping):
return

# Iterate through all attributes of the target object
Expand All @@ -641,7 +642,7 @@ def transfer_to_model(source_dict, target_obj, post_load_init_callback=None, _pa
continue

# Handle different types of values
if hasattr(target_value, "__dict__") and isinstance(source_value, dict):
if hasattr(target_value, "__dict__") and isinstance(source_value, Mapping):
# Recursively transfer for custom objects
# Build path only when needed (optimization: lazy string formatting)
current_path = f"{_path}.{attr_name}" if _path else attr_name
Expand Down Expand Up @@ -693,8 +694,10 @@ def deserialize(data, callback, _path="", format_type="json", cache: ArrayCache
if result is not data:
return result

# If not a dict with __type__, return as-is
if not isinstance(data, dict) or "__type__" not in data:
# If not a mapping with __type__, return as-is.
# Use Mapping rather than dict to support cbor2 6.x, which returns frozendict
# (a Mapping but not a dict subclass) instead of plain dict.
if not isinstance(data, Mapping) or "__type__" not in data:
return data

type_name = data["__type__"]
Expand Down Expand Up @@ -909,8 +912,9 @@ def depointer_as_key(data: dict, format_type: str = "json", cache: ArrayCache |
"""

def callback(x, path):
# Optimization: extract type once to avoid repeated isinstance and dict lookups
x_type = x.get("__type__") if isinstance(x, dict) else None
# Optimization: extract type once to avoid repeated isinstance and dict lookups.
# Use Mapping to support cbor2 6.x frozendict (not a dict subclass).
x_type = x.get("__type__") if isinstance(x, Mapping) else None

if x_type == "warp.array_ref":
if cache is None:
Expand Down Expand Up @@ -997,19 +1001,19 @@ def callback(x, path):
result = deserialize(data, callback, format_type=format_type, cache=cache)

def _resolve_cache_refs(obj):
if isinstance(obj, dict):
# Use Mapping to support cbor2 6.x frozendict (not a dict subclass).
if isinstance(obj, Mapping):
# Optimization: single dict lookup instead of checking membership then accessing
cache_ref = obj.get("__cache_ref__")
if cache_ref is not None:
idx = int(cache_ref["index"])
# Will raise KeyError with clear message if still missing
return cache.try_get_value(idx) if cache is not None else obj
# Recurse into dict
# Recurse into mapping; always return a plain dict
return {k: _resolve_cache_refs(v) for k, v in obj.items()}
if isinstance(obj, list):
# cbor2 6.x returns tuple instead of list for arrays; handle both
if isinstance(obj, (list, tuple)):
return [_resolve_cache_refs(v) for v in obj]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
if isinstance(obj, tuple):
return tuple(_resolve_cache_refs(v) for v in obj)
if isinstance(obj, set):
return {_resolve_cache_refs(v) for v in obj}
return obj
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ examples = [
"GitPython>=3.1.44", # for downloading assets via newton.utils.download_asset()
"imgui_bundle>=1.92.0", # for viewer GUI
"pyyaml>=6.0.2",
"cbor2>=5.7.0, <6", # for binary recording format (.bin files) - more efficient than JSON
"cbor2>=5.7.0", # for binary recording format (.bin files) - more efficient than JSON
"Pillow>=9.0.0", # for image processing (viewer icons, heightfield loading, textures)
]

Expand Down
Loading