Skip to content

Instantly share code, notes, and snippets.

@hdary85
Last active January 23, 2024 01:45
Show Gist options
  • Save hdary85/716d99fd172e410482957a3026655607 to your computer and use it in GitHub Desktop.
Save hdary85/716d99fd172e410482957a3026655607 to your computer and use it in GitHub Desktop.
import ipywidgets as widgets
from IPython.display import display
class NestedDictManagerJupyter:
def __init__(self, original_data):
self.original_data = original_data
self.data = original_data.copy()
self.accordion = widgets.Accordion(selected_index=None)
self.accordion.observe(self.update_selected_item, names='selected_index')
self.tree = widgets.TreeView(show_only_select_widget=True)
self.tree.observe(self.update_selected_item, names='selected_labels')
self.text_output = widgets.Output()
self.update_btn = widgets.Button(description="Update")
self.update_btn.on_click(self.update_key)
self.delete_btn = widgets.Button(description="Delete")
self.delete_btn.on_click(self.delete_key)
self.rename_btn = widgets.Button(description="Rename")
self.rename_btn.on_click(self.rename_key)
self.add_btn = widgets.Button(description="Add Key")
self.add_btn.on_click(self.add_key)
self.display()
def display_dict(self, dictionary, parent=None, label=''):
if parent is None:
parent = self.tree
for key, value in dictionary.items():
if isinstance(value, dict):
node = widgets.TreeNode(icon='folder-open', open_icon='folder', label=str(key))
parent.children += [node]
self.display_dict(value, parent=node, label=str(key))
else:
leaf = widgets.LeafNode(icon='file', label=f"{key}: {value}")
parent.children += [leaf]
def update_selected_item(self, change):
if change['owner'] == self.accordion:
selected_index = change['new']
if selected_index is not None:
selected_label = self.accordion.children[selected_index].value
self.selected_item_path = selected_label
else:
self.selected_item_path = None
elif change['owner'] == self.tree:
selected_labels = change['new']
if selected_labels:
selected_label = selected_labels[0]
self.selected_item_path = selected_label
else:
self.selected_item_path = None
def update_key(self, _):
if not hasattr(self, "selected_item_path") or not self.selected_item_path:
print("Please select a key to update.")
return
key = self.selected_item_path.split(":")[0].strip()
new_value = input(f"Enter new value for '{key}': ")
if new_value is not None:
self.update_original_dict(key, new_value)
self.refresh_display()
def delete_key(self, _):
if not hasattr(self, "selected_item_path") or not self.selected_item_path:
print("Please select a key to delete.")
return
key = self.selected_item_path.split(":")[0].strip()
confirm = input(f"Are you sure you want to delete the key '{key}'? (yes/no): ").lower()
if confirm == 'yes':
self.delete_from_original_dict(key)
self.refresh_display()
def rename_key(self, _):
if not hasattr(self, "selected_item_path") or not self.selected_item_path:
print("Please select a key to rename.")
return
old_key = self.selected_item_path.split(":")[0].strip()
new_key = input(f"Enter new key name for '{old_key}': ")
if new_key is not None:
self.rename_in_original_dict(old_key, new_key)
self.refresh_display()
def add_key(self, _):
parent_path, new_key = input("Enter parent key path (e.g., key1/key2) and new key name: ").split()
parent_dict = self.get_dict_by_path(parent_path)
parent_dict[new_key] = "New Value"
self.refresh_display()
def refresh_display(self):
self.accordion.children = []
self.display_dict(self.original_data)
def update_original_dict(self, key, new_value):
nested_keys = key.split('/')
current_dict = self.original_data
for nested_key in nested_keys[:-1]:
current_dict = current_dict[nested_key]
current_dict[nested_keys[-1]] = new_value
def delete_from_original_dict(self, key):
nested_keys = key.split('/')
current_dict = self.original_data
for nested_key in nested_keys[:-1]:
current_dict = current_dict[nested_key]
del current_dict[nested_keys[-1]]
def rename_in_original_dict(self, old_key, new_key):
nested_keys = old_key.split('/')
current_dict = self.original_data
for nested_key in nested_keys[:-1]:
current_dict = current_dict[nested_key]
current_dict[new_key] = current_dict.pop(nested_keys[-1])
def get_dict_by_path(self, path):
keys = path.split('/')
current_dict = self.original_data
for key in keys:
current_dict = current_dict[key]
return current_dict
def display(self):
with self.text_output:
display(self.tree)
self.accordion.children = [widgets.VBox([self.text_output])]
display(self.accordion)
display(widgets.HBox([self.update_btn, self.delete_btn, self.rename_btn, self.add_btn]))
# Example of an existing dictionary
original_dictionary = {
'key1': 'value1',
'key2': {
'key3': 'value3',
'key4': 'value4'
},
'key5': {
'key6': {
'key7': 'value7'
}
}
}
app_jupyter = NestedDictManagerJupyter(original_dictionary)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment