Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implements __copy__ for widgets #2436

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions ipywidgets/widgets/widget.py
Expand Up @@ -759,3 +759,23 @@ def _gen_repr_from_keys(self, keys):
for key in keys
)
return '%s(%s)' % (class_name, signature)


def __copy__(self):

cls = self.__class__
result = cls.__new__(cls)
result.__init__()

new_state = {key: value for key, value in self.get_state().items() if
not key.startswith('_') and
not key == 'layout' and
not key == 'style'}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe the state could be directly passed to __init__ as kwargs.

Also, rather than overriding the method for each widget type that may have subwidget, a good way to exclude things may be to exclude attributes that are of type Widget?

A list of synchronized keys is available in the keys attribute.

Finally, I don't quite know if there may be other state in the object that is no synchronized with the front-end, and would need to be included in a copy operator...


for key, value in new_state.items():
setattr(result, key, value)

result.layout = self.layout
result.style = self.style

return result
23 changes: 23 additions & 0 deletions ipywidgets/widgets/widget_box.py
Expand Up @@ -68,6 +68,29 @@ def _fire_children_displayed(self):
for child in self.children:
child._handle_displayed()

def __copy__(self):
cls = self.__class__
result = cls.__new__(cls)

result.__init__(children=tuple([*self.children]))

# Deep Copy
# from copy import copy
# result.__init__(children=tuple(copy(child) for child in self.children))

new_state = {key: value for key, value in self.get_state().items() if
not key.startswith('_') and
not key == 'layout' and
not key == 'style' and
not key == 'children'}

for key, value in new_state.items():
setattr(result, key, value)

result.layout = self.layout

return result


@register
@doc_subst(_doc_snippets)
Expand Down
24 changes: 24 additions & 0 deletions ipywidgets/widgets/widget_button.py
Expand Up @@ -103,3 +103,27 @@ def _handle_button_msg(self, _, content, buffers):
"""
if content.get('event', '') == 'click':
self.click()

def __copy__(self):

cls = self.__class__
result = cls.__new__(cls)
result.__init__()

new_state = {key: value for key, value in self.get_state().items() if
not key.startswith('_') and
not key == 'layout' and
not key == 'style'}
for key, value in new_state.items():
setattr(result, key, value)

result.layout = self.layout
result.style = self.style

for callback in self._click_handlers.callbacks:
result.on_click(callback, remove=False)

return result