Skip to content

Commit

Permalink
Merge pull request #196 from quantopian/bump-version
Browse files Browse the repository at this point in the history
Bump version to 1.0.3 (promote beta release to GA)
  • Loading branch information
TimShawver authored Jun 1, 2018
2 parents 5e12f8f + 733e807 commit 78e703e
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 21 deletions.
55 changes: 42 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@ Qgrid is a Jupyter notebook widget which uses `SlickGrid <https://github.com/mle
DataFrames within a Jupyter notebook. This allows you to explore your DataFrames with intuitive scrolling, sorting, and
filtering controls, as well as edit your DataFrames by double clicking cells.

We originally developed qgrid for use in `Quantopian's hosted research environment
<https://www.quantopian.com/research?utm_source=github&utm_medium=web&utm_campaign=qgrid-repo>`_ in fall of 2014, but
had to put it on the backburner for a while so we could focus on higher priority projects.
What's New in 1.0.3 - Introducing Qgrid Events
----------------------------------------------
Qgrid has some new API methods as of version 1.0.3 which can be used to attach event handlers. Event handlers are callback methods that get called when certain events occur in the qgrid interface. In qgrid 1.0.3, event handlers can be attached with the ``on`` method and detached with the ``off`` method. There are ``on`` and ``off`` methods on both the ``qgrid`` module (see `qgrid.on <https://qgrid.readthedocs.io/en/latest/#qgrid.on>`_), and on individual QgridWidget instances (see `qgrid.QgridWidget.on <https://qgrid.readthedocs.io/en/latest/#qgrid.QgridWidget.on>`_).

Qgrid development started up again in summer 2017, when we started a major refactoring project to allow qgrid to take
advantage of the latest advances in ipywidgets (specifically, ipywidget 7.x). As a part of this refactoring we also
moved qgrid's sorting, and filtering logic from the client (javascript) to the server (python). This new version is
called qgrid 1.0, and the instructions that follow are for this new version.
To get a better idea of how these methods might be used, see the `Events API`_ section below.

Demo
----
Expand Down Expand Up @@ -199,20 +196,52 @@ read-the-docs page, you can preview your changes locally before submitting a PR
This will result in the ``docs/_build/html`` folder being populated with a new version of the read-the-docs site. If
you open the ``index.html`` file in your browser, you should be able to preview your changes.

Experimental Demo
-----------------
As of qgrid 1.0 there are some interesting ways we can use qgrid in conjunction with other widgets/visualizations. One example is using qgrid to filter a DataFrame that's also being displayed by another visualization.
Events API
----------
As of qgrid 1.0.3 there are new ``on`` and ``off`` methods in qgrid which can be used to attach/detach event handlers. Previously the only way to listen for events was to use undocumented parts of the API.

Having the ability to attach event handlers allows us to do some interesting things in terms of using qgrid in conjunction with other widgets/visualizations. One example is using qgrid to filter a DataFrame that's also being displayed by another visualization.

If you previously used the ``observe`` method to respond to qgrid events, lets see how your code might be updated to use the new ``on`` method::

# Before upgrading to 1.0.3
def handle_df_change(change):
print(change['new'])

qgrid_widget.observe(handle_df_change, names=['_df'])

When you upgrade to 1.0.3, you have more granular control over which events you do an don't listen to, but you can also replicate the previous behavior of calling ``print`` every time the state of the internal DataFrame is changed. Here's what that would look like using the new ``on`` method::

# After upgrading to 1.0.3
def handle_json_updated(event, qgrid_widget):
# exclude 'viewport_changed' events since that doesn't change the DataFrame
if (event['triggered_by'] != 'viewport_changed'):
print(qgrid_widget.get_changed_df())

Currently these ways of using qgrid are not documented in the API docs or extensively tested, so they're still considered experimental. See the `experimental notebook <https://beta.mybinder.org/v2/gh/quantopian/qgrid-notebooks/master?filepath=experimental.ipynb>`_ to learn more.
qgrid_widget.on('json_updated', handle_json_updated)

For people who would rather not go to another page to try out the experimental notebook, here's the tldr; version:
See the `events notebook <https://mybinder.org/v2/gh/quantopian/qgrid-notebooks/master?filepath=events.ipynb>`_ for more examples of using these new API methods.

For people who would rather not go to another page to try out the events notebook, here are a couple of gifs to give you an idea of what you can do with it.

The first gif shows how you can use qgrid to filter the data that's being shown by a matplotlib scatter plot:

.. figure:: docs/images/linked_to_scatter.gif
:align: left
:target: docs/images/linked_to_scatter.gif
:width: 600px

A brief demo showing filtering, editing, and the `get_changed_df()` method
A brief demo showing qgrid hooked up to a matplotlib plot

The second gif shows how you can move qgrid to a separate view in JupyterLab, which makes it more convenient
to use in conjunction with other visualizations (in this case, a couple of ``Output`` widgets):

.. figure:: docs/images/events_api.gif
:align: left
:target: docs/images/events_api.gif
:width: 600px

A brief demo showing qgrid's events api

Continuing to use qgrid 0.3.3
-----------------------------
Expand Down
Binary file added docs/images/events_api.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "qgrid",
"version": "1.0.3-beta.0",
"version": "1.0.3",
"description": "An Interactive Grid for Sorting and Filtering DataFrames in Jupyter Notebook",
"author": "Quantopian Inc.",
"main": "src/index.js",
Expand Down
4 changes: 2 additions & 2 deletions js/src/qgrid.widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class QgridModel extends widgets.DOMWidgetModel {
_view_name : 'QgridView',
_model_module : 'qgrid',
_view_module : 'qgrid',
_model_module_version : '^1.0.3-beta.0',
_view_module_version : '^1.0.3-beta.0',
_model_module_version : '^1.0.3',
_view_module_version : '^1.0.3',
_df_json: '',
_columns: {}
});
Expand Down
2 changes: 1 addition & 1 deletion qgrid/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version_info = (1, 0, 3, 'beta', 0)
version_info = (1, 0, 3, 'final')

_specifier_ = {'alpha': 'a', 'beta': 'b', 'candidate': 'rc', 'final': ''}

Expand Down
10 changes: 6 additions & 4 deletions qgrid/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def on(names, handler):
The reason it's not available on individual qgrid instances is because
the only time it fires is when a new instance is created. This means
it's already donefiring by the time a user has a chance to hook up any
it's already done firing by the time a user has a chance to hook up any
event listeners.
Here's the full list of events that can be listened for via this
Expand Down Expand Up @@ -464,8 +464,8 @@ class QgridWidget(widgets.DOMWidget):
_model_name = Unicode('QgridModel').tag(sync=True)
_view_module = Unicode('qgrid').tag(sync=True)
_model_module = Unicode('qgrid').tag(sync=True)
_view_module_version = Unicode('1.0.3-beta.0').tag(sync=True)
_model_module_version = Unicode('1.0.3-beta.0').tag(sync=True)
_view_module_version = Unicode('1.0.3').tag(sync=True)
_model_module_version = Unicode('1.0.3').tag(sync=True)

_df = Instance(pd.DataFrame)
_df_json = Unicode('', sync=True)
Expand Down Expand Up @@ -588,7 +588,9 @@ def on(self, names, handler):
effect of certain actions such as scrolling, sorting, and filtering.
* **triggered_by** The name of the event that resulted in rows of
data being sent down to the browser.
data being sent down to the browser. Possible values are
``viewport_changed``, ``filter_changed``, ``sort_changed``,
``add_row``, and ``remove_row``.
* **range** A tuple specifying the range of rows that have been
sent down to the browser.
Expand Down

0 comments on commit 78e703e

Please sign in to comment.