Skip to content
Merged
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
21 changes: 18 additions & 3 deletions src/datajoint/preview.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ def _format_object_display(json_data):
return "=OBJ[file]="


def _get_blob_placeholder(heading, field_name, html_escape=False):
"""Get display placeholder for a blob/json field based on its codec."""
attr = heading.attributes.get(field_name)
if attr is None:
return "bytes"
Comment on lines +30 to +31
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we expect attr to be None? Can it ever be None? If it can, perhaps this should raise an error instead of returning bytes

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch! You're right - attr should never be None here since field_name always comes from heading.names. The defensive check was silently hiding potential bugs.

I've updated the code in PR #1331 (which now includes this PR) to raise an error instead:

if attr is None:
    raise DataJointError(f"Field '{field_name}' not found in heading")

This way any unexpected state will surface immediately rather than returning a misleading "bytes" placeholder.

if attr.codec is not None:
name = attr.codec.name
if html_escape:
return f"<{name}>"
return f"<{name}>"
if attr.json:
return "json"
return "bytes"


def preview(query_expression, limit, width):
heading = query_expression.heading
rel = query_expression.proj(*heading.non_blobs)
Expand Down Expand Up @@ -55,7 +70,7 @@ def preview(query_expression, limit, width):
def get_placeholder(f):
if f in object_fields:
return "=OBJ[.xxx]="
return "=BLOB="
return _get_blob_placeholder(heading, f)

widths = {
f: min(
Expand All @@ -72,7 +87,7 @@ def get_display_value(tup, f, idx):
elif f in object_fields and idx < len(object_data_list):
return _format_object_display(object_data_list[idx].get(f))
else:
return "=BLOB="
return _get_blob_placeholder(heading, f)

return (
" ".join([templates[f] % ("*" + f if f in rel.primary_key else f) for f in columns])
Expand Down Expand Up @@ -113,7 +128,7 @@ def get_html_display_value(tup, name, idx):
elif name in object_fields and idx < len(object_data_list):
return _format_object_display(object_data_list[idx].get(name))
else:
return "=BLOB="
return _get_blob_placeholder(heading, name, html_escape=True)

css = """
<style type="text/css">
Expand Down
Loading