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

Some cleanup items #744

Merged
merged 9 commits into from
Sep 30, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
update docs
  • Loading branch information
sc1f committed Sep 30, 2019
commit 18c4942aa4b2a93b1aa5781b3e6da68df0215c14
2 changes: 1 addition & 1 deletion python/perspective/perspective/table/_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _type_to_format(data_or_schema):


class _PerspectiveAccessor(object):
'''Internal class to manage perspective table state'''
'''A uniform accessor that wraps data/schemas of varying formats with a common `marshal` function.'''

def __init__(self, data_or_schema):
self._format, self._data_or_schema = _type_to_format(data_or_schema)
Expand Down
2 changes: 1 addition & 1 deletion python/perspective/perspective/table/_callback_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def add_callback(self, callback):
self._callbacks.append(callback)

def remove_callbacks(self, condition):
'''Remove callback functions that satisfy the given condition
'''Remove callback functions that satisfy the given condition.

Params:
condition (func) : a function that returns either True or False. If True is returned, filter the item out.
Expand Down
31 changes: 27 additions & 4 deletions python/perspective/perspective/table/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,21 @@ def view(self, **config):
for querying, pivoting, aggregating, sorting, and filtering of data.

Params:
config (dict or None) : a dictionary containing any of the optional keys below:
**config (dict) : optional keyword arguments that configure and transform the view:
- "row_pivots" (list[str]) : a list of column names to use as row pivots
- "column_pivots" (list[str]) : a list of column names to use as column pivots
- "aggregates" (dict[str:str]) : a dictionary of column names to aggregate types to specify aggregates for individual columns
- "sort" (list(list[str]))
- "filter" (list(list[str]))

Returns:
View : a new instance of the `View` class.

Examples:
>>> tbl = Table({"a": [1, 2, 3]})
>>> view = tbl.view(filter=[["a", "==", 1]]
>>> view.to_dict()
>>> {"a": [1]}
'''
if config.get("columns") is None:
config["columns"] = self.columns() # TODO: push into C++
Expand All @@ -191,24 +200,38 @@ def view(self, **config):
return view

def on_delete(self, callback):
'''Register a callback with the table that will be invoked when the `delete()` method is called.'''
'''Register a callback with the table that will be invoked when the `delete()` method is called on the Table.

Examples:
>>> def deleter():
>>> print("Delete called!")
>>> table.on_delete(deleter)
>>> table.delete()
>>> Delete called!
'''
if not callable(callback):
raise ValueError("on_delete callback must be a callable function!")
self._delete_callback = callback

def delete(self):
'''Delete this table and clean up associated resources.'''
'''Delete this table and clean up associated resources in the core engine.

Tables with associated views cannot be deleted.

Called when `__del__` is called by GC.
'''
if len(self._views) > 0:
raise PerspectiveError("Cannot delete a Table with active views still linked to it - call delete() on each view, and try again.")
self._table.unregister_gnode(self._gnode_id)
if self._delete_callback:
self._delete_callback()

def _update_callback(self):
'''When the table is updated with new data, call each of the callbacks associated with the views.'''
cache = {}
for callback in self._callbacks.get_callbacks():
callback["callback"](cache=cache)

def __del__(self):
'''Before GC, clean up internal resources to C++ objects'''
'''Before GC, clean up internal resources to C++ objects through `delete()`.'''
self.delete()
39 changes: 35 additions & 4 deletions python/perspective/perspective/table/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,15 @@ def get_config(self):
return self._config.get_config()

def sides(self):
'''How many pivoted sides does this View have?'''
'''Returns the number of pivoted sides of this View.

0-sided views have no pivots applied.
1-sided views have one or more `row_pivots` applied.
2-sided views have one or more `row_pivots` and `column_pivots` applied, or one or more `column_pivots` without `row_pivots`.

Returns:
int : 0, 1, or 2
'''
if len(self._config.get_row_pivots()) > 0 or len(self._config.get_column_pivots()) > 0:
if len(self._config.get_column_pivots()) > 0:
return 2
Expand Down Expand Up @@ -107,6 +115,19 @@ def schema(self, as_string=False):
return {item[0]: _str_to_pythontype(item[1]) for item in self._view.schema().items()}

def on_update(self, callback, mode=None):
'''Add a callback to be fired when `Table.update()` is called on the underlying table.

Multiple callbacks can be set through calling `on_update` multiple times, and will be called in the order they are set.

Callback must be a callable function that takes no parameters.

Examples:
>>> def updater():
>>> print("Update fired!")
>>> view.on_update(updater)
>>> table.update({"a": [1]})'
>>> Update fired!
'''
mode = mode or "none"

if not callable(callback):
Expand All @@ -130,7 +151,7 @@ def remove_update(self, callback):
'''Given a callback function, remove it from the list of callbacks.

Params:
callback (func) : a callback that needs to be removed from the list of callbacks
callback (func) : a function reference that will be removed.
'''
if not callable(callback):
return ValueError("remove_update callback should be a callable function!")
Expand All @@ -140,14 +161,24 @@ def on_delete(self, callback):
'''Set a callback to be run when the `delete()` method is called on the View.

Params:
callback (func) : a callback to run after the delete operation has completed
callback (func) : a callback to run after `delete()` has been called.

Examples:
>>> def deleter():
>>> print("Delete called!")
>>> view.on_delete(deleter)
>>> view.delete()
>>> Delete called!
'''
if not callable(callback):
return ValueError("on_delete callback must be a callable function!")
self._delete_callback = callback

def delete(self):
'''Delete the view and clean up associated resources and references.'''
'''Delete the view and clean up all callbacks associated with the view.

Called when `__del__` is called by GC.
'''
self._table._views.pop(self._table._views.index(self._name))
# remove the callbacks associated with this view
self._callbacks.remove_callbacks(lambda cb: cb["name"] != self._name)
Expand Down
2 changes: 1 addition & 1 deletion python/perspective/perspective/table/view_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self, **config):
'''Receives a user-provided config dict and standardizes it for consumption by the python client and the core engine.

Params:
config (dict): the configuration dictionary provided by the user
config (dict) : optional keyword args that configure the view.
'''
self._config = config
self._row_pivots = self._config.get('row_pivots', [])
Expand Down