Skip to content

Commit

Permalink
Backport documentation fixes and bugfixes for 7.1.0 release (#777)
Browse files Browse the repository at this point in the history
* Add a section to the documentation on the basics of Pyface Widgets. (#739)

(cherry picked from commit 86c9a9c)

* avoid importing ArrayDataModel if numpy is not installed (#749)

* avoid importing ArrayDataModel if numpy is not installed

* replace try except with look-before-you-leap approach

* typo

(cherry picked from commit a68eb28)

* Add api.py to data view packages (#750)

* Add/update api.py modules for data views.

* Use data view api modules in examples.

* Add data view api modules to documentation examples.

* Add some extra imports, change import locations.

* Test API modules in pyface.data_view (#752)

* Add test for pyface.data_view.api

* Add test for pyface.data_view.exporters.api

* Add test for data models API

Make sure the api module is importable even if we don't have NumPy

* Add tests to help developers keeping the list up-to-date

* Fix language in a comment

* Remove mixins from .api.

* Adjust tests.

Co-authored-by: Kit Choi <[email protected]>
(cherry picked from commit e9b7d96)

* Mention the data view API being provisional in the User Manual (#758)

(cherry picked from commit cfb3f8c)

* Set comparison mode to identity for MDataViewWidget.exporters (#759)

(cherry picked from commit d5f5e7f)

* Skip tests packages in API documentation (#761)

(cherry picked from commit 9f13097)

* Skip load_tests in API documentation (#762)

* Skip load_tests in autodoc

* Local flake8

(cherry picked from commit a3ad0f2)

* Additional documentation for the DataView (#763)

* Add documentation on Drag and Drop.

* Add a note about DataViewGetError.

* More notes on value types.

* Apply suggestions from code review

Co-authored-by: Kit Choi <[email protected]>

* Fix references to exporters.

Co-authored-by: Kit Choi <[email protected]>
(cherry picked from commit 3acd644)

* FIX docs click command to work on windows (#764)

* FIX : Docs build on windows

	modified:   etstool.py

* Update etstool.py

Co-authored-by: Kit Choi <[email protected]>

Co-authored-by: Kit Choi <[email protected]>
(cherry picked from commit bac64de)

* CLN : Rename api-docs click command to docs (#766)

Now, traitsui and pyface have the same command name - reducing
unnecessary cognitive overhead.

	modified:   etstool.py

(cherry picked from commit 3a6d349)

* FIX : Correct a docstring (#767)

(cherry picked from commit 95d0474)

* Get ModalDialogTester tests working on pyqt5 (#768)

* FIX : Get ModalDialogTester tests working on pyqt5

The tests were previously being skipped because they failed mysteriously
on pyqt5 - on further investigation, I saw weird errors related to two
of the tests - a missing AttributeError for self.gui

	modified:   pyface/ui/qt4/util/tests/test_modal_dialog_tester.py

* FIX : Reverse order of superclasses

	modified:   pyface/ui/qt4/util/tests/test_modal_dialog_tester.py

(cherry picked from commit 96b8580)

* Address sphinx warnings when building docs (#769)

* FIX : Address sphinx warnings when building docs

* FIX : Revert a confusing change

(i couldnt come up with a worse commit message)

	modified:   pyface/timer/do_later.py

(cherry picked from commit 5b21b49)

* Explicitly extract data from bytearrays rather than rely on wrapper. (#773)

(cherry picked from commit 0d5565f)

* Update changelog

Co-authored-by: Corran Webster <[email protected]>
Co-authored-by: aaronayres35 <[email protected]>
Co-authored-by: Poruri Sai Rahul <[email protected]>
  • Loading branch information
4 people authored Oct 19, 2020
1 parent 5818182 commit 1426bc5
Show file tree
Hide file tree
Showing 38 changed files with 588 additions and 61 deletions.
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ Build and continuous integration

Documentation

* Add documentation for the new PyfaceColor trait and Color class. (#710)
* Add documentation for DataView. (#543, #574, #763)
* Remove all enaml examples. (#652)
* Fix some Sphinx warnings while building documentation. (#769)

Maintenance and code organization

Expand Down
9 changes: 9 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,12 @@
'IPython.frontend.wx',
'IPython.frontend.wx.wx_frontend',
]


def autodoc_skip_member(app, what, name, obj, skip, options):
# Skip load_tests
return skip or name == "load_tests"


def setup(app):
app.connect('autodoc-skip-member', autodoc_skip_member)
139 changes: 137 additions & 2 deletions docs/source/data_view.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ Pyface DataViews
The Pyface DataView API allows visualization of hierarchical and
non-hierarchical tabular data.

.. note::
As of Pyface 7.1.0, the public API for DataView is provisional and may
change in the future minor releases through until Pyface 8.0

.. See enthought/pyface#756 for removing the note.
Indexing
--------

Expand Down Expand Up @@ -90,6 +96,104 @@ Note: with the current implementations, the |selection| list should not be
mutated, rather the entire list should be replaced on every change. This
restriction may be relaxed in the future.


Drag and Drop
-------------

The |IDataViewWidget| interface provides hooks to support dragging the
selected values out of the table, or dropping objects onto the data view.
To provide cross-platform and cross-toolkit compatibility, drag and drop
operations require the data that is being exported or imported to be
converted to or from a bytestring in some MIME type.

The DataView infrastructure provides a |DataFormat| named tuple to
encapsulate the process of converting different data objects to bytes.
For string objects this conversion might be as simple as encoding the
text as UTF-8 and declaring it to be a ``text/plain`` MIME type, but for
more complex structures there is serialization and deserialization which
needs to occur. The |DataFormat| objects are expected to provide the
mimetype of the data, a function to serialize an object, and a function
to deserialize bytes.

In practice the sorts of objects being dragged and dropped, can be
classified as simple scalar values (such as might occur when the selection
is a single item), 1D collections of values (such as might occur when
multiple items are selected, or a single row or column is selected),
or 2D collections of values (such as might occur for extended row or
column selections).

The DataView api provides a standard data formats for plain text, CSV,
and .npy format for scalar, 1D and 2D exports; HTML and JSON formats
for scalar values, as well as standard serializers and deserializers
for users to create build their own |DataFormat| instances if the defaults
do not match the needs.

Dragging
~~~~~~~~

To allow dragging the selection, the |exporters| trait should hold a list
of |AbstractDataExporter| instances. This class provides methods to access
the values to be exported from the selected indices, as well as a reference
to a |DataFormat| that will perform the actual serialization and provides
the MIME type.

In practice, users will usually use a standard data exporter, such as the
|ItemExporter| or |RowExporter|. Some care should be taken that
the data exporter provides data in the shape that the |DataFormat| expects.
For example, the |ItemExporter| works best when paired with scalar data
formats. In many cases all that is needed to enable dragging data from a
DataViewWidget is to configure it appropriately:

.. code-block:: python
control = DataViewWidget(
...,
selection_mode='extended',
exporters=[
RowExporter(format=table_format),
RowExporter(format=csv_format),
],
...
)
When multiple exporters are provided, _all_ of the supported formats are
exported as part of the drag operation, and it is up to the target program
to decide which of the supplied formats it can best handle, if any.

Dropping
~~~~~~~~

The |IDataViewWidget| supports dropping of objects via the |IDropHandler|
interface supported by other widgets. Developers using DataViews can
handle dropped data by providing a list of |IDropHandler| instances which
tell the underlying code whether the objects being dropped can be dropped,
and if so, how to handle the drop operation.

For example, to handle files being dropped onto the DataView, a DataView could
use the generic |FileDropHandler| class, coupled with a callback to load the
data from the dropped file.

.. code-block:: python
control = DataViewWidget(
...,
drop_handlers=[
FileDropHandler(
extensions=['.csv', '.tsv', '.npy'],
open_file=self.load_data,
)
],
...
)
When multiple drop handlers are supplied, the first one which says it can
handle the dropped objects is the one which is used.

There are currently no specific drop handlers for supporting dragging
data within the table, but this can be supported by custom drop handlers
that use toolkit code to interact with the underlying toolkit objects.


Index Managers
--------------

Expand Down Expand Up @@ -174,7 +278,8 @@ it corresponds to the keys or the values. The code looks like this:
:end-at: return value

Conversion of values into data channels is done by providing a value type
for each cell. The |get_value_type| method provides an appropriate data
for each cell that implements the |AbstractValueType| interface. The
|get_value_type| method is expected to provide an appropriate data
type for each item in the table. For this data model we have three value
types: the column headers, the keys and the values.

Expand All @@ -196,6 +301,27 @@ value types:
:start-at: def get_value_type
:end-at: return self.value_type

The |AbstractValueType| interface provides getters (and in some cases setters)
for various data channels the most obvious of these is the text to display
in an item, but channels allow checked state, image, color and tooltips
to also be associated with a value. How (or even if) these values are
displayed or used is up to the implementation of the |IDataViewWidget|.

As noted above, the DataView API provides a number of pre-definited value
type implementations that cover common cases, but where they do not meet the
needs of a particular design, developers should create their own
implementations with the desired properties.

Invalid Values
~~~~~~~~~~~~~~

If no valid value can be generated for some *expected* reason, value
generation code can raise a |DataViewGetError| exception. This error
will be handled and silently ignored by the DataView code, and no value
will be displayed. Any other errors raised by value generation are
assumed to be unexpected and will be logged and re-raised, which is
likely to cause an application crash.

Handling Updates
~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -275,11 +401,19 @@ the |has_editor_value| method returns ``False``.
.. |AbstractIndexManager| replace:: :py:class:`~pyface.data_view.index_manager.AbstractIndexManager`
.. |AbstractDataModel| replace:: :py:class:`~pyface.data_view.abstract_data_model.AbstractDataModel`
.. |DataViewSetError| replace:: :py:class:`~pyface.data_view.abstract_data_model.DataViewSetError`
.. |AbstractDataExporter| replace:: :py:class:`~pyface.data_view.abstract_data_exporter.AbstractDataExporter`
.. |AbstractValueType| replace:: :py:class:`~pyface.data_view.abstract_value_type.AbstractValueType`
.. |DataFormat| replace:: :py:class:`~pyface.data_view.i_data_wrapper.DataFormat`
.. |DataViewGetError| replace:: :py:class:`~pyface.data_view.data_view_errors.DataViewGetError`
.. |DataViewSetError| replace:: :py:class:`~pyface.data_view.data_view_errors.DataViewSetError`
.. |EditableValue| replace:: :py:class:`~pyface.data_view.value_types.editable_value.EditableValue`
.. |FileDropHandler| replace:: :py:class:`~pyface.drop_handler.FileDropHandler`
.. |IDataViewWidget| replace:: :py:class:`~pyface.data_view.i_data_view_widget.IDataViewWidget`
.. |IDropHandler| replace:: :py:class:`~pyface.i_drop_handler.IDropHandler`
.. |IntIndexManager| replace:: :py:class:`~pyface.data_view.index_manager.IntIndexManager`
.. |IntValue| replace:: :py:class:`~pyface.data_view.value_types.numeric_value.IntValue`
.. |ItemExporter| replace:: :py:class:`~pyface.data_view.exporters.item_exporter.ItemExporter`
.. |RowExporter| replace:: :py:class:`~pyface.data_view.exporters.row_exporter.RowExporter`
.. |TextValue| replace:: :py:class:`~pyface.data_view.value_types.text_value.TextValue`
.. |TupleIndexManager| replace:: :py:class:`~pyface.data_view.index_manager.TupleIndexManager`
.. |can_have_children| replace:: :py:meth:`~pyface.data_view.abstract_data_model.AbstractDataModel.can_have_children`
Expand All @@ -289,6 +423,7 @@ the |has_editor_value| method returns ``False``.
.. |get_value| replace:: :py:meth:`~pyface.data_view.abstract_data_model.AbstractDataModel.get_value`
.. |get_value_type| replace:: :py:meth:`~pyface.data_view.abstract_data_model.AbstractDataModel.get_value`
.. |has_editor_value| replace:: :py:meth:`~pyface.data_view.abstract_value_type.AbstractValueType.has_editor_value`
.. |exporters| replace:: :py:attr:`~pyface.data_view.i_data_view_widget.IDataViewWidget.exporters`
.. |selection| replace:: :py:attr:`~pyface.data_view.i_data_view_widget.IDataViewWidget.selection`
.. |selection_mode| replace:: :py:attr:`~pyface.data_view.i_data_view_widget.IDataViewWidget.selection_mode`
.. |selection_type| replace:: :py:attr:`~pyface.data_view.i_data_view_widget.IDataViewWidget.selection_type`
Expand Down
3 changes: 1 addition & 2 deletions docs/source/examples/data_model_indices.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

from traits.api import Instance, Int, List

from pyface.data_view.abstract_data_model import AbstractDataModel
from pyface.data_view.index_manager import TupleIndexManager
from pyface.data_view.api import AbstractDataModel, TupleIndexManager


class IndexDataModel(AbstractDataModel):
Expand Down
8 changes: 2 additions & 6 deletions docs/source/examples/dict_data_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@

from traits.api import ComparisonMode, Dict, Instance, Str, observe

from pyface.data_view.abstract_data_model import (
AbstractDataModel, DataViewSetError
from pyface.data_view.api import (
AbstractDataModel, AbstractValueType, DataViewSetError, IntIndexManager
)
from pyface.data_view.abstract_value_type import AbstractValueType
from pyface.data_view.index_manager import IntIndexManager


class DictDataModel(AbstractDataModel):
Expand Down Expand Up @@ -121,7 +119,6 @@ def _value_type_default(self):
from pyface.data_view.data_view_widget import DataViewWidget
from pyface.data_view.value_types.api import IntValue, TextValue


class MainWindow(ApplicationWindow):
""" The main application window. """

Expand All @@ -144,7 +141,6 @@ def destroy(self):
self.data_view.destroy()
super().destroy()


# Create the GUI (this does NOT start the GUI event loop).
gui = GUI()

Expand Down
2 changes: 2 additions & 0 deletions docs/source/fields.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _fields:

======
Fields
======
Expand Down
3 changes: 2 additions & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ Contents

Overview <overview>
Toolkits <toolkits>
Submodules <submodules>
Widgets <widgets>
Pyface Applications <applications>
Pyface Trait Types <traits>
Submodules <submodules>
API Documentation <api/pyface>
Change Log <changelog>
2 changes: 2 additions & 0 deletions docs/source/overview.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _overview:

========
Overview
========
Expand Down
Loading

0 comments on commit 1426bc5

Please sign in to comment.