Commit 5f51401e authored by legac's avatar legac Committed by LE GAC Renaud
Browse files

Complete the documentation with epytext.

parent c5397581
......@@ -79,12 +79,18 @@ def epydoc():
# create the directory
if not os.path.exists(HTMLDOC):
os.makedirs(HTMLDOC)
# inhibit the __init__.py files
# to avoid long modules path in the documentation
os.rename("__init__.py", "__init__.py.ref")
os.rename("modules/__init__.py", "modules/__init__.py.ref")
# clean the directory
for el in os.listdir(HTMLDOC):
os.remove(os.path.join(HTMLDOC, el))
cmd = ["epydoc", "--html",
cmd = ["epydoc", "--docformat", "epytext",
"--html",
"--name", "plugin_dbui",
"-o", HTMLDOC,
"--parse-only",
......@@ -92,6 +98,11 @@ def epydoc():
"modules/plugin_dbui/*.py"]
subprocess.call(cmd)
# restore the __init__.py files
os.rename("__init__.py.ref", "__init__.py")
os.rename("modules/__init__.py.ref", "modules/__init__.py")
print "HTML documentation in", HTMLDOC
def get_version():
......
......@@ -444,7 +444,7 @@ def to_gridFilter(table, **kwargs):
where C{field1} is the name of a field belonging to the C{table}.
A more elaborate filter rule allows to filter on any foreign field using
the syntax is C{("table2.field1", "operator", "comments")}.
Valid operators are defined in the method L{DbSvc._encode_query}.
Valid operators are defined in the method L{dbsvc.DbSvc._encode_query}.
@note: Rules are store in the modifier section C{grid_filters}.
......
......@@ -33,9 +33,11 @@ class DbSvcException(BaseException): pass
class DbSvc(BaseSvc):
"""Interface the database and the client request.
It is the glue between wep2py and ExtJS library.
It relies on the C{Ext.Direct} protocol exposing DbSvc methods on
the client-side.
It is the glue between wep2py and Ext JS library.
This service is the companion of L{DirectSvc} which implements
the C{Ext.Direct} protocol on the server side.
This protocol exposes methods of the C{DbSvc} service directly
on the client-side.
The main methods allow to:
......
""" Author: R. Le Gac
""" implementation of the C{Ext.Direct} protocol on the server-side.
@author: R. Le Gac
"""
......@@ -18,7 +20,7 @@ PROC_KEY = '%s.%s'
class MyJsonEncoder(json.JSONEncoder):
"""Add date, datetime and time to the standard encoder.
"""Add date, datetime and time to the standard JSON encoder.
"""
def default(self, obj):
......@@ -33,31 +35,37 @@ class MyJsonEncoder(json.JSONEncoder):
class DirectSvc(BaseSvc):
"""Generic service to implement the Ext.Direct protocol on the server side
Specification: U{http://www.sencha.com/products/extjs/extdirect/}
"""Generic service to implement the
U{Ext.Direct<http://www.sencha.com/products/extjs/extdirect/>} protocol
on the server-side.
This implementation is based on the web2py service:
U{http://www.web2py.com/book/default/chapter/09}
It is a simplified version of the class Service in gluon.tools.
This implementation is based on the
U{web2py service<http://www.web2py.com/book/default/chapter/09>}
using a simplified version of the class L{gluon.tools.Service}.
To register functions and make it available remotely use decorator::
To register functions and make them available on the client-side
use decorator::
service = DirectSvc(globals())
@service.register
def myfunction(a, b):
The same technique can be used with method of a class.
The same technique can be used with methods.
On the client-side:
On the client side the api definition can be retrieved using the
url: /app/plugin_dbui/call/get_api
- the API definition can be retrieved using the
URL: C{/myapplication/plugin_dbui/call/get_api}
On the client side the url to send requests is /app/plugin_dbui/call
Remote functions / methods can be call in the following way:
Dbui.myfunction(a, b, callback), MyClass.mymethod(c, d, callback).
- the URL to send requests is
C{/myapplication/plugin_dbui/call}
- remote functions and methods can be call in the
following way C{Dbui.myfunction(a, b, callback)}
and C{MyClass.mymethod(c, d, callback)} respectively.
In this implementation requests are JSON-Encoded raw HTTP
and response are JSON encoded.
In this implementation requests and response are JSON encoded.
"""
......@@ -70,6 +78,19 @@ class DirectSvc(BaseSvc):
def __call__(self):
"""Check the client request and launch the execution
of the function / method on the server.
@rtype: str
@return:
- the response of the function / method run
on the server side
- the response is encoded as a JSON string.
@raise gluon.http.HTTP: when the request has no arguments
or when the function / method crashed.
"""
self.dbg('Start directSvc.call')
request = self.environment['request']
......@@ -81,18 +102,44 @@ class DirectSvc(BaseSvc):
def echo(self, x):
"""Helper function returning the input arguments.
Helpful to run echo tests.
"""Return the input arguments to run echo tests.
"""
return x
def error(self, code, message):
"""Build and raise the gluon.http.HTTP exception
@type code: int
@param code: code of the HTTP error
@type message: str
@param message: explanation for the HTTP error
@raise gluon.http.HTTP:
"""
raise HTTP(code, message)
def register(self, f):
""" Register a function/method.
Example::
service = DirectSvc(globals())
@service.register
def myfunction(a, b):
@type f: function
@rtype: function
@return: f
"""
# a procedure is registered as 'action.method'
# The action is equal to Dbui for a function
# and to the name of the class for a method
......@@ -108,9 +155,18 @@ class DirectSvc(BaseSvc):
def route(self):
"""Route the request to the appropriate methods, pass the
proper arguments and return the results.
"""Route the request to the appropriate function / method,
pass the proper arguments and return the results.
@rtype: str
@return: the response of the function / method
encoded as a JSON string.
@raise gluon.http.HTTP:
- with the code 500 when
the execution of the function / method crash.
- the python trace back is stored in the web2py ticket system.
"""
self.dbg('Start directSvc.route')
......
""" Configurators for Ext JS components.
""" configurators for the Ext JS components.
@author: R. Le Gac
......
""" Author: R. Le Gac
""" the fields modifier
@author: R. Le Gac
"""
......@@ -10,12 +12,38 @@ MODIFIER_FIELDS = 'modifier_fields'
class FieldsModifier(Modifier):
"""Helper tool to customise the field widget of a table.
"""Modifier to customise the field widgets associated to a database table.
"""
def __init__(self, tablename):
"""Initialize the modifier persistent data.
"""Initialize the fields modifier associated to the database
table C{tablename}.
The data structure of the fields modifier can be access
outside the class:
>>> p = PluginManager('dbui')
>>> modifier = p.dbui['modifier_fields'][tablename]
or internally via the attribute C{data}.
The keys of the C{data} structure are:
- C{extjs_fields} (dict) Ext JS configuration options
for individual C{field}.
- C{composite_fields.main} (list) the first field
of the CompositeField.
- C{composite_fields.others} (list of list) the others field of
a CompositeField.
- There is one to one correspondence between the C{composite_fields.main}
and the C{composite_fields.others} lists.
@type tablename: str
@param tablename: name of the database table
"""
Modifier.__init__(self, MODIFIER_FIELDS, tablename)
......@@ -30,37 +58,41 @@ class FieldsModifier(Modifier):
def append_plugins(self, *plugins):
"""Overwrite the method of the base class since it make
no sense in for this modifier.
no sense for this modifier.
"""
def configure(self, **extjs):
"""Overwrite the method of the base class since it make
no sense in for this modifier.
no sense for this modifier.
"""
def configure_field(self, field, **kwargs):
"""Update the configuration options of the field widget:
Ext.form.Field, Ext.form.DateField, Ext.form.TextField....
"""Update the configuration options of the Ext JS widget
associated to the C{field}.
Existing value of the configuration options are replace by those
defined by the keyword arguments.
@type field: str
@param field: name of the database field.
It should belong to the database table defined in the constructor.
"""
self.data.extjs_fields[field] = kwargs
def merge_fields(self, *fields, **kwargs):
"""Merge fields in a composite field corresponding to
an Ext.form.CompositeField widget.
Each field is identified by its database field name.
"""Merge fields in a CompositeField.
The keyword arguments contains the configuration options of
the Ext.form.CompositeField widget.
@note:
- Each C{field} is identified by its database field name.
- C{field} should belong to the database table defined in the constructor.
- The first C{field} is the main field of the C{CompositeField}.
- The keyword arguments contains the configuration options of
the C{Ext.form.CompositeField} widget.
"""
......
""" Author: R. Le Gac
""" the form modifier
@author: R. Le Gac
"""
import copy
......@@ -13,11 +15,14 @@ MODIFIER_FORMS = 'modifier_forms'
def configure_forms(db, **extjs):
"""Helper functions to apply to all grid widgets a set of
configuration options. Useful to set plugins for example.
"""Apply to all form widgets the same configuration options.
Useful to set plugins in one go, for example.
@type db: gluon.dal.DAL
@param db:
The keyword arguments contain the configuration options for
the Ext.form.FormPanel.
@note: The keyword arguments define values for the Ext JS configuration
options of he C{Ext.form.FormPanel} class.
"""
for tablename in db.tables:
......@@ -28,12 +33,41 @@ def configure_forms(db, **extjs):
class FormModifier(Modifier):
"""Helper tool to customise the form widget associated to a table.
"""Modifier to customise the form widget associated to a database table.
"""
def __init__(self, tablename):
"""Initialise the modifier persistent data.
"""Initialize the form modifier associated to the database
table C{tablename}.
The data structure of the form modifier can be access
outside the class:
>>> p = PluginManager('dbui')
>>> modifier = p.dbui['modifier_forms'][tablename]
or internally via the attribute C{data}.
The keys of the C{data} structure are:
- C{extjs} (dict) Ext JS configuration options for the form widget.
- C{field_sets} (list of Storage) each C{Storage} defined a
C{FieldSets}. It has two keys C{fields} and C{extjs}.
The former is a list of field names belonging to the table
defined in the constructor. The latter is a dictionary with
the configuration options of the C{Ext.form.FieldSet} widget.
- C{hidden_fields} (list) list of field names to be hidden in
the form. The fields have to belong to the table defined in
the constructor.
- C{mapper} (None or function) reference to the function used
to organize the C{FieldSet} in C{Tabs}, for example.
@type tablename: str
@param tablename: name of the database table
"""
Modifier.__init__(self, MODIFIER_FORMS, tablename)
......@@ -47,7 +81,9 @@ class FormModifier(Modifier):
def link_comboboxes(self, **kwargs):
"""Link to Ext.form.ComboBox of the form in such a way that
""" TO BE MODIFIED
Link to Ext.form.ComboBox of the form in such a way that
the value available for the second depend on the value selected
in the first one. This first field is the master while the second one
is the slave.
......@@ -154,14 +190,14 @@ class FormModifier(Modifier):
def merge_fields(self, *fields, **kwargs):
"""Merge fields in a field set corresponding to
an Ext.form.FieldSet widget.
"""Merge fields in a L{FieldSet} corresponding to
an C{Ext.form.FieldSet} widget.
Each field is either a string identifying database field by its name
or an instance of the modifier.Widget class (Spacer, ....).
Each C{field} is either a string identifying the database field by its name
or an instance of the Ext JS configurator like the C{Spacer}.
The keyword argument contains the configuration options of
the Ext.form.FieldSet widget.
The keyword argument define values for the configuration options of
the C{Ext.form.FieldSet} widget.
"""
# by default the field occupies all the field set space
......@@ -197,7 +233,7 @@ class FormModifier(Modifier):
field/fieldset. The function return a dictionary with the structure of
panels embedded in the form an the fields they contained.
Example of mapper can be found in the mapper module.
Example of mapper can be found in the L{mapper} module.
"""
self.data.mapper = func
\ No newline at end of file
""" Author: R. Le Gac
"""the grid modifier.
@author: R. Le Gac
"""
import copy
......@@ -16,15 +18,15 @@ MSG_TPL_MISSING = 'configuration option tpl is missing in extjs'
def configure_grids(db, **extjs):
"""Helper functions to configure all grid widgets with the same
configuration options. Useful to set plugins for example.
"""Apply to all grid widgets the same configuration options.
Useful to set plugins in one go, for example.
@type db: gluon.dal.DAL
@param db:
The keyword arguments contain the configuration options for
the Ext.grid.GridPanel.
This tool can be use to set grid plugins for all grids in one go:
> configure_grids(db, plugins=['pGridRowEditorContextMenu'])
"""
for tablename in db.tables:
gm = GridModifier(tablename)
......@@ -36,12 +38,42 @@ class GridModifierException(BaseException): pass
class GridModifier(Modifier):
"""Helper tool to customize the grid widget associated to a table.
"""Modifier to customize the grid widget associated to a table.
"""
def __init__(self, tablename):
"""Initialize the modifier persistent data.
"""Initialize the grid modifier associated to the database
table C{tablename}.
The data structure of the grid modifier can be access
outside the class:
>>> p = PluginManager('dbui')
>>> modifier = p.dbui['modifier_grids'][tablename]
or internally via the attribute C{data}.
The keys of the C{data} structure are:
- C{extjs} (dict) Ext JS configuration options for the grid widget.
- C{configure_columns} (dict) the Ext JS configuration options for
the C{Ext.grid.Column} widget. The column is identify by its
C{fieldname}.
- C{delete_columns} (list)
- C{grid_filters} (storage)
- C{hidden_columns} (list)
- C{row_numbering} (bool)
- C{template_columns} (list
@type tablename: str
@param tablename: name of the database table
"""
Modifier.__init__(self, MODIFIER_GRIDS, tablename)
......@@ -58,7 +90,9 @@ class GridModifier(Modifier):
def add_column(self, ktable, kfield, position=0, extjs={}):
"""Add a column displaying the database field kfield of the
"""NOT YET IMPLEMENTED
Add a column displaying the database field kfield of the
foreign table ktable.
The keyword argument position is a number defining where the
......@@ -71,18 +105,24 @@ class GridModifier(Modifier):
def configure_column(self, fieldname, **kwargs):
"""Modified the model of a given column.
"""Modify the configuration options for a given column.
Each column is identified by its database field name.
This method is useful to fine tune column width for example.
The keyword arguments defines the configuration option
of the underlying Ext.grid.Column
@type fieldname: str
@param fieldname: name of a database field.
It has to belong to the table defined in the constructor.
The keyword arguments defines the configuration options
for the associated C{Ext.grid.Column} widget.
"""
self.data.configure_columns[fieldname] = kwargs
def delete_columns(self, *fields):
"""Delete the columns in the Ext.grid.GridPanel widget.
"""Delete the columns in the C{Ext.grid.GridPanel} widget.
Each column is identified by its database field name.
"""
......@@ -92,7 +132,7 @@ class GridModifier(Modifier):
def hide_columns(self, *fields):
"""Hide the columns list in arguments
"""Hide the columns in the C{Ext.grid.GridPanel} widget.
Each column is identified by its database field name.
"""
......@@ -102,30 +142,36 @@ class GridModifier(Modifier):
def merge_columns(self, *fields, **kwargs):
"""Merge columns in a single template column Ext.grid.TemplateColumn.
Each column is identified by its database field name.
"""Merge several fields in a single C{TemplateColumn}.
The TemplateColumn is rendered by the C{Ext.grid.TemplateColumn}.
Each field is identified by its database field name.
The new column should have an header and a template defining how the
merge field are displayed. These two configuration options of the
Ext.grid.Templatecolumn have to be defined via the keyword argument
extjs. The corresponding key of this dictionary are header and tpl.
@keyword header: (str) the header of the TemplateColumn
The syntax of the template is rather tricky to manipulate.
see the documentation of Ext.XTemplate constructor.
There is some limitation when defining the template in python.
For example the use of the template member function is impossible.
In the template, database fields are identified using the CapWord
syntax: TablenameFieldName. The first letter of the tablename and field
name are in upper case while all the other letters are in lower case.
@keyword tpl: (list) the template defining how fields are displayed
in the TemplateColumn.
- The syntax of the template is is defined in the documentation
of C{Ext.XTemplate} constructor.
- There is some limitation when defining the template in python,
namely the use of the template member function.
- Database fields are identified using the C{CapWord} syntax:
C{TablenameFieldname}. It works for standard and reference fields.
- HTML balises are understood.
- Example of a template list::
When the keyword argument autohide is set to true the columns in field
are hidden.
tpl = ['<b>{PeopleLast_name}</b><br>',
'{PeopleFirst_name}<br>',
'<tpl if={PeoplePhone_number}>{PeoplePhone_number}</tpl>']
The keyword argument position is a number defining where the
column will be insert. The first column is at 0.
@keyword autohide: (bool) hide the columns associated to the fields
used in the TemplateColumn when set to C{True}.
@keyword position: (int) is a number defining where the
column will be inserted in the grid widget.
The first column is at 0.
The keyword arguments extjs defines the configuration option
of the underlying Ext.grid.TemplateColumn
@keyword extjs: (dict) contains the Ext JS configuration options
of the C{Ext.grid.TemplateColumn}.
"""
keywords = ['autohide', 'position']
......@@ -152,28 +198,23 @@ class GridModifier(Modifier):
def append_filter(self, filter, **kwargs):
"""Append a filter associated to the grid.
The widget associated to each filter is a field, comboBox, dataField,..
They are grouped in a Ext.form.Fieldset appearing in a panel on the
right side of the grid.
"""Append a filter to the GridFilter.
The filter will be add to the GridFilter which is a FieldSet
located on the right side of the GridPanel.
A filter corresponds to a field in the FieldSet.
A filter is define by a tuple containing three columns:
- a string with the database field name
- a string with the operator. Valid operator are defined in
the method dbsvc._encode_query
- a string with a comment for the tool tip
@type filter: tuple
@param filter: A filter is defined by a tuple containing three strings:
- The database field name. The field has to
belong to the database table defined in the constructor.
However, the more elaborate syntax, C{'table2.field1'},