[doc/book] various content fixes stable
authorAurelien Campeas <aurelien.campeas@logilab.fr>
Fri, 23 Apr 2010 20:06:04 +0200
branchstable
changeset 5400 b7ab099b128a
parent 5399 03c641ae00a6
child 5401 547911327475
[doc/book] various content fixes
doc/book/en/admin/additional-tips.rst
doc/book/en/annexes/rql/intro.rst
doc/book/en/devrepo/cubes/cc-newcube.rst
doc/book/en/devrepo/datamodel/define-workflows.rst
doc/book/en/devrepo/datamodel/definition.rst
doc/book/en/devrepo/devcore/dbapi.rst
doc/book/en/devrepo/devcore/reqbase.rst
doc/book/en/devrepo/entityclasses/data-as-objects.rst
doc/book/en/devweb/controllers.rst
doc/book/en/devweb/css.rst
doc/book/en/devweb/form.rst
doc/book/en/devweb/index.rst
doc/book/en/devweb/js.rst
doc/book/en/devweb/property.rst
doc/book/en/devweb/publisher.rst
doc/book/en/devweb/views/primary.rst
doc/book/en/intro/concepts.rst
--- a/doc/book/en/admin/additional-tips.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/admin/additional-tips.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -1,40 +1,37 @@
 
 .. _Additional Tips:
 
-Additional Tips
----------------
-
-Here are some additional tips as far as administration of a CubicWeb is concerned.
+Backups (mostly with postgresql)
+--------------------------------
 
-Backup, backup, backup
-``````````````````````
+It is always a good idea to backup. If your system does not do that,
+you should set it up. Note that whenever you do an upgrade,
+`cubicweb-ctl` offers you to backup your database.  There are a number
+of ways for doing backups.
 
-It is always a good idea to backup. If your system does not do that, you should
-set it up. Note that whenever you do an upgrade, `cubicweb-ctl` offers you to
-backup your database.  There are a number of ways for doing backups. Before you
+Using postgresql (and only that)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Before you
 go ahead, make sure the following permissions are correct ::
 
    # chgrp postgres /var/lib/cubicweb/backup
-
    # chmod g+ws /var/lib/cubicweb/backup
-
    # chgrp postgres /etc/cubicweb.d/*<instance>*/sources
-
    # chmod g+r /etc/cubicweb.d/*<instance>*/sources
 
-**Classic way on PostgreSQL server**
-
 Simply use the pg_dump in a cron installed for `postgres` user on the database server::
 
     # m h  dom mon dow   command
     0 2 * * * pg_dump -Fc --username=cubicweb --no-owner <instance> > /var/backups/<instance>-$(date '+%Y-%m-%d_%H:%M:%S').dump
 
-**CubicWeb way**
+Using :command:`cubicweb-ctl db-dump`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The CubicWeb way is to use the `db-dump` command. For that, you have to put
-your passwords in a user-only-readable file at the home directory of root user.
-The file is `.pgpass` (`chmod 0600`), in this case for a socket run connection
-to PostgreSQL ::
+The CubicWeb way is to use the :command:`db-dump` command. For that,
+you have to put your passwords in a user-only-readable file at the
+home directory of root user.  The file is `.pgpass` (`chmod 0600`), in
+this case for a socket run connection to PostgreSQL ::
 
     /var/run/postgresql:5432:<instance>:<database user>:<database password>
 
@@ -45,7 +42,9 @@
     # m h  dom mon dow   command
     0 2 * * * cubicweb-ctl db-dump <instance>
 
-**The automated sysadmin way**
+
+Backup ninja
+~~~~~~~~~~~~
 
 You can use a combination `backup-ninja`_ (which has a postgres script in the
 example directory), `backuppc`)_ (for versionning).
@@ -56,3 +55,10 @@
 .. _`here` : http://www.postgresql.org/docs/current/static/libpq-pgpass.html
 .. _`backup-ninja` : https://labs.riseup.net/code/projects/show/backupninja/
 .. _`backuppc` : http://backuppc.sourceforge.net/
+
+.. warning::
+
+  Remember that these indications will fail you whenever you use
+  another database backend than postgres. Also it does properly handle
+  externally managed data such as files (using the Bytes File System
+  Storage).
--- a/doc/book/en/annexes/rql/intro.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/annexes/rql/intro.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -1,3 +1,5 @@
+
+.. _rql_intro:
 
 Introduction
 ------------
--- a/doc/book/en/devrepo/cubes/cc-newcube.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devrepo/cubes/cc-newcube.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -3,9 +3,10 @@
 
 Let's start by creating the cube environment in which we will develop ::
 
-  cd ~/hg
+  cd ~/cubes
   # use cubicweb-ctl to generate a template for the cube
-  cubicweb-ctl newcube mycube  # will ask some questions, most with nice default
+  # will ask some questions, most with nice default
+  cubicweb-ctl newcube mycube
   # makes the cube source code managed by mercurial
   cd mycube
   hg init
@@ -16,11 +17,12 @@
 returned by ``cubicweb-ctl list`` in the section *Available cubes*,
 and if it is not the case please refer to :ref:`ConfigurationEnv`.
 
-To reuse an existing cube, add it to the list named ``__use__`` and defined in
-:file:`__pkginfo__.py`.  This variable is used for the instance packaging
-(dependencies handled by system utility tools such as APT) and the usable cubes
-at the time the base is created (import_erschema('MyCube') will not properly
-work otherwise).
+To reuse an existing cube, add it to the list named
+``__depends_cubes__`` and defined in :file:`__pkginfo__.py`.  This
+variable is used for the instance packaging (dependencies handled by
+system utility tools such as APT) and the usable cubes at the time the
+base is created (import_erschema('MyCube') will not properly work
+otherwise).
 
 .. note::
 
--- a/doc/book/en/devrepo/datamodel/define-workflows.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devrepo/datamodel/define-workflows.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -2,22 +2,23 @@
 
 .. _Workflow:
 
-Define a Workflow
-=================
+Defining a Workflow
+===================
 
 General
 -------
 
 A workflow describes how certain entities have to evolve between
-different states. Hence we have a set of states, and a "transition graph",
-i.e. a set of possible transitions from one state to another state.
+different states. Hence we have a set of states, and a "transition
+graph", i.e. a set of possible transitions from one state to another
+state.
 
 We will define a simple workflow for a blog, with only the following
 two states: `submitted` and `published`. So first, we create a simple
-*CubicWeb* instance in ten minutes (see :ref:`BlogFiveMinutes`).
+|cubicweb| instance in five minutes (see :ref:`BlogFiveMinutes`).
 
-Set-up a workflow
------------------
+Setting up a workflow
+---------------------
 
 We want to create a workflow to control the quality of the BlogEntry
 submitted on the instance. When a BlogEntry is created by a user
@@ -50,13 +51,13 @@
       ...
 
 
-Create states, transitions and group permissions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Creating states, transitions and group permissions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The ``postcreate.py`` script is executed in a special environment, adding
-several *CubicWeb* primitives that can be used.
+The :mod:`postcreate` script is executed in a special environment,
+adding several |cubicweb| primitives that can be used.
 
-They are all defined in the ``class ServerMigrationHelper``.
+They are all defined in the :class:`ServerMigrationHelper` class.
 We will only discuss the methods we use to create a workflow in this example.
 
 A workflow is a collection of entities of type ``State`` and of type
@@ -115,8 +116,9 @@
   checkpoint()
 
 .. note::
-  Do not forget to add the `_()` in front of all states and transitions names while creating
-  a workflow so that they will be identified by the i18n catalog scripts.
+  Do not forget to add the `_()` in front of all states and
+  transitions names while creating a workflow so that they will be
+  identified by the i18n catalog scripts.
 
 In addition to the user groups (one of which the user needs to belong
 to), we could have added a RQL condition.  In this case, the user can
--- a/doc/book/en/devrepo/datamodel/definition.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devrepo/datamodel/definition.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -50,7 +50,8 @@
 
 Also |yams| supports the notions of:
 
-* entity inheritance,
+* entity inheritance (quite experimental yet, and completely
+  undocumented),
 * relation type: that is, relationships can be established over a set
   of couple of entity types (henre the distinction made between
   `RelationType` and `RelationDefinition` below)
--- a/doc/book/en/devrepo/devcore/dbapi.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devrepo/devcore/dbapi.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -9,7 +9,7 @@
 
 .. sourcecode:: python
 
-  execute(rqlstring, args=None, build_descr=True)
+   execute(rqlstring, args=None, build_descr=True)
 
 :rqlstring: the RQL query to execute (unicode)
 :args: if the query contains substitutions, a dictionary containing the values to use
@@ -33,6 +33,8 @@
 handled by the request object. You should not have to access it directly, but
 use the `execute` method directly available on the request, eg:
 
+.. sourcecode:: python
+
    rset = self._cw.execute(rqlstring, kwargs)
 
 Similarly, on the server side (eg in hooks), there is no db-api connexion (since
@@ -40,8 +42,8 @@
 of the session object.
 
 
-Important note about proper usage of .execute
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Proper usage of `.execute`
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Let's say you want to get T which is in configuration C, this translates to:
 
@@ -110,7 +112,7 @@
 
 The whole cursor API is developped below.
 
-.. note:
+.. note::
 
   In practice we use the `.execute` method on the _cw object of
   appobjects. Usage of other methods is quite rare.
--- a/doc/book/en/devrepo/devcore/reqbase.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devrepo/devcore/reqbase.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -1,32 +1,40 @@
 Request and ResultSet methods
 -----------------------------
 
-Those are methods you'll find on both request objects and on repository session:
+Those are methods you'll find on both request objects and on
+repository session.
+
+Request methods
+~~~~~~~~~~~~~~~
+
+`URL handling`:
+
+* `build_url(*args, **kwargs)`, returns an absolute URL based on the
+  given arguments. The *controller* supposed to handle the response,
+  can be specified through the first positional parameter (the
+  connection is theoretically done automatically :).
 
-:URL handling:
-  * `build_url(*args, **kwargs)`, returns an absolute URL based on the
-    given arguments. The *controller* supposed to handle the response,
-    can be specified through the first positional parameter (the
-    connection is theoretically done automatically :).
-:Data formatting:
-  * `format_date(date, date_format=None, time=False)` returns a string for a
-    date time according to instance's configuration
+`Data formatting`:
+
+* `format_date(date, date_format=None, time=False)` returns a string for a
+  date time according to instance's configuration
 
-  * `format_time(time)` returns a string for a date time according to
-    instance's configuration
+* `format_time(time)` returns a string for a date time according to
+  instance's configuration
 
-:And more...:
+`And more...`:
 
-  * `tal_render(template, variables)`, renders a precompiled page template with
-    variables in the given dictionary as context
+* `tal_render(template, variables)`, renders a precompiled page template with
+  variables in the given dictionary as context
 
 
-Result set methods:
+Result set methods
+~~~~~~~~~~~~~~~~~~
 
-  * `get_entity(row, col)`, returns the entity corresponding to the data position
-    in the *result set*
+* `get_entity(row, col)`, returns the entity corresponding to the data position
+  in the *result set*
 
-  * `complete_entity(row, col, skip_bytes=True)`, is equivalent to `get_entity` but
-    also call the method `complete()` on the entity before returning it
+* `complete_entity(row, col, skip_bytes=True)`, is equivalent to `get_entity` but
+  also call the method `complete()` on the entity before returning it
 
 
--- a/doc/book/en/devrepo/entityclasses/data-as-objects.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devrepo/entityclasses/data-as-objects.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -14,53 +14,53 @@
   the same name on instances (entities instances list)
 
 
-:Formatting and output generation:
+`Formatting and output generation`:
 
-  * `view(__vid, __registry='views', **kwargs)`, applies the given view to the entity
-    (and returns an unicode string)
+* `view(__vid, __registry='views', **kwargs)`, applies the given view to the entity
+  (and returns an unicode string)
 
-  * `absolute_url(*args, **kwargs)`, returns an absolute URL to access the primary view
-    of an entity
+* `absolute_url(*args, **kwargs)`, returns an absolute URL to access the primary view
+  of an entity
 
-  * `rest_path()`, returns a relative REST URL to get the entity
+* `rest_path()`, returns a relative REST URL to get the entity
 
-  * `printable_value(attr, value=_marker, attrtype=None, format='text/html', displaytime=True)`,
-    returns a string enabling the display of an attribute value in a given format
-    (the value is automatically recovered if necessary)
+* `printable_value(attr, value=_marker, attrtype=None, format='text/html', displaytime=True)`,
+  returns a string enabling the display of an attribute value in a given format
+  (the value is automatically recovered if necessary)
 
-:Data handling:
+`Data handling`:
 
-  * `as_rset()`, converts the entity into an equivalent result set simulating the
-     request `Any X WHERE X eid _eid_`
+* `as_rset()`, converts the entity into an equivalent result set simulating the
+   request `Any X WHERE X eid _eid_`
 
-  * `complete(skip_bytes=True)`, executes a request that recovers at
-    once all the missing attributes of an entity
+* `complete(skip_bytes=True)`, executes a request that recovers at
+  once all the missing attributes of an entity
 
-  * `get_value(name)`, returns the value associated to the attribute name given
-    in parameter
+* `get_value(name)`, returns the value associated to the attribute name given
+  in parameter
 
-  * `related(rtype, role='subject', limit=None, entities=False)`,
-    returns a list of entities related to the current entity by the
-    relation given in parameter
+* `related(rtype, role='subject', limit=None, entities=False)`,
+  returns a list of entities related to the current entity by the
+  relation given in parameter
 
-  * `unrelated(rtype, targettype, role='subject', limit=None)`,
-    returns a result set corresponding to the entities not (yet)
-    related to the current entity by the relation given in parameter
-    and satisfying its constraints
+* `unrelated(rtype, targettype, role='subject', limit=None)`,
+  returns a result set corresponding to the entities not (yet)
+  related to the current entity by the relation given in parameter
+  and satisfying its constraints
 
-  * `set_attributes(**kwargs)`, updates the attributes list with the corresponding
-    values given named parameters
+* `set_attributes(**kwargs)`, updates the attributes list with the corresponding
+  values given named parameters
 
-  * `set_relations(**kwargs)`, add relations to the given object. To
-     set a relation where this entity is the object of the relation,
-     use `reverse_<relation>` as argument name.  Values may be an
-     entity, a list of entities, or None (meaning that all relations of
-     the given type from or to this object should be deleted).
+* `set_relations(**kwargs)`, add relations to the given object. To
+   set a relation where this entity is the object of the relation,
+   use `reverse_<relation>` as argument name.  Values may be an
+   entity, a list of entities, or None (meaning that all relations of
+   the given type from or to this object should be deleted).
 
-  * `copy_relations(ceid)`, copies the relations of the entities having the eid
-    given in the parameters on the current entity
+* `copy_relations(ceid)`, copies the relations of the entities having the eid
+  given in the parameters on the current entity
 
-  * `delete()` allows to delete the entity
+* `delete()` allows to delete the entity
 
 
 The :class:`AnyEntity` class
@@ -80,42 +80,42 @@
 
 .. _`Dublin Core`: http://dublincore.org/
 
-:Standard meta-data (Dublin Core):
+`Standard meta-data (Dublin Core)`:
 
-  * `dc_title()`, returns a unicode string corresponding to the
-    meta-data `Title` (used by default is the first non-meta attribute
-    of the entity schema)
+* `dc_title()`, returns a unicode string corresponding to the
+  meta-data `Title` (used by default is the first non-meta attribute
+  of the entity schema)
 
-  * `dc_long_title()`, same as dc_title but can return a more
-    detailed title
+* `dc_long_title()`, same as dc_title but can return a more
+  detailed title
 
-  * `dc_description(format='text/plain')`, returns a unicode string
-    corresponding to the meta-data `Description` (looks for a
-    description attribute by default)
+* `dc_description(format='text/plain')`, returns a unicode string
+  corresponding to the meta-data `Description` (looks for a
+  description attribute by default)
 
-  * `dc_authors()`, returns a unicode string corresponding to the meta-data
-    `Authors` (owners by default)
+* `dc_authors()`, returns a unicode string corresponding to the meta-data
+  `Authors` (owners by default)
 
-  * `dc_creator()`, returns a unicode string corresponding to the
-    creator of the entity
+* `dc_creator()`, returns a unicode string corresponding to the
+  creator of the entity
 
-  * `dc_date(date_format=None)`, returns a unicode string corresponding to
-    the meta-data `Date` (update date by default)
+* `dc_date(date_format=None)`, returns a unicode string corresponding to
+  the meta-data `Date` (update date by default)
 
-  * `dc_type(form='')`, returns a string to display the entity type by
-    specifying the preferred form (`plural` for a plural form)
+* `dc_type(form='')`, returns a string to display the entity type by
+  specifying the preferred form (`plural` for a plural form)
 
-  * `dc_language()`, returns the language used by the entity
+* `dc_language()`, returns the language used by the entity
 
 
-:Misc methods:
+`Misc methods`:
 
-  * `after_deletion_path`, return (path, parameters) which should be
-     used as redirect information when this entity is being deleted
+* `after_deletion_path`, return (path, parameters) which should be
+   used as redirect information when this entity is being deleted
 
-  * `pre_web_edit`, callback called by the web editcontroller when an
-    entity will be created/modified, to let a chance to do some entity
-    specific stuff (does nothing by default)
+* `pre_web_edit`, callback called by the web editcontroller when an
+  entity will be created/modified, to let a chance to do some entity
+  specific stuff (does nothing by default)
 
 Inheritance
 -----------
@@ -123,14 +123,21 @@
 When describing a data model, entities can inherit from other entities as is
 common in object-oriented programming.
 
-You have the possibility to adapt some entity attributes, as follow:
+You have the possibility to redefine whatever pleases you, as follow:
 
 .. sourcecode:: python
 
     from cubes.OTHER_CUBE import entities
+
     class EntityExample(entities.EntityExample):
+
         def dc_long_title(self):
             return '%s (%s)' % (self.name, self.description)
 
+The most specific entity definition will always the one used by the
+ORM. For instance, the new EntityExample above in mycube replaces the
+one in OTHER_CUBE. These types are stored in the `etype` section of
+the `vregistry`.
+
 Notice this is different than yams schema inheritance.
 
--- a/doc/book/en/devweb/controllers.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/controllers.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -10,24 +10,25 @@
 (loosely following the terminology of the MVC meta pattern).
 
 The following controllers are provided out-of-the box in CubicWeb. We
-list them by category.
+list them by category. They are all defined in
+(:mod:`cubicweb.web.views.basecontrollers`).
 
 `Browsing`:
 
-* the View controller (web/views/basecontrollers.py) is associated
-  with most browsing actions within a CubicWeb application: it always
-  instantiates a `main template` and lets the ResultSet/Views dispatch
+* the View controlleris associated with most browsing actions within a
+  CubicWeb application: it always instantiates a
+  :ref:`the_main_template` and lets the ResultSet/Views dispatch
   system build up the whole content; it handles ObjectNotFound and
   NoSelectableObject errors that may bubble up to its entry point, in
   an end-user-friendly way (but other programming errors will slip
   through)
 
-* the JSon controller (web/views/basecontrollers.py) provides services
-  for Ajax calls, typically using JSON as a serialization format for
-  input, and sometimes using either JSON or XML for output;
+* the JSon controller (same module) provides services for Ajax calls,
+  typically using JSON as a serialization format for input, and
+  sometimes using either JSON or XML for output;
 
-* the Login/Logout controllers (web/views/basecontrollers.py) make
-  effective user login or logout requests
+* the Login/Logout controllers make effective user login or logout
+  requests
 
 `Edition`:
 
@@ -35,12 +36,12 @@
   operations in response to a form being submitted; it works in close
   association with the Forms, to which it delegates some of the work
 
-* the Form validator controller (web/views/basecontrollers.py)
-  provides form validation from Ajax context, using the Edit
-  controller, to implement the classic form handling loop (user edits,
-  hits 'submit/apply', validation occurs server-side by way of the
-  Form validator controller, and the UI is decorated with failure
-  information, either global or per-field , until it is valid)
+* the Form validator controller provides form validation from Ajax
+  context, using the Edit controller, to implement the classic form
+  handling loop (user edits, hits 'submit/apply', validation occurs
+  server-side by way of the Form validator controller, and the UI is
+  decorated with failure information, either global or per-field ,
+  until it is valid)
 
 `Other`:
 
@@ -88,8 +89,9 @@
 Editing control
 ~~~~~~~~~~~~~~~~
 
-Re-requisites: the parameters related to entities to edit are
-specified as follows ::
+.. XXX this look obsolete
+
+The parameters related to entities to edit are specified as follows ::
 
   <field name>:<entity eid>
 
--- a/doc/book/en/devweb/css.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/css.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -5,9 +5,9 @@
 Conventions
 ~~~~~~~~~~~
 
-XXX external_resources variable
-    naming convention
-    request.add_css
+.. XXX external_resources variable
+..    naming convention
+..    request.add_css
 
 
 Extending / overriding existing styles
@@ -26,4 +26,5 @@
 
 CubicWeb stylesheets
 ~~~~~~~~~~~~~~~~~~~~
-XXX explain diffenrent files and main classes
+
+.. XXX explain diffenrent files and main classes
--- a/doc/book/en/devweb/form.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/form.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -14,8 +14,8 @@
 
 The **field** should be used according to the type of what you want to edit.
 E.g. if you want to edit some date, you'll have to use the
-:class:`~cubicweb.web.formfields.DateField`. Then you can choose among multiple
-widgets to edit it, for instance :class:`~cubicweb.web.formwidgets.TextInput` (a
+:class:`cubicweb.web.formfields.DateField`. Then you can choose among multiple
+widgets to edit it, for instance :class:`cubicweb.web.formwidgets.TextInput` (a
 bare text field), :class:`~cubicweb.web.formwidgets.DateTimePicker` (a simple
 calendar) or even :class:`~cubicweb.web.formwidgets.JQueryDatePicker` (the JQuery
 calendar).  You can of course also write your own widget.
@@ -129,28 +129,28 @@
 
 .. sourcecode:: python
 
-    class SendMailController(Controller):
-        __regid__ = 'sendmail'
-        __select__ = authenticated_user() & match_form_params('recipient', 'mailbody', 'subject')
+   class SendMailController(Controller):
+       __regid__ = 'sendmail'
+       __select__ = authenticated_user() & match_form_params('recipient', 'mailbody', 'subject')
 
-        def publish(self, rset=None):
-            body = self._cw.form['mailbody']
-            subject = self._cw.form['subject']
-            eids = self._cw.form['recipient']
-            # eids may be a string if only one recipient was specified
-            if isinstance(eids, basestring):
-                rset = self._cw.execute('Any X WHERE X eid %(x)s', {'x': eids})
-            else:
-                rset = self._cw.execute('Any X WHERE X eid in (%s)' % (','.join(eids)))
-            recipients = list(rset.entities())
-            msg = format_mail({'email' : self._cw.user.get_email(),
-                               'name' : self._cw.user.dc_title()},
-                              recipients, body, subject)
-            if not self._cw.vreg.config.sendmails([(msg, recipients]):
-                msg = self._cw._('could not connect to the SMTP server')
-            else:
-                msg = self._cw._('emails successfully sent')
-            raise Redirect(self._cw.build_url(__message=msg))
+       def publish(self, rset=None):
+           body = self._cw.form['mailbody']
+           subject = self._cw.form['subject']
+           eids = self._cw.form['recipient']
+           # eids may be a string if only one recipient was specified
+           if isinstance(eids, basestring):
+               rset = self._cw.execute('Any X WHERE X eid %(x)s', {'x': eids})
+           else:
+               rset = self._cw.execute('Any X WHERE X eid in (%s)' % (','.join(eids)))
+           recipients = list(rset.entities())
+           msg = format_mail({'email' : self._cw.user.get_email(),
+                              'name' : self._cw.user.dc_title()},
+                             recipients, body, subject)
+           if not self._cw.vreg.config.sendmails([(msg, recipients]):
+               msg = self._cw._('could not connect to the SMTP server')
+           else:
+               msg = self._cw._('emails successfully sent')
+           raise Redirect(self._cw.build_url(__message=msg))
 
 
 The entry point of a controller is the publish method. In that case we simply get
--- a/doc/book/en/devweb/index.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/index.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -17,5 +17,5 @@
    form
    facets
    internationalization
-   property
+..   property
    httpcaching
--- a/doc/book/en/devweb/js.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/js.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -20,7 +20,7 @@
 It is good practice to name cube specific js files after the name of
 the cube, like this : 'cube.mycube.js', so as to avoid name clashes.
 
-XXX external_resources variable (which needs love)
+.. XXX external_resources variable (which needs love)
 
 CubicWeb javascript API
 ~~~~~~~~~~~~~~~~~~~~~~~
@@ -319,8 +319,8 @@
 
 
 
-XXX reloadComponent
-XXX userCallback / user_callback
+.. XXX reloadComponent
+.. XXX userCallback / user_callback
 
 Javascript library: overview
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- a/doc/book/en/devweb/property.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/property.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -1,12 +1,13 @@
 The property mecanism
 ---------------------
-XXX CWProperty and co
+
+.. XXX CWProperty and co
 
 
 Property API
 ~~~~~~~~~~~~
-XXX feed me
+.. XXX feed me
 
 Registering and using your own property
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-XXX feed me
+.. XXX feed me
--- a/doc/book/en/devweb/publisher.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/publisher.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -11,6 +11,8 @@
 ``cubicweb.etwist.server.CubicWebRootResource.render_request`` is the
 real entry point.
 
+.. _`twisted`: http://twistedmatrix.com/trac/
+
 What main_publish does:
 
 * get a controller id and a result set from the path (this is actually
--- a/doc/book/en/devweb/views/primary.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/devweb/views/primary.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -3,8 +3,6 @@
 The Primary View
 -----------------
 
-(:mod:`cubicweb.web.views.primary`)
-
 By default, *CubicWeb* provides a view that fits every available
 entity type. This is the first view you might be interested in
 modifying. It is also one of the richest and most complex.
@@ -15,6 +13,8 @@
 This view is supposed to render a maximum of informations about the
 entity.
 
+It lives in the :mod:`cubicweb.web.views.primary` module.
+
 .. _primary_view_layout:
 
 Layout
@@ -209,21 +209,23 @@
 
 We continue along the basic tutorial :ref:`tuto_blog`.
 
-If you want to change the way a ``BlogEntry`` is displayed, just override
-the method ``cell_call()`` of the view ``primary`` in ``BlogDemo/views.py``.
+If you want to change the way a ``BlogEntry`` is displayed, just
+override the method ``cell_call()`` of the view ``primary`` in
+``BlogDemo/views.py``.
 
 .. sourcecode:: python
 
-  from cubicweb.selectors import implements
-  from cubicweb.web.views.primary import Primaryview
+   from cubicweb.selectors import implements
+   from cubicweb.web.views.primary import Primaryview
+
+   class BlogEntryPrimaryView(PrimaryView):
+     __select__ = PrimaryView.__select__ & implements('BlogEntry')
 
-  class BlogEntryPrimaryView(PrimaryView):
-    __select__ = PrimaryView.__select__ & implements('BlogEntry')
+       def render_entity_attributes(self, entity):
+           self.w(u'<p>published on %s</p>' %
+                  entity.publish_date.strftime('%Y-%m-%d'))
+           super(BlogEntryPrimaryView, self).render_entity_attributes(entity)
 
-      def render_entity_attributes(self, entity):
-          self.w(u'<p>published on %s</p>' %
-                 entity.publish_date.strftime('%Y-%m-%d'))
-          super(BlogEntryPrimaryView, self).render_entity_attributes(entity)
 
 The above source code defines a new primary view for
 ``BlogEntry``. The `id` class attribute is not repeated there since it
--- a/doc/book/en/intro/concepts.rst	Fri Apr 23 17:01:45 2010 +0200
+++ b/doc/book/en/intro/concepts.rst	Fri Apr 23 20:06:04 2010 +0200
@@ -16,8 +16,8 @@
 -----
 
 A cube is a software component made of three parts: its data model
-(:file:`schema`), its logic (:file:`entities`) and its user interface
-(:file:`views`).
+(:mod:`schema`), its logic (:mod:`entities`) and its user interface
+(:mod:`views`).
 
 A cube can use other cubes as building blocks and assemble them to provide a
 whole with richer functionnalities than its parts. The cubes `cubicweb-blog`_ and
@@ -70,7 +70,7 @@
 environment variable.
 
 
-.. Note::
+.. note::
 
   The term application is used to refer to "something that should do something as
   a whole", eg more like a project and so can refer to an instance or to a cube,
@@ -101,14 +101,14 @@
 repository side, you can for instance by-pass security checks, which isn't
 possible from client code.
 
-Some logic can be attached to events that happen in the repository, like
-creation of entities, deletion of relations, etc. This is used for example to
-send email notifications when the state of an object changes. See :ref:`HookIntro` below.
+Some logic can be attached to events that happen in the repository,
+like creation of entities, deletion of relations, etc. This is used
+for example to send email notifications when the state of an object
+changes. See :ref:`HookIntro` below.
 
 .. [1] not to be confused with a Mercurial repository or a Debian repository.
 .. _`Python Remote Objects`: http://pyro.sourceforge.net/
 
-
 .. _WebEngineIntro:
 
 Web Engine
@@ -237,11 +237,11 @@
 The RQL query language
 ----------------------
 
-**No need for a complicated ORM when you have a powerful data
-  manipulation language**
+No need for a complicated ORM when you have a powerful data
+manipulation language.
 
-All the persistent data in a |cubicweb| instance is retrieved and modified by
-using the Relation Query Language.
+All the persistent data in a |cubicweb| instance is retrieved and
+modified using RQL (see :ref:`rql_intro`).
 
 This query language is inspired by SQL but is on a higher level in order to
 emphasize browsing relations.
@@ -252,6 +252,8 @@
 
 The repository exposes a `db-api`_ like api but using the RQL instead of SQL.
 
+.. _`db-api`: http://www.python.org/dev/peps/pep-0249/
+
 You basically get a connection using :func:`cubicweb.dbapi.connect` , then
 get a cursor to call its `execute` method which will return result set for the
 given rql query.
@@ -336,8 +338,6 @@
 Hooks and operation are an essential building block of any moderately complicated
 cubicweb application.
 
-.. Note:
+.. note::
    RQL queries executed in hooks and operations are *unsafe* by default, e.g. the
    read and write security is deactivated unless explicitly asked.
-
-.. |cubicweb| replace:: *CubicWeb*