Skip to content

Commit

Permalink
Merge pull request #21 from force-h2020/traits-intro
Browse files Browse the repository at this point in the history
Traits intro
  • Loading branch information
sparsonslab committed Jun 2, 2020
2 parents b00090d + 31a22c0 commit 365dd7e
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 23 deletions.
36 changes: 27 additions & 9 deletions docs/source/extending/create_install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ Creating a Plugin

All plugin classes must

- Inherit from ``force_bdss.api.BaseExtensionPlugin``::
- Inherit from ``force_bdss.api.BaseExtensionPlugin``

.. code-block:: python
from force_bdss.api import BaseExtensionPlugin, plugin_id
Expand All @@ -13,7 +15,9 @@ All plugin classes must
"""This is an example of the plugin system for the BDSS."""
- Implement a ``id`` class member, that must be set to the result of
calling the function ``plugin_id()``::
calling the function ``plugin_id()``

.. code-block:: python
id = plugin_id("enthought", "example", VERSION)
Expand All @@ -23,7 +27,9 @@ All plugin classes must
``get_description()`` to return appropriate values. The ``get_version()``
method in particular should return the same value as in the id (in this case
zero). It is advised to extract this value in a global, module level
constant::
constant

.. code-block:: python
def get_name(self):
return "Enthought example"
Expand All @@ -35,7 +41,9 @@ All plugin classes must
return VERSION
- Implement a method ``get_factory_classes()`` returning a list of all
the classes (NOT the instances) of the entities you want to export.::
the classes (NOT the instances) of the entities you want to export.

.. code-block:: python
def get_factory_classes(self):
return [
Expand All @@ -57,7 +65,9 @@ can be found `here <https://setuptools.readthedocs.io/en/latest/setuptools.html>
The plugin is declared as an extension to the ``force_bdss`` by having it defined as the ``setup`` command
``entry_points`` keyword argument, under the namespace ``force.bdss.extensions``. You have to specify a path to the
plugin class (in this case ``ExamplePlugin``), as given below. The name (before the ``'='``) of the plugin is irrelevant, but to avoid confusion,
try to use the name of the module. For example::
try to use the name of the module. For example

.. code-block:: python
entry_points={
"force.bdss.extensions": [
Expand All @@ -66,7 +76,9 @@ try to use the name of the module. For example::
]
}
A basic example ``setup.py`` file is therefore shown below::
A basic example ``setup.py`` file is therefore shown below

.. code-block:: python
from setuptools import setup, find_packages
Expand All @@ -87,7 +99,9 @@ A basic example ``setup.py`` file is therefore shown below::
)
Running the following command line instruction from the same directory as ``setup.py`` will then install
the package in the deployed environment::
the package in the deployed environment

.. code-block:: console
edm run -e force-py36 -- pip install -e .
Expand All @@ -102,7 +116,9 @@ In which case, the plugin class
must inherit from ``force_bdss.api.ServiceOfferExtensionPlugin``
, which is a child class of ``BaseExtensionPlugin``. Any UI subclasses
can then be made discoverable by ``force-wfmanager`` using the Envisage
``ServiceOffer`` protocol through the ``get_service_offer_factories`` method::
``ServiceOffer`` protocol through the ``get_service_offer_factories`` method

.. code-block:: python
def get_service_offer_factories(self):
"""A method returning a list user-made objects to be provided by this
Expand Down Expand Up @@ -130,7 +146,9 @@ for any UI feature that can be used to display MCO data or a present a simplifie
workflow builder respectively.

Also, multiple types of plugin contributed UI objects can be imported in the same
method. For instance::
method. For instance

.. code-block:: python
from force_bdss.api import ServiceOfferExtensionPlugin
Expand Down
16 changes: 12 additions & 4 deletions docs/source/extending/data_source.rst
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ These functions could be merged into a single class.

``BaseDataSource``
------------------
The node's function. ::
The node's function.

.. code-block:: python
class Gaussian(BaseDataSource):
Expand Down Expand Up @@ -108,7 +110,9 @@ The ``run`` method is the function itself. Its arguments are:
``run()`` returns the list of ``DataValue`` objects that are the node's outputs.

The ``slots`` method returns ``Slot`` objects corresponding to the node's inputs and outputs, in the
form of a tuple::
form of a tuple

.. code-block:: python
((<tuple of input slots>), (<tuple of output slots>))
Expand All @@ -119,7 +123,9 @@ of ``run``'s return.

``BaseDataSourceModel``
-----------------------
The node's 'internal' parameters ::
The node's 'internal' parameters

.. code-block:: python
class GaussianModel(BaseDataSourceModel):
Expand Down Expand Up @@ -148,7 +154,9 @@ The ``View`` object determines how they are presented for editing in the Workflo
``BaseDataSourceFactory``
-------------------------
This is contributed to BDSS by the plugin and thus allows it to create instances of
``BaseDataSource`` and ``BaseDataSourceModel``. ::
``BaseDataSource`` and ``BaseDataSourceModel``.

.. code-block:: python
class GaussianFactory(BaseDataSourceFactory):
def get_identifier(self):
Expand Down
1 change: 1 addition & 0 deletions docs/source/extending/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ To implement a new plugin, you must define at least four classes:
.. toctree::
:maxdepth: 2

Traits and TraitsUI <traits>
The Plugin <create_install>
Factories and Classes <factory_class>
Data Source <data_source>
Expand Down
8 changes: 6 additions & 2 deletions docs/source/extending/notification.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ notification listeners.
Each notification listener is defined by an implementation of ``BaseNotificationListenerFactory``, which
contributes both ``BaseNotificationListenerModel`` and ``BaseNotificationListener``
subclasses. It therefore requires implementation of the following additional abstract methods alongside
the standard ``get_identifier``, ``get_name``, and ``get_description`` methods::
the standard ``get_identifier``, ``get_name``, and ``get_description`` methods

.. code-block:: python
def get_model_class(self):
Returns a BaseNotificationListenerModel subclass
Expand All @@ -18,7 +20,9 @@ the standard ``get_identifier``, ``get_name``, and ``get_description`` methods::
Returns a BaseNotificationListener subclass
The BaseNotificationListener class must reimplement the following methods, that
are invoked in specific lifetime events of the BDSS::
are invoked in specific lifetime events of the BDSS

.. code-block:: python
def initialize(self):
Called once, when the BDSS is initialized. For example, to setup the
Expand Down
16 changes: 12 additions & 4 deletions docs/source/extending/optimizer_engine.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ optimizer can be examined

``BaseMCOModel``
----------------
The TraitsUI to the optimizer. ::
The TraitsUI to the optimizer.

.. code-block:: python
class NevergradMCOModel(BaseMCOModel):
Expand Down Expand Up @@ -47,7 +49,9 @@ It exposes a set of optimizer parameters with an associated ``View``.

``BaseMCO``
-----------
Creates a ``BaseOptimizerEngine`` object and runs that engine on the workflow. ::
Creates a ``BaseOptimizerEngine`` object and runs that engine on the workflow.

.. code-block:: python
class NevergradMCO(BaseMCO):
Expand Down Expand Up @@ -114,7 +118,9 @@ method if you want to pass additional/different values to the model.

``BaseOptimizerEngine``
-----------------------
Does the actual optimization. ::
Does the actual optimization.

.. code-block:: python
class AposterioriOptimizerEngine(BaseOptimizerEngine):
Expand Down Expand Up @@ -157,7 +163,9 @@ the BDSS running as a subprocess of the MCO to evaluate a single point.
``BaseMCOFactory``
------------------
This is contributed to BDSS by the plugin and thus allows it to create instances of
``BaseMCOModel``, ``BaseMCO`` and ``BaseMCOCommunicator``. ::
``BaseMCOModel``, ``BaseMCO`` and ``BaseMCOCommunicator``.

.. code-block:: python
class NevergradMCOFactory(BaseMCOFactory):
Expand Down
8 changes: 6 additions & 2 deletions docs/source/extending/parameter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ parameterization can be examined

``BaseMCOParameter``
--------------------
A parameterization. ::
A parameterization.

.. code-block:: python
class RangedMCOParameter(BaseMCOParameter):
Expand Down Expand Up @@ -64,7 +66,9 @@ be verified in the UI when it is changed should set the verify=True metadata.
``BaseMCOParameterFactory``
---------------------------
Each ``BaseMCOParameter`` must be associated with a ``BaseMCOParameterFactory`` that returns
its class, description, etc. ::
its class, description, etc.

.. code-block:: python
class RangedMCOParameterFactory(BaseMCOParameterFactory):
""" Ranged Parameter factory"""
Expand Down
153 changes: 153 additions & 0 deletions docs/source/extending/traits.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
Traits and TraitsUI
===================

Traits is a python package, developed by Enthought, for creating and interacting with
statically-typed variables: '**traits**'. To efficiently develop UIs for traits
Enthough developed a sister package, TraitsUI.

A class that has traits variables as attributes, inherits from ``HasTraits``,
so that those variables can be initialized and handled appropriately. Most, if not all,
of the classes in the BDSS (and in the Workflow Manager) inherit from ``HasTraits``,
therefore before extending BDSS it is useful to have some basic knowledge of Traits and
TraitsUI.

Full documentation can be found here:

`Traits <https://docs.enthought.com/traits/>`_

`TraitsUI <https://docs.enthought.com/traitsui/traitsui_user_manual/index.html#contents>`_

These provide brief introductions to the packages. Here we provide an even more
minimal introduction that should make the code examples in following topics clearer.

Traits
------
Traits are class objects (like every variable in python). The more common classes just
wrap around a built-in python type, with a class name that is the camel case version
of the built-in type. For instance,

.. code-block:: python
# initialization of a string trait, x.
x = Str('hello world')
# initialization of a dictionary trait, y.
y = Dict({'English':'hello world', 'German':'hallo welt'})
# initialization of a float trait, z, to the default value of 0.0
z = Float()
print(z)
>> 0.0
Traits are typically initialized within a ``HasTraits`` class,

.. code-block:: python
class HelloWorld(HasTraits):
x = Str('bonjour le monde')
.....
The ``HasTraits`` inheritence defines a constructor that takes the traits as
arguments.

.. code-block:: python
my_hello_world = HelloWorld(x='ciao mondo', .....)
print(my_hello_world.x)
>> ciao mondo
If no argument is given for a trait it is initialized to the value (default or otherwise)
given within the class declaration,

.. code-block:: python
my_hello_world = HelloWorld()
print(my_hello_world.x)
>> bonjour le monde
As with any python class member, traits variables are refered to by ``self`` in
methods,

.. code-block:: python
class HelloWorld(HasTraits):
x = Str('bonjour le monde')
def shout_the_greeting(self):
return self.x.upper()
my_hello_world = HelloWorld()
print(my_hello_world.shout_the_greeting())
>> BONJOUR LE MONDE
Almost all classes in the BDSS and the Workflow Manager (including all those in the code
examples in the following topics) inherit from ``HasTraits``, usually indirectly through
a base class (you won't see ``HasTraits`` in the class declaration).

Views
-----

TraitsUI provides the UI to traits (as the name suggests!). It provides any
``HasTraits`` object with a default UI that exposes all the traits it contains. Each
trait type is associated with a default UI element (text field for a Str, etc.) and
TraitsUI lays out these elements automatically in a window or panel.

A custom layout, possibly including custom UI elements ('editors'), can be provided by
intializing a ``View`` object within the ``TraitsUI`` class,

.. code-block:: python
class HelloWorld(HasTraits):
x = Str('bonjour le monde')
y = Int(5)
view = View(
Item(name='x', label='hello message', editor=HTMLEditor()),
Item(name='y', label='number of people listening'),
padding=10,
resizable=True
)
Each trait is associated with an ``Item`` object (itself a ``HasTraits`` class) by
assigning the ``Item`` 's ``name`` attribute to the string of the trait
variable name. In addition, the ``Item`` constructor has optional arguments that
determine what non-default UI elements ('editors'), if any, are used to expose
the trait and how they are laid out.

The ``Item`` s are assigned to a ``View`` object as * vargs. In addition the ``View``
constructor has a number of optional keyword arguments that determine layout, etc.

For layout purposes ``Item`` s can be grouped by assigning them to ``Group`` objects
that are then assigned to the ``View``.

.. code-block:: python
view = View(
Group(
Item(name='x', label='hello message'),
Item(name='y', label='number of people arriving'),
label='arriving'
),
Group(
Item(name='i', label='goodbye message'),
Item(name='j', label='number of people departing'),
label='departing'
)
)
Like for the ``View``, the ``Group`` constructor has a number of keyword arguments that
effect layout, labelling, etc.

In the following topics, code examples with ``View`` initializations will show the
resulting UI alongside.

0 comments on commit 365dd7e

Please sign in to comment.