-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2414 from plotly/patch-update
Add Patch callbacks
- Loading branch information
Showing
14 changed files
with
1,073 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
def _operation(name, location, **kwargs): | ||
return {"operation": name, "location": location, "params": dict(**kwargs)} | ||
|
||
|
||
_noop = object() | ||
|
||
|
||
def validate_slice(obj): | ||
if isinstance(obj, slice): | ||
raise TypeError("a slice is not a valid index for patch") | ||
|
||
|
||
class Patch: | ||
""" | ||
Patch a callback output value | ||
Act like a proxy of the output prop value on the frontend. | ||
Supported prop types: Dictionaries and lists. | ||
""" | ||
|
||
def __init__(self, location=None, parent=None): | ||
if location is not None: | ||
self._location = location | ||
else: | ||
# pylint: disable=consider-using-ternary | ||
self._location = (parent and parent._location) or [] | ||
if parent is not None: | ||
self._operations = parent._operations | ||
else: | ||
self._operations = [] | ||
|
||
def __getitem__(self, item): | ||
validate_slice(item) | ||
return Patch(location=self._location + [item], parent=self) | ||
|
||
def __getattr__(self, item): | ||
if item == "tolist": | ||
# to_json fix | ||
raise AttributeError | ||
if item == "_location": | ||
return self._location | ||
if item == "_operations": | ||
return self._operations | ||
return self.__getitem__(item) | ||
|
||
def __setattr__(self, key, value): | ||
if key in ("_location", "_operations"): | ||
self.__dict__[key] = value | ||
else: | ||
self.__setitem__(key, value) | ||
|
||
def __delattr__(self, item): | ||
self.__delitem__(item) | ||
|
||
def __setitem__(self, key, value): | ||
validate_slice(key) | ||
if value is _noop: | ||
# The += set themselves. | ||
return | ||
self._operations.append( | ||
_operation( | ||
"Assign", | ||
self._location + [key], | ||
value=value, | ||
) | ||
) | ||
|
||
def __delitem__(self, key): | ||
validate_slice(key) | ||
self._operations.append(_operation("Delete", self._location + [key])) | ||
|
||
def __iadd__(self, other): | ||
if isinstance(other, (list, tuple)): | ||
self.extend(other) | ||
else: | ||
self._operations.append(_operation("Add", self._location, value=other)) | ||
return _noop | ||
|
||
def __isub__(self, other): | ||
self._operations.append(_operation("Sub", self._location, value=other)) | ||
return _noop | ||
|
||
def __imul__(self, other): | ||
self._operations.append(_operation("Mul", self._location, value=other)) | ||
return _noop | ||
|
||
def __itruediv__(self, other): | ||
self._operations.append(_operation("Div", self._location, value=other)) | ||
return _noop | ||
|
||
def __ior__(self, other): | ||
self.update(E=other) | ||
return _noop | ||
|
||
def append(self, item): | ||
"""Add the item to the end of a list""" | ||
self._operations.append(_operation("Append", self._location, value=item)) | ||
|
||
def prepend(self, item): | ||
"""Add the item to the start of a list""" | ||
self._operations.append(_operation("Prepend", self._location, value=item)) | ||
|
||
def insert(self, index, item): | ||
"""Add the item at the index of a list""" | ||
self._operations.append( | ||
_operation("Insert", self._location, value=item, index=index) | ||
) | ||
|
||
def clear(self): | ||
"""Remove all items in a list""" | ||
self._operations.append(_operation("Clear", self._location)) | ||
|
||
def reverse(self): | ||
"""Reversal of the order of items in a list""" | ||
self._operations.append(_operation("Reverse", self._location)) | ||
|
||
def extend(self, item): | ||
"""Add all the items to the end of a list""" | ||
if not isinstance(item, (list, tuple)): | ||
raise TypeError(f"{item} should be a list or tuple") | ||
self._operations.append(_operation("Extend", self._location, value=item)) | ||
|
||
def remove(self, item): | ||
"""filter the item out of a list on the frontend""" | ||
self._operations.append(_operation("Remove", self._location, value=item)) | ||
|
||
def update(self, E=None, **F): | ||
"""Merge a dict or keyword arguments with another dictionary""" | ||
value = E or {} | ||
value.update(F) | ||
self._operations.append(_operation("Merge", self._location, value=value)) | ||
|
||
# pylint: disable=no-self-use | ||
def sort(self): | ||
raise KeyError("sort is reserved for future use, use brackets to access this key on your object") | ||
|
||
def to_plotly_json(self): | ||
return { | ||
"__dash_patch_update": "__dash_patch_update", | ||
"operations": self._operations, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.