Skip to content

Commit 0680330

Browse files
committed
Change media widgets to use memory views.
This can be more efficient with fewer copies in some cases, such as uploading a file and setting the value from the file content.
1 parent 5042b8c commit 0680330

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

ipywidgets/widgets/trait_types.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,32 @@ def date_from_json(js, manager):
146146
'to_json': date_to_json
147147
}
148148

149+
class ByteMemoryView(traitlets.TraitType):
150+
"""A trait for memory views of bytes."""
151+
152+
default_value = memoryview(b'')
153+
info_text = 'a memory view object'
154+
155+
def validate(self, obj, value):
156+
if isinstance(value, memoryview) and value.format == 'B':
157+
return value
158+
self.error(obj, value)
159+
160+
161+
class CByteMemoryView(ByteMemoryView):
162+
"""A casting version of the byte memory view trait."""
163+
164+
def validate(self, obj, value):
165+
if isinstance(value, memoryview) and value.format == 'B':
166+
return value
167+
168+
try:
169+
mv = memoryview(value)
170+
if mv.format != 'B':
171+
mv = mv.cast('B')
172+
return mv
173+
except Exception:
174+
self.error(obj, value)
149175

150176
class InstanceDict(traitlets.Instance):
151177
"""An instance trait which coerces a dict to an instance.

ipywidgets/widgets/widget_media.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
from .domwidget import DOMWidget
88
from .valuewidget import ValueWidget
99
from .widget import register
10-
from traitlets import Unicode, CUnicode, Bytes, Bool
11-
from .trait_types import bytes_serialization
10+
from traitlets import Unicode, CUnicode, Bool
11+
from .trait_types import CByteMemoryView
1212

1313

1414
@register
@@ -23,7 +23,7 @@ class _Media(DOMWidget, ValueWidget, CoreWidget):
2323
"""
2424

2525
# Define the custom state properties to sync with the front-end
26-
value = Bytes(help="The media data as a byte string.").tag(sync=True, **bytes_serialization)
26+
value = CByteMemoryView(help="The media data as a memory view of bytes.").tag(sync=True)
2727

2828
@classmethod
2929
def _from_file(cls, tag, filename, **kwargs):
@@ -116,12 +116,13 @@ def _get_repr(self, cls):
116116

117117
# Return value first like a ValueWidget
118118
signature = []
119-
sig_value = repr(self.value)
120-
prefix, rest = sig_value.split("'", 1)
121-
content = rest[:-1]
122-
if len(content) > 100:
123-
sig_value = "{}'{}...'".format(prefix, content[0:100])
124-
signature.append('{}={}'.format('value', sig_value))
119+
120+
# strip off the starting b' and ending ' so we can truncate if needed
121+
sig_value = repr(self.value[:100].tobytes())[2:-1]
122+
123+
if self.value.nbytes > 100:
124+
sig_value += '...'
125+
signature.append("{}=b'{}'".format('value', sig_value))
125126

126127
for key in super(cls, self)._repr_keys():
127128
if key == 'value':

0 commit comments

Comments
 (0)