[doc] Restructure the documentation
authorChristophe de Vienne <christophe@unlish.com>
Thu, 08 Jan 2015 22:11:06 +0100
changeset 10491 c67bcee93248
parent 10490 76ab3c71aff2
child 10492 68c13e0c0fc5
[doc] Restructure the documentation * Create a new index file * Move the sphinx configuration files do the documentation root * Move book/README to dev/documenting.rst * Move book/mode_plan.py to tools/ * Move book/en/images to images * Move book/en/* to book/ * Move changelogs to changes/* * Adapt the Makefile * Add a title to the javascript api index Related to #4832808
.hgignore
doc/3.14.rst
doc/3.15.rst
doc/3.16.rst
doc/3.17.rst
doc/3.18.rst
doc/3.19.rst
doc/3.20.rst
doc/Makefile
doc/_static/cubicweb.png
doc/_static/logilab.png
doc/_static/sphinx-default.css
doc/_templates/layout.html
doc/_themes/cubicweb/layout.html
doc/_themes/cubicweb/static/cubicweb.css_t
doc/_themes/cubicweb/static/cubicweb.ico
doc/_themes/cubicweb/static/logo-cubicweb-small.svg
doc/_themes/cubicweb/static/logo-cubicweb.svg
doc/_themes/cubicweb/theme.conf
doc/book/MERGE_ME-tut-create-app.en.txt
doc/book/MERGE_ME-tut-create-gae-app.en.txt
doc/book/README
doc/book/additionnal_services/index.rst
doc/book/additionnal_services/undo.rst
doc/book/admin/additional-tips.rst
doc/book/admin/config.rst
doc/book/admin/create-instance.rst
doc/book/admin/cubicweb-ctl.rst
doc/book/admin/index.rst
doc/book/admin/instance-config.rst
doc/book/admin/ldap.rst
doc/book/admin/migration.rst
doc/book/admin/multisources.rst
doc/book/admin/pyro.rst
doc/book/admin/rql-logs.rst
doc/book/admin/setup-windows.rst
doc/book/admin/setup.rst
doc/book/admin/site-config.rst
doc/book/annexes/depends.rst
doc/book/annexes/docstrings-conventions.rst
doc/book/annexes/faq.rst
doc/book/annexes/index.rst
doc/book/annexes/mercurial.rst
doc/book/annexes/rql/Graph-ex.gif
doc/book/annexes/rql/debugging.rst
doc/book/annexes/rql/implementation.rst
doc/book/annexes/rql/index.rst
doc/book/annexes/rql/intro.rst
doc/book/annexes/rql/language.rst
doc/book/devrepo/cubes/available-cubes.rst
doc/book/devrepo/cubes/cc-newcube.rst
doc/book/devrepo/cubes/index.rst
doc/book/devrepo/cubes/layout.rst
doc/book/devrepo/dataimport.rst
doc/book/devrepo/datamodel/baseschema.rst
doc/book/devrepo/datamodel/define-workflows.rst
doc/book/devrepo/datamodel/definition.rst
doc/book/devrepo/datamodel/index.rst
doc/book/devrepo/datamodel/metadata.rst
doc/book/devrepo/devcore/dbapi.rst
doc/book/devrepo/devcore/index.rst
doc/book/devrepo/devcore/reqbase.rst
doc/book/devrepo/entityclasses/adapters.rst
doc/book/devrepo/entityclasses/application-logic.rst
doc/book/devrepo/entityclasses/data-as-objects.rst
doc/book/devrepo/entityclasses/index.rst
doc/book/devrepo/entityclasses/load-sort.rst
doc/book/devrepo/fti.rst
doc/book/devrepo/index.rst
doc/book/devrepo/migration.rst
doc/book/devrepo/profiling.rst
doc/book/devrepo/repo/hooks.rst
doc/book/devrepo/repo/index.rst
doc/book/devrepo/repo/notifications.rst
doc/book/devrepo/repo/sessions.rst
doc/book/devrepo/repo/tasks.rst
doc/book/devrepo/testing.rst
doc/book/devrepo/vreg.rst
doc/book/devweb/ajax.rst
doc/book/devweb/controllers.rst
doc/book/devweb/css.rst
doc/book/devweb/edition/dissection.rst
doc/book/devweb/edition/editcontroller.rst
doc/book/devweb/edition/examples.rst
doc/book/devweb/edition/form.rst
doc/book/devweb/edition/index.rst
doc/book/devweb/facets.rst
doc/book/devweb/httpcaching.rst
doc/book/devweb/index.rst
doc/book/devweb/internationalization.rst
doc/book/devweb/js.rst
doc/book/devweb/property.rst
doc/book/devweb/publisher.rst
doc/book/devweb/request.rst
doc/book/devweb/resource.rst
doc/book/devweb/rtags.rst
doc/book/devweb/searchbar.rst
doc/book/devweb/views/basetemplates.rst
doc/book/devweb/views/baseviews.rst
doc/book/devweb/views/boxes.rst
doc/book/devweb/views/breadcrumbs.rst
doc/book/devweb/views/idownloadable.rst
doc/book/devweb/views/index.rst
doc/book/devweb/views/primary.rst
doc/book/devweb/views/reledit.rst
doc/book/devweb/views/startup.rst
doc/book/devweb/views/table.rst
doc/book/devweb/views/urlpublish.rst
doc/book/devweb/views/views.rst
doc/book/devweb/views/wdoc.rst
doc/book/devweb/views/xmlrss.rst
doc/book/en/.static/cubicweb.png
doc/book/en/.static/logilab.png
doc/book/en/.static/sphinx-default.css
doc/book/en/.templates/layout.html
doc/book/en/MERGE_ME-tut-create-app.en.txt
doc/book/en/MERGE_ME-tut-create-gae-app.en.txt
doc/book/en/_themes/cubicweb/layout.html
doc/book/en/_themes/cubicweb/static/cubicweb.css_t
doc/book/en/_themes/cubicweb/static/cubicweb.ico
doc/book/en/_themes/cubicweb/static/logo-cubicweb-small.svg
doc/book/en/_themes/cubicweb/static/logo-cubicweb.svg
doc/book/en/_themes/cubicweb/theme.conf
doc/book/en/additionnal_services/index.rst
doc/book/en/additionnal_services/undo.rst
doc/book/en/admin/additional-tips.rst
doc/book/en/admin/config.rst
doc/book/en/admin/create-instance.rst
doc/book/en/admin/cubicweb-ctl.rst
doc/book/en/admin/index.rst
doc/book/en/admin/instance-config.rst
doc/book/en/admin/ldap.rst
doc/book/en/admin/migration.rst
doc/book/en/admin/multisources.rst
doc/book/en/admin/rql-logs.rst
doc/book/en/admin/setup-windows.rst
doc/book/en/admin/setup.rst
doc/book/en/admin/site-config.rst
doc/book/en/annexes/depends.rst
doc/book/en/annexes/docstrings-conventions.rst
doc/book/en/annexes/faq.rst
doc/book/en/annexes/index.rst
doc/book/en/annexes/mercurial.rst
doc/book/en/annexes/rql/Graph-ex.gif
doc/book/en/annexes/rql/debugging.rst
doc/book/en/annexes/rql/implementation.rst
doc/book/en/annexes/rql/index.rst
doc/book/en/annexes/rql/intro.rst
doc/book/en/annexes/rql/language.rst
doc/book/en/conf.py
doc/book/en/devrepo/cubes/available-cubes.rst
doc/book/en/devrepo/cubes/cc-newcube.rst
doc/book/en/devrepo/cubes/index.rst
doc/book/en/devrepo/cubes/layout.rst
doc/book/en/devrepo/dataimport.rst
doc/book/en/devrepo/datamodel/baseschema.rst
doc/book/en/devrepo/datamodel/define-workflows.rst
doc/book/en/devrepo/datamodel/definition.rst
doc/book/en/devrepo/datamodel/index.rst
doc/book/en/devrepo/datamodel/metadata.rst
doc/book/en/devrepo/devcore/index.rst
doc/book/en/devrepo/devcore/reqbase.rst
doc/book/en/devrepo/entityclasses/adapters.rst
doc/book/en/devrepo/entityclasses/application-logic.rst
doc/book/en/devrepo/entityclasses/data-as-objects.rst
doc/book/en/devrepo/entityclasses/index.rst
doc/book/en/devrepo/entityclasses/load-sort.rst
doc/book/en/devrepo/fti.rst
doc/book/en/devrepo/index.rst
doc/book/en/devrepo/migration.rst
doc/book/en/devrepo/profiling.rst
doc/book/en/devrepo/repo/hooks.rst
doc/book/en/devrepo/repo/index.rst
doc/book/en/devrepo/repo/notifications.rst
doc/book/en/devrepo/repo/sessions.rst
doc/book/en/devrepo/repo/tasks.rst
doc/book/en/devrepo/testing.rst
doc/book/en/devrepo/vreg.rst
doc/book/en/devweb/ajax.rst
doc/book/en/devweb/controllers.rst
doc/book/en/devweb/css.rst
doc/book/en/devweb/edition/dissection.rst
doc/book/en/devweb/edition/editcontroller.rst
doc/book/en/devweb/edition/examples.rst
doc/book/en/devweb/edition/form.rst
doc/book/en/devweb/edition/index.rst
doc/book/en/devweb/facets.rst
doc/book/en/devweb/httpcaching.rst
doc/book/en/devweb/index.rst
doc/book/en/devweb/internationalization.rst
doc/book/en/devweb/js.rst
doc/book/en/devweb/property.rst
doc/book/en/devweb/publisher.rst
doc/book/en/devweb/request.rst
doc/book/en/devweb/resource.rst
doc/book/en/devweb/rtags.rst
doc/book/en/devweb/searchbar.rst
doc/book/en/devweb/views/basetemplates.rst
doc/book/en/devweb/views/baseviews.rst
doc/book/en/devweb/views/boxes.rst
doc/book/en/devweb/views/breadcrumbs.rst
doc/book/en/devweb/views/idownloadable.rst
doc/book/en/devweb/views/index.rst
doc/book/en/devweb/views/primary.rst
doc/book/en/devweb/views/reledit.rst
doc/book/en/devweb/views/startup.rst
doc/book/en/devweb/views/table.rst
doc/book/en/devweb/views/urlpublish.rst
doc/book/en/devweb/views/views.rst
doc/book/en/devweb/views/wdoc.rst
doc/book/en/devweb/views/xmlrss.rst
doc/book/en/images/03-transitions-view_en.png
doc/book/en/images/archi_globale.png
doc/book/en/images/archi_globale_en.png
doc/book/en/images/breadcrumbs_header.png
doc/book/en/images/facet_date_range.png
doc/book/en/images/facet_has_image.png
doc/book/en/images/facet_overview.png
doc/book/en/images/facet_range.png
doc/book/en/images/lax-book_00-login_en.png
doc/book/en/images/lax-book_01-start_en.png
doc/book/en/images/lax-book_02-cookie-values_en.png
doc/book/en/images/lax-book_02-create-blog_en.png
doc/book/en/images/lax-book_03-list-one-blog_en.png
doc/book/en/images/lax-book_03-site-config-panel_en.png
doc/book/en/images/lax-book_03-state-submitted_en.png
doc/book/en/images/lax-book_03-transitions-view_en.png
doc/book/en/images/lax-book_04-detail-one-blog_en.png
doc/book/en/images/lax-book_05-list-two-blog_en.png
doc/book/en/images/lax-book_06-add-relation-entryof_en.png
doc/book/en/images/lax-book_06-main-template-logo_en.png
doc/book/en/images/lax-book_07-detail-one-blogentry_en.png
doc/book/en/images/lax-book_08-schema_en.png
doc/book/en/images/lax-book_09-new-view-blogentry_en.png
doc/book/en/images/lax-book_10-blog-with-two-entries_en.png
doc/book/en/images/main_template.png
doc/book/en/images/main_template.svg
doc/book/en/images/main_template_layout.png
doc/book/en/images/primaryview_template.png
doc/book/en/images/primaryview_template.svg
doc/book/en/images/request_session.png
doc/book/en/images/request_session.svg
doc/book/en/images/server-class-diagram.png
doc/book/en/images/tutos-base_blog-form_en.png
doc/book/en/images/tutos-base_blog-primary-after-post-creation_en.png
doc/book/en/images/tutos-base_blog-primary_en.png
doc/book/en/images/tutos-base_blogs-list_en.png
doc/book/en/images/tutos-base_form-generic-relations_en.png
doc/book/en/images/tutos-base_index_en.png
doc/book/en/images/tutos-base_login-form_en.png
doc/book/en/images/tutos-base_myblog-blogentry-taggable-commentable-primary_en.png
doc/book/en/images/tutos-base_myblog-community-custom-primary_en.png
doc/book/en/images/tutos-base_myblog-community-default-primary_en.png
doc/book/en/images/tutos-base_myblog-community-taggable-primary_en.png
doc/book/en/images/tutos-base_myblog-custom-footer_en.png
doc/book/en/images/tutos-base_myblog-schema_en.png
doc/book/en/images/tutos-base_myblog-siteinfo_en.png
doc/book/en/images/tutos-base_schema_en.png
doc/book/en/images/tutos-base_siteconfig_en.png
doc/book/en/images/tutos-base_user-menu_en.png
doc/book/en/images/tutos-photowebsite_background-image.png
doc/book/en/images/tutos-photowebsite_boxes.png
doc/book/en/images/tutos-photowebsite_breadcrumbs.png
doc/book/en/images/tutos-photowebsite_facets.png
doc/book/en/images/tutos-photowebsite_grey-box.png
doc/book/en/images/tutos-photowebsite_index-after.png
doc/book/en/images/tutos-photowebsite_index-before.png
doc/book/en/images/tutos-photowebsite_login-box.png
doc/book/en/images/tutos-photowebsite_prevnext.png
doc/book/en/images/tutos-photowebsite_ui1.png
doc/book/en/images/tutos-photowebsite_ui2.png
doc/book/en/images/tutos-photowebsite_ui3.png
doc/book/en/images/undo_history-view_w600.png
doc/book/en/images/undo_mesage_w600.png
doc/book/en/images/undo_startup-link_w600.png
doc/book/en/images/views-table-filter-shadow.png
doc/book/en/images/views-table-filter.png
doc/book/en/images/views-table-shadow.png
doc/book/en/images/views-table.png
doc/book/en/index.rst
doc/book/en/intro/concepts.rst
doc/book/en/intro/history.rst
doc/book/en/intro/index.rst
doc/book/en/makefile
doc/book/en/tutorials/advanced/index.rst
doc/book/en/tutorials/advanced/part01_create-cube.rst
doc/book/en/tutorials/advanced/part02_security.rst
doc/book/en/tutorials/advanced/part03_bfss.rst
doc/book/en/tutorials/advanced/part04_ui-base.rst
doc/book/en/tutorials/advanced/part05_ui-advanced.rst
doc/book/en/tutorials/base/blog-in-five-minutes.rst
doc/book/en/tutorials/base/conclusion.rst
doc/book/en/tutorials/base/customizing-the-application.rst
doc/book/en/tutorials/base/discovering-the-ui.rst
doc/book/en/tutorials/base/index.rst
doc/book/en/tutorials/index.rst
doc/book/en/tutorials/textreports/index.rst
doc/book/en/tutorials/tools/windmill.rst
doc/book/index.rst
doc/book/intro/concepts.rst
doc/book/intro/history.rst
doc/book/intro/index.rst
doc/book/mode_plan.py
doc/changes/3.14.rst
doc/changes/3.15.rst
doc/changes/3.16.rst
doc/changes/3.17.rst
doc/changes/3.18.rst
doc/changes/3.19.rst
doc/changes/3.20.rst
doc/changes/index.rst
doc/conf.py
doc/dev/documenting.rst
doc/images/03-transitions-view_en.png
doc/images/archi_globale.png
doc/images/archi_globale_en.png
doc/images/breadcrumbs_header.png
doc/images/facet_date_range.png
doc/images/facet_has_image.png
doc/images/facet_overview.png
doc/images/facet_range.png
doc/images/lax-book_00-login_en.png
doc/images/lax-book_01-start_en.png
doc/images/lax-book_02-cookie-values_en.png
doc/images/lax-book_02-create-blog_en.png
doc/images/lax-book_03-list-one-blog_en.png
doc/images/lax-book_03-site-config-panel_en.png
doc/images/lax-book_03-state-submitted_en.png
doc/images/lax-book_03-transitions-view_en.png
doc/images/lax-book_04-detail-one-blog_en.png
doc/images/lax-book_05-list-two-blog_en.png
doc/images/lax-book_06-add-relation-entryof_en.png
doc/images/lax-book_06-main-template-logo_en.png
doc/images/lax-book_07-detail-one-blogentry_en.png
doc/images/lax-book_08-schema_en.png
doc/images/lax-book_09-new-view-blogentry_en.png
doc/images/lax-book_10-blog-with-two-entries_en.png
doc/images/main_template.png
doc/images/main_template.svg
doc/images/main_template_layout.png
doc/images/primaryview_template.png
doc/images/primaryview_template.svg
doc/images/request_session.png
doc/images/request_session.svg
doc/images/server-class-diagram.png
doc/images/tutos-base_blog-form_en.png
doc/images/tutos-base_blog-primary-after-post-creation_en.png
doc/images/tutos-base_blog-primary_en.png
doc/images/tutos-base_blogs-list_en.png
doc/images/tutos-base_form-generic-relations_en.png
doc/images/tutos-base_index_en.png
doc/images/tutos-base_login-form_en.png
doc/images/tutos-base_myblog-blogentry-taggable-commentable-primary_en.png
doc/images/tutos-base_myblog-community-custom-primary_en.png
doc/images/tutos-base_myblog-community-default-primary_en.png
doc/images/tutos-base_myblog-community-taggable-primary_en.png
doc/images/tutos-base_myblog-custom-footer_en.png
doc/images/tutos-base_myblog-schema_en.png
doc/images/tutos-base_myblog-siteinfo_en.png
doc/images/tutos-base_schema_en.png
doc/images/tutos-base_siteconfig_en.png
doc/images/tutos-base_user-menu_en.png
doc/images/tutos-photowebsite_background-image.png
doc/images/tutos-photowebsite_boxes.png
doc/images/tutos-photowebsite_breadcrumbs.png
doc/images/tutos-photowebsite_facets.png
doc/images/tutos-photowebsite_grey-box.png
doc/images/tutos-photowebsite_index-after.png
doc/images/tutos-photowebsite_index-before.png
doc/images/tutos-photowebsite_login-box.png
doc/images/tutos-photowebsite_prevnext.png
doc/images/tutos-photowebsite_ui1.png
doc/images/tutos-photowebsite_ui2.png
doc/images/tutos-photowebsite_ui3.png
doc/images/undo_history-view_w600.png
doc/images/undo_mesage_w600.png
doc/images/undo_startup-link_w600.png
doc/images/views-table-filter-shadow.png
doc/images/views-table-filter.png
doc/images/views-table-shadow.png
doc/images/views-table.png
doc/index.rst
doc/tools/mode_plan.py
doc/tools/pyjsrest.py
doc/tutorials/advanced/index.rst
doc/tutorials/advanced/part01_create-cube.rst
doc/tutorials/advanced/part02_security.rst
doc/tutorials/advanced/part03_bfss.rst
doc/tutorials/advanced/part04_ui-base.rst
doc/tutorials/advanced/part05_ui-advanced.rst
doc/tutorials/base/blog-in-five-minutes.rst
doc/tutorials/base/conclusion.rst
doc/tutorials/base/customizing-the-application.rst
doc/tutorials/base/discovering-the-ui.rst
doc/tutorials/base/index.rst
doc/tutorials/index.rst
doc/tutorials/textreports/index.rst
doc/tutorials/tools/windmill.rst
--- a/.hgignore	Mon Jul 06 17:39:35 2015 +0200
+++ b/.hgignore	Thu Jan 08 22:11:06 2015 +0100
@@ -18,4 +18,7 @@
 ^doc/html/
 ^doc/doctrees/
 ^doc/book/en/devweb/js_api/
+^doc/_build
+^doc/js_api/
+data/pgdb/
 data.*/pgdb.*
--- a/doc/3.14.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-Whats new in CubicWeb 3.14
-==========================
-
-First notice CW 3.14 depends on yams 0.34 (which is incompatible with prior
-cubicweb releases regarding instance re-creation).
-
-API changes
------------
-
-* `Entity.fetch_rql` `restriction` argument has been deprecated and should be
-  replaced with a call to the new `Entity.fetch_rqlst` method, get the returned
-  value (a rql `Select` node) and use the RQL syntax tree API to include the
-  above-mentionned restrictions.
-
-  Backward compat is kept with proper warning.
-
-* `Entity.fetch_order` and `Entity.fetch_unrelated_order` class methods have been
-  replaced by `Entity.cw_fetch_order` and `Entity.cw_fetch_unrelated_order` with
-  a different prototype:
-
-  - instead of taking (attr, var) as two string argument, they now take (select,
-    attr, var) where select is the rql syntax tree beinx constructed and var the
-    variable *node*.
-
-  - instead of returning some string to be inserted in the ORDERBY clause, it has
-    to modify the syntax tree
-
-  Backward compat is kept with proper warning, BESIDE cases below:
-
-  - custom order method return **something else the a variable name with or
-    without the sorting order** (e.g. cases where you sort on the value of a
-    registered procedure as it was done in the tracker for instance). In such
-    case, an error is logged telling that this sorting is ignored until API
-    upgrade.
-
-  - client code use direct access to one of those methods on an entity (no code
-    known to do that).
-
-* `Entity._rest_attr_info` class method has been renamed to
-  `Entity.cw_rest_attr_info`
-
-  No backward compat yet since this is a protected method an no code is known to
-  use it outside cubicweb itself.
-
-* `AnyEntity.linked_to` has been removed as part of a refactoring of this
-  functionality (link a entity to another one at creation step). It was replaced
-  by a `EntityFieldsForm.linked_to` property.
-
-  In the same refactoring, `cubicweb.web.formfield.relvoc_linkedto`,
-  `cubicweb.web.formfield.relvoc_init` and
-  `cubicweb.web.formfield.relvoc_unrelated` were removed and replaced by
-  RelationField methods with the same names, that take a form as a parameter.
-
-  **No backward compatibility yet**. It's still time to cry for it.
-  Cubes known to be affected: tracker, vcsfile, vcreview.
-
-* `CWPermission` entity type and its associated require_permission relation type
-  (abstract) and require_group relation definitions have been moved to a new
-  `localperms` cube. With this have gone some functions from the
-  `cubicweb.schemas` package as well as some views. This makes cubicweb itself
-  smaller while you get all the local permissions stuff into a single,
-  documented, place.
-
-  Backward compat is kept for existing instances, **though you should have
-  installed the localperms cubes**. A proper error should be displayed when
-  trying to migrate to 3.14 an instance the use `CWPermission` without the new
-  cube installed. For new instances / test, you should add a dependancy on the
-  new cube in cubes using this feature, along with a dependancy on cubicweb >=
-  3.14.
-
-* jQuery has been updated to 1.6.4 and jquery-tablesorter to 2.0.5. No backward
-  compat issue known.
-
-* Table views refactoring : new `RsetTableView` and `EntityTableView`, as well as
-  rewritten an enhanced version of `PyValTableView` on the same bases, with logic
-  moved to some column renderers and a layout. Those should be well documented
-  and deprecates former `TableView`, `EntityAttributesTableView` and `CellView`,
-  which are however kept for backward compat, with some warnings that may not be
-  very clear unfortunatly (you may see your own table view subclass name here,
-  which doesn't make the problem that clear). Notice that `_cw.view('table',
-  rset, *kwargs)` will be routed to the new `RsetTableView` or to the old
-  `TableView` depending on given extra arguments. See #1986413.
-
-* `display_name` don't call .lower() anymore. This may leads to changes in your
-  user interface. Different msgid for upper/lower cases version of entity type
-  names, as this is the only proper way to handle this with some languages.
-
-* `IEditControlAdapter` has been deprecated in favor of `EditController`
-  overloading, which was made easier by adding dedicated selectors called
-  `match_edited_type` and `match_form_id`.
-
-* Pre 3.6 API backward compat has been dropped, though *data* migration
-  compatibility has been kept. You may have to fix errors due to old API usage
-  for your instance before to be able to run migration, but then you should be
-  able to upgrade even a pre 3.6 database.
-
-* Deprecated `cubicweb.web.views.iprogress` in favor of new `iprogress` cube.
-
-* Deprecated `cubicweb.web.views.flot` in favor of new `jqplot` cube.
-
-
-Unintrusive API changes
------------------------
-
-* Refactored properties forms (eg user preferences and site wide properties) as
-  well as pagination components to ease overridding.
-
-* New `cubicweb.web.uihelper` module with high-level helpers for uicfg.
-
-* New `anonymized_request` decorator to temporary run stuff as an anonymous
-  user, whatever the currently logged in user.
-
-* New 'verbatimattr' attribute view.
-
-* New facet and form widget for Integer used to store binary mask.
-
-* New `js_href` function to generated proper javascript href.
-
-* `match_kwargs` and `match_form_params` selectors both accept a new
-  `once_is_enough` argument.
-
-* `printable_value` is now a method of request, and may be given dict of
-   formatters to use.
-
-* `[Rset]TableView` allows to set None in 'headers', meaning the label should be
-  fetched from the result set as done by default.
-
-* Field vocabulary computation on entity creation now takes `__linkto`
-  information into accounet.
-
-* Started a `cubicweb.pylintext` pylint plugin to help pylint analyzing cubes.
-
-
-RQL
----
-
-* Support for HAVING in 'SET' and 'DELETE' queries.
-
-* new `AT_TZ` function to get back a timestamp at a given time-zone.
-
-* new `WEEKDAY` date extraction function
-
-
-User interface changes
-----------------------
-
-* Datafeed source now present an history of the latest import's log, including
-  global status and debug/info/warning/error messages issued during
-  imports. Import logs older than a configurable amount of time are automatically
-  deleted.
-
-* Breadcrumbs component is properly kept when creating an entity with '__linkto'.
-
-* users and groups management now really lead to that (i.e. includes *groups*
-  management).
-
-* New 'jsonp' controller with 'jsonexport' and 'ejsonexport' views.
-
-
-Configuration
-------------
-
-* Added option 'resources-concat' to make javascript/css files concatenation
-  optional.
--- a/doc/3.15.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-What's new in CubicWeb 3.15?
-============================
-
-New functionnalities
---------------------
-
-* Add Zmq server, based on the cutting edge ZMQ (http://www.zeromq.org/) socket
-  library.  This allows to access distant instance, in a similar way as Pyro.
-
-* Publish/subscribe mechanism using ZMQ for communication among cubicweb
-  instances.  The new zmq-address-sub and zmq-address-pub configuration variables
-  define where this communication occurs.  As of this release this mechanism is
-  used for entity cache invalidation.
-
-* Improved WSGI support. While there is still some caveats, most of the code
-  which was twisted only is now generic and allows related functionalities to work
-  with a WSGI front-end.
-
-* Full undo/transaction support : undo of modification has eventually been
-  implemented, and the configuration simplified (basically you activate it or not
-  on an instance basis).
-
-* Controlling HTTP status code used is not much more easier :
-
-  - `WebRequest` now has a `status_out` attribut to control the response status ;
-
-  - most web-side exceptions take an optional ``status`` argument.
-
-API changes
------------
-
-* The base registry implementation has been moved to a new
-  `logilab.common.registry` module (see #1916014). This includes code from :
-
-  * `cubicweb.vreg` (the whole things that was in there)
-  * `cw.appobject` (base selectors and all).
-
-  In the process, some renaming was done:
-
-  * the top level registry is now `RegistryStore` (was `VRegistry`), but that
-    should not impact cubicweb client code ;
-
-  * former selectors functions are now known as "predicate", though you still use
-    predicates to build an object'selector ;
-
-  * for consistency, the `objectify_selector` decoraror has hence be renamed to
-    `objectify_predicate` ;
-
-  * on the CubicWeb side, the `selectors` module has been renamed to
-    `predicates`.
-
-  Debugging refactoring dropped the more need for the `lltrace` decorator.  There
-  should be full backward compat with proper deprecation warnings.  Notice the
-  `yes` predicate and `objectify_predicate` decorator, as well as the
-  `traced_selection` function should now be imported from the
-  `logilab.common.registry` module.
-
-* All login forms are now submitted to <app_root>/login. Redirection to requested
-  page is now handled by the login controller (it was previously handle by the
-  session manager).
-
-* `Publisher.publish` has been renamed to `Publisher.handle_request`. This
-  method now contains generic version of logic previously handled by
-  Twisted. `Controller.publish` is **not** affected.
-
-Unintrusive API changes
------------------------
-
-* New 'ldapfeed' source type, designed to replace 'ldapuser' source with
-  data-feed (i.e. copy based) source ideas.
-
-* New 'zmqrql' source type, similar to 'pyrorql' but using ømq instead of Pyro.
-
-* A new registry called `services` has appeared, where you can register
-  server-side `cubicweb.server.Service` child classes. Their `call` method can be
-  invoked from a web-side AppObject instance using new `self._cw.call_service`
-  method or a server-side one using `self.session.call_service`. This is a new
-  way to call server-side methods, much cleaner than monkey patching the
-  Repository class, which becomes a deprecated way to perform similar tasks.
-
-* a new `ajax-func` registry now hosts all remote functions (i.e. functions
-  callable through the `asyncRemoteExec` JS api). A convenience `ajaxfunc`
-  decorator will let you expose your python function easily without all the
-  appobject standard boilerplate. Backward compatibility is preserved.
-
-* the 'json' controller is now deprecated in favor of the 'ajax' one.
-
-* `WebRequest.build_url` can now take a __secure__ argument. When True cubicweb
-  try to generate an https url.
-
-
-User interface changes
-----------------------
-
-A new 'undohistory' view expose the undoable transactions and give access to undo
-some of them.
--- a/doc/3.16.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-What's new in CubicWeb 3.16?
-============================
-
-New functionalities
---------------------
-
-* Add a new dataimport store (`SQLGenObjectStore`). This store enables a fast
-  import of data (entity creation, link creation) in CubicWeb, by directly
-  flushing information in SQL.  This may only be used with PostgreSQL, as it
-  requires the 'COPY FROM' command.
-
-
-API changes
------------
-
-* Orm: `set_attributes` and `set_relations` are unified (and
-  deprecated) in favor of `cw_set` that works in all cases.
-
-* db-api/configuration: all the external repository connection information is
-  now in an URL (see `#2521848 <http://www.cubicweb.org/2521848>`_),
-  allowing to drop specific options of pyro nameserver host, group, etc and fix
-  broken `ZMQ <http://www.zeromq.org/>`_ source. Configuration related changes:
-
-  * Dropped 'pyro-ns-host', 'pyro-instance-id', 'pyro-ns-group' from the client side
-    configuration, in favor of 'repository-uri'. **NO MIGRATION IS DONE**,
-    supposing there is no web-only configuration in the wild.
-
-  * Stop discovering the connection method through `repo_method` class attribute
-    of the configuration, varying according to the configuration class. This is
-    a first step on the way to a simpler configuration handling.
-
-  DB-API related changes:
-
-  * Stop indicating the connection method using `ConnectionProperties`.
-
-  * Drop `_cnxtype` attribute from `Connection` and `cnxtype` from
-    `Session`. The former is replaced by a `is_repo_in_memory` property
-    and the later is totaly useless.
-
-  * Turn `repo_connect` into `_repo_connect` to mark it as a private function.
-
-  * Deprecate `in_memory_cnx` which becomes useless, use `_repo_connect` instead
-    if necessary.
-
-* the "tcp://" uri scheme used for `ZMQ <http://www.zeromq.org/>`_
-  communications (in a way reminiscent of Pyro) is now named
-  "zmqpickle-tcp://", so as to make room for future zmq-based lightweight
-  communications (without python objects pickling).
-
-* Request.base_url gets a `secure=True` optional parameter that yields
-  an https url if possible, allowing hook-generated content to send
-  secure urls (e.g. when sending mail notifications)
-
-* Dataimport ucsvreader gets a new boolean `ignore_errors`
-  parameter.
-
-
-Unintrusive API changes
------------------------
-
-* Drop of `cubicweb.web.uicfg.AutoformSectionRelationTags.bw_tag_map`,
-  deprecated since 3.6.
-
-
-User interface changes
-----------------------
-
-* The RQL search bar has now some auto-completion support. It means
-  relation types or entity types can be suggested while typing. It is
-  an awesome improvement over the current behaviour !
-
-* The `action box` associated with `table` views (from `tableview.py`)
-  has been transformed into a nice-looking series of small tabs; it
-  means that the possible actions are immediately visible and need not
-  be discovered by clicking on an almost invisible icon on the upper
-  right.
-
-* The `uicfg` module has moved to web/views/ and ui configuration
-  objects are now selectable. This will reduce the amount of
-  subclassing and whole methods replacement usually needed to
-  customize the ui behaviour in many cases.
-
-* Remove changelog view, as neither cubicweb nor known
-  cubes/applications were properly feeding related files.
-
-
-Other changes
--------------
-
-* 'pyrorql' sources will be automatically updated to use an URL to locate the source
-  rather than configuration option. 'zmqrql' sources were broken before this change,
-  so no upgrade is needed...
-
-* Debugging filters for Hooks and Operations have been added.
-
-* Some cubicweb-ctl commands used to show the output of `msgcat` and
-  `msgfmt`; they don't anymore.
--- a/doc/3.17.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-What's new in CubicWeb 3.17?
-============================
-
-New functionalities
---------------------
-
-* add a command to compare db schema and file system schema
-  (see `#464991 <http://www.cubicweb.org/464991>`_)
-
-* Add CubicWebRequestBase.content with the content of the HTTP request (see #2742453)
-  (see `#2742453 <http://www.cubicweb.org/2742453>`_)
-
-* Add directive bookmark to ReST rendering
-  (see `#2545595 <http://www.cubicweb.org/ticket/2545595>`_)
-
-* Allow user defined final type
-  (see `#124342 <https://www.logilab.org/ticket/124342>`_)
-
-
-API changes
------------
-
-* drop typed_eid() in favour of int() (see `#2742462 <http://www.cubicweb.org/2742462>`_)
-
-* The SIOC views and adapters have been removed from CubicWeb and moved to the
-  `sioc` cube.
-
-* The web page embedding views and adapters have been removed from CubicWeb and
-  moved to the `embed` cube.
-
-* The email sending views and controllers have been removed from CubicWeb and
-  moved to the `massmailing` cube.
-
-* ``RenderAndSendNotificationView`` is deprecated in favor of
-  ``ActualNotificationOp`` the new operation use the more efficient *data*
-  idiom.
-
-* Looping task can now have a interval <= ``0``. Negative interval disable the
-  looping task entirely.
-
-* We now serve html instead of xhtml.
-  (see `#2065651 <http://www.cubicweb.org/ticket/2065651>`_)
-
-
-Deprecation
----------------------
-
-* ``ldapuser`` have been deprecated. It'll be fully dropped in the next
-  version. If you are still using ldapuser switch to ``ldapfeed`` **NOW**!
-
-* ``hijack_user`` have been deprecated. It will be dropped soon.
-
-Deprecated Code Drops
-----------------------
-
-* The progress views and adapters have been removed from CubicWeb. These
-  classes were deprecated since 3.14.0. They are still available in the
-  `iprogress` cube.
-
-* API deprecated since 3.7 have been dropped.
--- a/doc/3.18.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-What's new in CubicWeb 3.18?
-============================
-
-The migration script does not handle sqlite nor mysql instances.
-
-
-New functionalities
---------------------
-
-* add a security debugging tool
-  (see `#2920304 <http://www.cubicweb.org/2920304>`_)
-
-* introduce an `add` permission on attributes, to be interpreted at
-  entity creation time only and allow the implementation of complex
-  `update` rules that don't block entity creation (before that the
-  `update` attribute permission was interpreted at entity creation and
-  update time)
-
-* the primary view display controller (uicfg) now has a
-  `set_fields_order` method similar to the one available for forms
-
-* new method `ResultSet.one(col=0)` to retrive a single entity and enforce the
-  result has only one row (see `#3352314 https://www.cubicweb.org/ticket/3352314`_)
-
-* new method `RequestSessionBase.find` to look for entities
-  (see `#3361290 https://www.cubicweb.org/ticket/3361290`_)
-
-* the embedded jQuery copy has been updated to version 1.10.2, and jQuery UI to
-  version 1.10.3.
-
-* initial support for wsgi for the debug mode, available through the new
-  ``wsgi`` cubicweb-ctl command, which can use either python's builtin
-  wsgi server or the werkzeug module if present.
-
-* a ``rql-table`` directive is now available in ReST fields
-
-* cubicweb-ctl upgrade can now generate the static data resource directory
-  directly, without a manual call to gen-static-datadir.
-
-API changes
------------
-
-* not really an API change, but the entity permission checks are now
-  systematically deferred to an operation, instead of a) trying in a
-  hook and b) if it failed, retrying later in an operation
-
-* The default value storage for attributes is no longer String, but
-  Bytes.  This opens the road to storing arbitrary python objects, e.g.
-  numpy arrays, and fixes a bug where default values whose truth value
-  was False were not properly migrated.
-
-* `symmetric` relations are no more handled by an rql rewrite but are
-  now handled with hooks (from the `activeintegrity` category); this
-  may have some consequences for applications that do low-level database
-  manipulations or at times disable (some) hooks.
-
-* `unique together` constraints (multi-columns unicity constraints)
-  get a `name` attribute that maps the CubicWeb contraint entities to
-  corresponding backend index.
-
-* BreadCrumbEntityVComponent's open_breadcrumbs method now includes
-  the first breadcrumbs separator
-
-* entities can be compared for equality and hashed
-
-* the ``on_fire_transition`` predicate accepts a sequence of possible
-  transition names
-
-* the GROUP_CONCAT rql aggregate function no longer repeats duplicate
-  values, on the sqlite and postgresql backends
-
-Deprecation
----------------------
-
-* ``pyrorql`` sources have been deprecated. Multisource will be fully dropped
-  in the next version. If you are still using pyrorql, switch to ``datafeed``
-  **NOW**!
-
-* the old multi-source system
-
-* `find_one_entity` and `find_entities` in favor of `find`
-  (see `#3361290 https://www.cubicweb.org/ticket/3361290`_)
-
-* the `TmpFileViewMixin` and `TmpPngView` classes (see `#3400448
-  https://www.cubicweb.org/ticket/3400448`_)
-
-Deprecated Code Drops
-----------------------
-
-* ``ldapuser`` have been dropped; use ``ldapfeed`` now
-  (see `#2936496 <http://www.cubicweb.org/2936496>`_)
-
-* action ``GotRhythm`` was removed, make sure you do not
-  import it in your cubes (even to unregister it)
-  (see `#3093362 <http://www.cubicweb.org/3093362>`_)
-
-* all 3.8 backward compat is gone
-
-* all 3.9 backward compat (including the javascript side) is gone
-
-* the ``twisted`` (web-only) instance type has been removed
--- a/doc/3.19.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-What's new in CubicWeb 3.19?
-============================
-
-New functionalities
---------------------
-
-* implement Cross Origin Resource Sharing (CORS)
-  (see `#2491768 <http://www.cubicweb.org/2491768>`_)
-
-* system_source.create_eid can get a range of IDs, to reduce overhead of batch
-  entity creation
-
-Behaviour Changes
------------------
-
-* The anonymous property of Session and Connection are now computed from the
-  related user login. If it matches the ``anonymous-user`` in the config the
-  connection is anonymous. Beware that the ``anonymous-user`` config is web
-  specific. Therefore, no session may be anonymous in a repository only setup.
-
-
-New Repository Access API
--------------------------
-
-Connection replaces Session
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A new explicit Connection object replaces Session as the main repository entry
-point. Connection holds all the necessary methods to be used server-side
-(``execute``, ``commit``, ``rollback``, ``call_service``, ``entity_from_eid``,
-etc...). One obtains a new Connection object using ``session.new_cnx()``.
-Connection objects need to have an explicit begin and end. Use them as a context
-manager to never miss an end::
-
-    with session.new_cnx() as cnx:
-        cnx.execute('INSERT Elephant E, E name "Babar"')
-        cnx.commit()
-        cnx.execute('INSERT Elephant E, E name "Celeste"')
-        cnx.commit()
-    # Once you get out of the "with" clause, the connection is closed.
-
-Using the same Connection object in multiple threads will give you access to the
-same Transaction. However, Connection objects are not thread safe (hence at your
-own risks).
-
-``repository.internal_session`` is deprecated in favor of
-``repository.internal_cnx``. Note that internal connections are now `safe` by default,
-i.e. the integrity hooks are enabled.
-
-Backward compatibility is preserved on Session.
-
-
-dbapi vs repoapi
-~~~~~~~~~~~~~~~~
-
-A new API has been introduced to replace the dbapi. It is called `repoapi`.
-
-There are three relevant functions for now:
-
-* ``repoapi.get_repository`` returns a Repository object either from an
-  URI when used as ``repoapi.get_repository(uri)`` or from a config
-  when used as ``repoapi.get_repository(config=config)``.
-
-* ``repoapi.connect(repo, login, **credentials)`` returns a ClientConnection
-  associated with the user identified by the credentials. The
-  ClientConnection is associated with its own Session that is closed
-  when the ClientConnection is closed. A ClientConnection is a
-  Connection-like object to be used client side.
-
-* ``repoapi.anonymous_cnx(repo)`` returns a ClientConnection associated
-  with the anonymous user if described in the config.
-
-
-repoapi.ClientConnection replace dbapi.Connection and company
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-On the client/web side, the Request is now using a ``repoapi.ClientConnection``
-instead of a ``dbapi.connection``. The ``ClientConnection`` has multiple backward
-compatible methods to make it look like a ``dbapi.Cursor`` and ``dbapi.Connection``.
-
-Session used on the Web side are now the same than the one used Server side.
-Some backward compatibility methods have been installed on the server side Session
-to ease the transition.
-
-The authentication stack has been altered to use the ``repoapi`` instead of
-the ``dbapi``. Cubes adding new element to this stack are likely to break.
-
-Session data can be accessed using the cnx.data dictionary, while
-transaction data is available through cnx.transaction_data.  These
-replace the [gs]et_shared_data methods with optional txid kwarg.
-
-New API in tests
-~~~~~~~~~~~~~~~~
-
-All current methods and attributes used to access the repo on ``CubicWebTC`` are
-deprecated. You may now use a ``RepoAccess`` object. A ``RepoAccess`` object is
-linked to a new ``Session`` for a specified user. It is able to create
-``Connection``, ``ClientConnection`` and web side requests linked to this
-session::
-
-    access = self.new_access('babar') # create a new RepoAccess for user babar
-    with access.repo_cnx() as cnx:
-        # some work with server side cnx
-        cnx.execute(...)
-        cnx.commit()
-        cnx.execute(...)
-        cnx.commit()
-
-    with access.client_cnx() as cnx:
-        # some work with client side cnx
-        cnx.execute(...)
-        cnx.commit()
-
-    with access.web_request(elephant='babar') as req:
-        # some work with client side cnx
-        elephant_name = req.form['elephant']
-        req.execute(...)
-        req.cnx.commit()
-
-By default ``testcase.admin_access`` contains a ``RepoAccess`` object for the
-default admin session.
-
-
-API changes
------------
-
-* ``RepositorySessionManager.postlogin`` is now called with two arguments,
-  request and session. And this now happens before the session is linked to the
-  request.
-
-* ``SessionManager`` and ``AuthenticationManager`` now take a repo object at
-  initialization time instead of a vreg.
-
-* The ``async`` argument of ``_cw.call_service`` has been dropped. All calls are
-  now  synchronous. The zmq notification bus looks like a good replacement for
-  most async use cases.
-
-* ``repo.stats()`` is now deprecated. The same information is available through
-  a service (``_cw.call_service('repo_stats')``).
-
-* ``repo.gc_stats()`` is now deprecated. The same information is available through
-  a service (``_cw.call_service('repo_gc_stats')``).
-
-* ``repo.register_user()`` is now deprecated.  The functionality is now
-  available through a service (``_cw.call_service('register_user')``).
-
-* ``request.set_session`` no longer takes an optional ``user`` argument.
-
-* CubicwebTC does not have repo and cnx as class attributes anymore. They are
-  standard instance attributes. ``set_cnx`` and ``_init_repo`` class methods
-  become instance methods.
-
-* ``set_cnxset`` and ``free_cnxset`` are deprecated. cnxset are now
-  automatically managed.
-
-* The implementation of cascading deletion when deleting `composite`
-  entities has changed. There comes a semantic change: merely deleting
-  a composite relation does not entail any more the deletion of the
-  component side of the relation.
-
-* ``_cw.user_callback`` and ``_cw.user_rql_callback`` are deprecated.  Users
-  are encouraged to write an actual controller (e.g. using ``ajaxfunc``)
-  instead of storing a closure in the session data.
-
-* A new ``entity.cw_linkable_rql`` method provides the rql to fetch all entities
-  that are already or may be related to the current entity using the given
-  relation.
-
-
-Deprecated Code Drops
-----------------------
-
-* session.hijack_user mechanism has been dropped.
-
-* EtypeRestrictionComponent has been removed, its functionality has been
-  replaced by facets a while ago.
-
-* the old multi-source support has been removed.  Only copy-based sources
-  remain, such as datafeed or ldapfeed.
-
--- a/doc/3.20.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-What's new in CubicWeb 3.20
-===========================
-
-New features
-------------
-
-* virtual relations: a new ComputedRelation class can be used in
-  schema.py; its `rule` attribute is an RQL snippet that defines the new
-  relation.
-
-* computed attributes: an attribute can now be defined with a `formula`
-  argument (also an RQL snippet); it will be read-only, and updated
-  automatically.
-
-  Both of these features are described in `CWEP-002`_, and the updated
-  "Data model" chapter of the CubicWeb book.
-
-* cubicweb-ctl plugins can use the ``cubicweb.utils.admincnx`` function
-  to get a Connection object from an instance name.
-
-* new 'tornado' wsgi backend
-
-* session cookies have the HttpOnly flag, so they're no longer exposed to
-  javascript
-
-* rich text fields can be formatted as markdown
-
-* the edit controller detects concurrent editions, and raises a ValidationError
-  if an entity was modified between form generation and submission
-
-* cubicweb can use a postgresql "schema" (namespace) for its tables
-
-* "cubicweb-ctl configure" can be used to set values of the admin user
-  credentials in the sources configuration file
-
-* in debug mode, setting the _cwtracehtml parameter on a request allows tracing
-  where each bit of output is produced
-
-.. _CWEP-002: http://hg.logilab.org/review/cwep/file/tip/CWEP-002.rst
-
-
-API Changes
------------
-
-* ``ucsvreader()`` and ``ucsvreader_pb()`` from the ``dataimport`` module have
-  2 new keyword arguments ``delimiter`` and ``quotechar`` to replace the
-  ``separator`` and ``quote`` arguments respectively. This makes the API match
-  that of Python's ``csv.reader()``.  The old arguments are still supported
-  though deprecated.
-
-* the migration environment's ``remove_cube`` function is now called ``drop_cube``.
-
-* cubicweb.old.css is now cubicweb.css.  The previous "new"
-  cubicweb.css, along with its cubicweb.reset.css companion, have been
-  removed.
-
-* the jquery-treeview plugin was updated to its latest version
-
-
-Deprecated Code Drops
-----------------------
-
-* most of 3.10 and 3.11 backward compat is gone; this includes:
-  - CtxComponent.box_action() and CtxComponent.build_link()
-  - cubicweb.devtools.htmlparser.XMLDemotingValidator
-  - various methods and properties on Entities, replaced by cw_edited and cw_attr_cache
-  - 'commit_event' method on hooks, replaced by 'postcommit_event'
-  - server.hook.set_operation(), replaced by Operation.get_instance(...).add_data()
-  - View.div_id(), View.div_class() and View.create_url()
-  - `*VComponent` classes
-  - in forms, Field.value() and Field.help() must take the form and the field itself as arguments
-  - form.render() must get `w` as a named argument, and renderer.render() must take `w` as first argument
-  - in breadcrumbs, the optional `recurs` argument must be a set, not False
-  - cubicweb.web.views.idownloadable.{download_box,IDownloadableLineView}
-  - primary views no longer have `render_entity_summary` and `summary` methods
-  - WFHistoryVComponent's `cell_call` method is replaced by `render_body`
-  - cubicweb.dataimport.ObjectStore.add(), replaced by create_entity
-  - ManageView.{folders,display_folders}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/Makefile	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,88 @@
+SRC=.
+
+# You can set these sphinx variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+#BUILDDIR      = build
+BUILDDIR      = _build
+CWDIR         = ..
+JSDIR         = ${CWDIR}/web/data
+JSTORST       = tools/pyjsrest.py
+BUILDJS       = js_api
+
+# Internal variables for sphinx
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d ${BUILDDIR}/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  all       to make standalone HTML files, developer manual and API doc"
+	@echo "  html      to make standalone HTML files"
+	@echo "---  "
+	@echo "  pickle    to make pickle files (usable by e.g. sphinx-web)"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview over all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+
+clean:
+	rm -f *.html
+	-rm -rf ${BUILDDIR}/html ${BUILDDIR}/doctrees
+	-rm -rf ${BUILDJS}
+
+all: html
+
+# run sphinx ###
+html: js
+	mkdir -p ${BUILDDIR}/html ${BUILDDIR}/doctrees
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) ${BUILDDIR}/html
+	@echo
+	@echo "Build finished. The HTML pages are in ${BUILDDIR}/html."
+
+js:
+	mkdir -p ${BUILDJS}
+	$(JSTORST) -p ${JSDIR} -o ${BUILDJS}
+
+pickle:
+	mkdir -p ${BUILDDIR}/pickle ${BUILDDIR}/doctrees
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) ${BUILDDIR}/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files or run"
+	@echo "  sphinx-web ${BUILDDIR}/pickle"
+	@echo "to start the sphinx-web server."
+
+web: pickle
+
+htmlhelp:
+	mkdir -p ${BUILDDIR}/htmlhelp ${BUILDDIR}/doctrees
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) ${BUILDDIR}/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in ${BUILDDIR}/htmlhelp."
+
+latex:
+	mkdir -p ${BUILDDIR}/latex ${BUILDDIR}/doctrees
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) ${BUILDDIR}/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in ${BUILDDIR}/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	mkdir -p ${BUILDDIR}/changes ${BUILDDIR}/doctrees
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) ${BUILDDIR}/changes
+	@echo
+	@echo "The overview file is in ${BUILDDIR}/changes."
+
+linkcheck:
+	mkdir -p ${BUILDDIR}/linkcheck ${BUILDDIR}/doctrees
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) ${BUILDDIR}/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in ${BUILDDIR}/linkcheck/output.txt."
Binary file doc/_static/cubicweb.png has changed
Binary file doc/_static/logilab.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_static/sphinx-default.css	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,861 @@
+/**
+ * Sphinx Doc Design
+ */
+
+html, body {
+    background: white;
+}
+
+body {
+    font-family: Verdana, sans-serif;
+    font-size: 100%;
+    background-color: white;
+    color: black;
+    margin: 0;
+    padding: 0;
+}
+
+/* :::: LAYOUT :::: */
+
+div.logilablogo {
+    padding: 10px 10px 10px 10px;
+    height:75;
+}
+
+
+div.document {
+    background-color: white;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 230px;
+}
+
+div.body {
+    background-color: white;
+    padding: 0 20px 30px 20px;
+    border-left:solid;
+    border-left-color:#e2e2e2;
+    border-left-width:thin;
+}
+
+div.sphinxsidebarwrapper {
+    padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+    float: left;
+    width: 230px;
+    margin-left: -100%;
+    font-size: 90%;
+}
+
+div.clearer {
+    clear: both;
+}
+
+div.footer {
+    color: #ff4500;
+    width: 100%;
+    padding: 9px 0 9px 0;
+    text-align: center;
+    font-size: 75%;
+}
+
+div.footer a {
+    color: #ff4500;
+    text-decoration: underline;
+}
+
+div.related {
+    background-color: #ff7700;
+    color: white;
+    width: 100%;
+    height: 30px;
+    line-height: 30px;
+    font-size: 90%;
+}
+
+div.related h3 {
+    display: none;
+}
+
+div.related ul {
+    margin: 0;
+    padding: 0 0 0 10px;
+    list-style: none;
+}
+
+div.related li {
+    display: inline;
+}
+
+div.related li.right {
+    float: right;
+    margin-right: 5px;
+}
+
+div.related a {
+    color: white;
+    font-weight:bold;
+}
+
+/* ::: TOC :::: */
+
+div.sphinxsidebar {
+    border-style:solid;
+    border-color: white;
+/*    background-color:#e2e2e2;*/
+    padding-bottom:5px;
+}
+
+div.sphinxsidebar h3 {
+    font-family: Verdana, sans-serif;
+    color: black;
+    font-size: 1.2em;
+    font-weight: normal;
+    margin: 0;
+    padding: 0;
+    font-weight:bold;
+    font-style:italic;
+}
+
+div.sphinxsidebar h4 {
+    font-family: Verdana, sans-serif;
+    color: black;
+    font-size: 1.1em;
+    font-weight: normal;
+    margin: 5px 0 0 0;
+    padding: 0;
+    font-weight:bold;
+    font-style:italic;
+}
+
+div.sphinxsidebar p {
+    color: black;
+}
+
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px;
+    padding: 0;
+    list-style: none;
+    color: black;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+    margin-left: 20px;
+    list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+div.sphinxsidebar a {
+    color: black;
+    text-decoration: none;
+}
+
+div.sphinxsidebar form {
+    margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #e2e2e2;
+    font-family: sans-serif;
+    font-size: 1em;
+    padding-bottom: 5px;
+}
+
+/* :::: MODULE CLOUD :::: */
+div.modulecloud {
+    margin: -5px 10px 5px 10px;
+    padding: 10px;
+    line-height: 160%;
+    border: 1px solid #cbe7e5;
+    background-color: #f2fbfd;
+}
+
+div.modulecloud a {
+    padding: 0 5px 0 5px;
+}
+
+/* :::: SEARCH :::: */
+ul.search {
+    margin: 10px 0 0 20px;
+    padding: 0;
+}
+
+ul.search li {
+    padding: 5px 0 5px 20px;
+    background-image: url(file.png);
+    background-repeat: no-repeat;
+    background-position: 0 7px;
+}
+
+ul.search li a {
+    font-weight: bold;
+}
+
+ul.search li div.context {
+    color: #888;
+    margin: 2px 0 0 30px;
+    text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+    font-weight: bold;
+}
+
+/* :::: COMMON FORM STYLES :::: */
+
+div.actions {
+    padding: 5px 10px 5px 10px;
+    border-top: 1px solid #cbe7e5;
+    border-bottom: 1px solid #cbe7e5;
+    background-color: #e0f6f4;
+}
+
+form dl {
+    color: #333;
+}
+
+form dt {
+    clear: both;
+    float: left;
+    min-width: 110px;
+    margin-right: 10px;
+    padding-top: 2px;
+}
+
+input#homepage {
+    display: none;
+}
+
+div.error {
+    margin: 5px 20px 0 0;
+    padding: 5px;
+    border: 1px solid #d00;
+    font-weight: bold;
+}
+
+/* :::: INLINE COMMENTS :::: */
+
+div.inlinecomments {
+    position: absolute;
+    right: 20px;
+}
+
+div.inlinecomments a.bubble {
+    display: block;
+    float: right;
+    background-image: url(style/comment.png);
+    background-repeat: no-repeat;
+    width: 25px;
+    height: 25px;
+    text-align: center;
+    padding-top: 3px;
+    font-size: 0.9em;
+    line-height: 14px;
+    font-weight: bold;
+    color: black;
+}
+
+div.inlinecomments a.bubble span {
+    display: none;
+}
+
+div.inlinecomments a.emptybubble {
+    background-image: url(style/nocomment.png);
+}
+
+div.inlinecomments a.bubble:hover {
+    background-image: url(style/hovercomment.png);
+    text-decoration: none;
+    color: #3ca0a4;
+}
+
+div.inlinecomments div.comments {
+    float: right;
+    margin: 25px 5px 0 0;
+    max-width: 50em;
+    min-width: 30em;
+    border: 1px solid #2eabb0;
+    background-color: #f2fbfd;
+    z-index: 150;
+}
+
+div#comments {
+    border: 1px solid #2eabb0;
+    margin-top: 20px;
+}
+
+div#comments div.nocomments {
+    padding: 10px;
+    font-weight: bold;
+}
+
+div.inlinecomments div.comments h3,
+div#comments h3 {
+    margin: 0;
+    padding: 0;
+    background-color: #2eabb0;
+    color: white;
+    border: none;
+    padding: 3px;
+}
+
+div.inlinecomments div.comments div.actions {
+    padding: 4px;
+    margin: 0;
+    border-top: none;
+}
+
+div#comments div.comment {
+    margin: 10px;
+    border: 1px solid #2eabb0;
+}
+
+div.inlinecomments div.comment h4,
+div.commentwindow div.comment h4,
+div#comments div.comment h4 {
+    margin: 10px 0 0 0;
+    background-color: #2eabb0;
+    color: white;
+    border: none;
+    padding: 1px 4px 1px 4px;
+}
+
+div#comments div.comment h4 {
+    margin: 0;
+}
+
+div#comments div.comment h4 a {
+    color: #d5f4f4;
+}
+
+div.inlinecomments div.comment div.text,
+div.commentwindow div.comment div.text,
+div#comments div.comment div.text {
+    margin: -5px 0 -5px 0;
+    padding: 0 10px 0 10px;
+}
+
+div.inlinecomments div.comment div.meta,
+div.commentwindow div.comment div.meta,
+div#comments div.comment div.meta {
+    text-align: right;
+    padding: 2px 10px 2px 0;
+    font-size: 95%;
+    color: #538893;
+    border-top: 1px solid #cbe7e5;
+    background-color: #e0f6f4;
+}
+
+div.commentwindow {
+    position: absolute;
+    width: 500px;
+    border: 1px solid #cbe7e5;
+    background-color: #f2fbfd;
+    display: none;
+    z-index: 130;
+}
+
+div.commentwindow h3 {
+    margin: 0;
+    background-color: #2eabb0;
+    color: white;
+    border: none;
+    padding: 5px;
+    font-size: 1.5em;
+    cursor: pointer;
+}
+
+div.commentwindow div.actions {
+    margin: 10px -10px 0 -10px;
+    padding: 4px 10px 4px 10px;
+    color: #538893;
+}
+
+div.commentwindow div.actions input {
+    border: 1px solid #2eabb0;
+    background-color: white;
+    color: #135355;
+    cursor: pointer;
+}
+
+div.commentwindow div.form {
+    padding: 0 10px 0 10px;
+}
+
+div.commentwindow div.form input,
+div.commentwindow div.form textarea {
+    border: 1px solid #3c9ea2;
+    background-color: white;
+    color: black;
+}
+
+div.commentwindow div.error {
+    margin: 10px 5px 10px 5px;
+    background-color: #fbe5dc;
+    display: none;
+}
+
+div.commentwindow div.form textarea {
+    width: 99%;
+}
+
+div.commentwindow div.preview {
+    margin: 10px 0 10px 0;
+    background-color: #70d0d4;
+    padding: 0 1px 1px 25px;
+}
+
+div.commentwindow div.preview h4 {
+    margin: 0 0 -5px -20px;
+    padding: 4px 0 0 4px;
+    color: white;
+    font-size: 1.3em;
+}
+
+div.commentwindow div.preview div.comment {
+    background-color: #f2fbfd;
+}
+
+div.commentwindow div.preview div.comment h4 {
+    margin: 10px 0 0 0!important;
+    padding: 1px 4px 1px 4px!important;
+    font-size: 1.2em;
+}
+
+/* :::: SUGGEST CHANGES :::: */
+div#suggest-changes-box input, div#suggest-changes-box textarea {
+    border: 1px solid #ccc;
+    background-color: white;
+    color: black;
+}
+
+div#suggest-changes-box textarea {
+    width: 99%;
+    height: 400px;
+}
+
+
+/* :::: PREVIEW :::: */
+div.preview {
+    background-image: url(style/preview.png);
+    padding: 0 20px 20px 20px;
+    margin-bottom: 30px;
+}
+
+
+/* :::: INDEX PAGE :::: */
+
+table.contentstable {
+    width: 90%;
+}
+
+table.contentstable p.biglink {
+    line-height: 150%;
+}
+
+a.biglink {
+    font-size: 1.3em;
+}
+
+span.linkdescr {
+    font-style: italic;
+    padding-top: 5px;
+    font-size: 90%;
+}
+
+/* :::: INDEX STYLES :::: */
+
+table.indextable td {
+    text-align: left;
+    vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+    height: 10px;
+}
+
+table.indextable tr.cap {
+    margin-top: 10px;
+    background-color: #f2f2f2;
+}
+
+img.toggler {
+    margin-right: 3px;
+    margin-top: 3px;
+    cursor: pointer;
+}
+
+form.pfform {
+    margin: 10px 0 20px 0;
+}
+
+/* :::: GLOBAL STYLES :::: */
+
+.docwarning {
+    background-color: #ffe4e4;
+    padding: 10px;
+    margin: 0 -20px 0 -20px;
+    border-bottom: 1px solid #f66;
+}
+
+p.subhead {
+    font-weight: bold;
+    margin-top: 20px;
+}
+
+a {
+    color: orangered;
+    text-decoration: none;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: 'Verdana', sans-serif;
+    background-color: white;
+    font-weight: bold;
+    color: black;
+    border-bottom: 1px solid #ccc;
+    margin: 20px -20px 10px -20px;
+    padding: 3px 0 3px 10px;
+}
+
+div.body h1 { margin-top: 10pt; font-size: 150%; }
+div.body h2 { font-size: 120%; }
+div.body h3 { font-size: 100%; }
+div.body h4 { font-size: 80%; }
+div.body h5 { font-size: 600%; }
+div.body h6 { font-size: 40%; }
+
+a.headerlink {
+    color: #c60f0f;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+    visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink {
+    visibility: visible;
+}
+
+a.headerlink:hover {
+    background-color: #c60f0f;
+    color: white;
+}
+
+div.body p, div.body dd, div.body li {
+    text-align: justify;
+    line-height: 130%;
+}
+
+div.body p.caption {
+    text-align: inherit;
+}
+
+div.body td {
+    text-align: left;
+}
+
+ul.fakelist {
+    list-style: none;
+    margin: 10px 0 10px 20px;
+    padding: 0;
+}
+
+.field-list ul {
+    padding-left: 1em;
+}
+
+.first {
+    margin-top: 0 !important;
+}
+
+/* "Footnotes" heading */
+p.rubric {
+    margin-top: 30px;
+    font-weight: bold;
+}
+
+/* "Topics" */
+
+div.topic {
+    background-color: #eee;
+    border: 1px solid #ccc;
+    padding: 0 7px 0 7px;
+    margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+    font-size: 1.1em;
+    font-weight: bold;
+    margin-top: 10px;
+}
+
+/* Admonitions */
+
+div.admonition {
+    margin-top: 10px;
+    margin-bottom: 10px;
+    padding: 7px;
+}
+
+div.admonition dt {
+    font-weight: bold;
+}
+
+div.admonition dl {
+    margin-bottom: 0;
+}
+
+div.admonition p {
+    display: inline;
+}
+
+div.seealso {
+    background-color: #ffc;
+    border: 1px solid #ff6;
+}
+
+div.warning {
+    background-color: #ffe4e4;
+    border: 1px solid #f66;
+}
+
+div.note {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+p.admonition-title {
+    margin: 0px 10px 5px 0px;
+    font-weight: bold;
+    display: inline;
+}
+
+p.admonition-title:after {
+    content: ":";
+}
+
+div.body p.centered {
+    text-align: center;
+    margin-top: 25px;
+}
+
+table.docutils {
+    border: 0;
+}
+
+table.docutils td, table.docutils th {
+    padding: 1px 8px 1px 0;
+    border-top: 0;
+    border-left: 0;
+    border-right: 0;
+    border-bottom: 1px solid #aaa;
+}
+
+table.field-list td, table.field-list th {
+    border: 0 !important;
+}
+
+table.footnote td, table.footnote th {
+    border: 0 !important;
+}
+
+.field-list ul {
+    margin: 0;
+    padding-left: 1em;
+}
+
+.field-list p {
+    margin: 0;
+}
+
+dl {
+    margin-bottom: 15px;
+    clear: both;
+}
+
+dd p {
+    margin-top: 0px;
+}
+
+dd ul, dd table {
+    margin-bottom: 10px;
+}
+
+dd {
+    margin-top: 3px;
+    margin-bottom: 10px;
+    margin-left: 30px;
+}
+
+.refcount {
+    color: #060;
+}
+
+dt:target,
+.highlight {
+    background-color: #fbe54e;
+}
+
+dl.glossary dt {
+    font-weight: bold;
+    font-size: 1.1em;
+}
+
+th {
+    text-align: left;
+    padding-right: 5px;
+}
+
+pre {
+    padding: 5px;
+    background-color: #efc;
+    color: #333;
+    border: 1px solid #ac9;
+    border-left: none;
+    border-right: none;
+    overflow: auto;
+}
+
+td.linenos pre {
+    padding: 5px 0px;
+    border: 0;
+    background-color: transparent;
+    color: #aaa;
+}
+
+table.highlighttable {
+    margin-left: 0.5em;
+}
+
+table.highlighttable td {
+    padding: 0 0.5em 0 0.5em;
+}
+
+tt {
+    background-color: #ecf0f3;
+    padding: 0 1px 0 1px;
+    font-size: 0.95em;
+}
+
+tt.descname {
+    background-color: transparent;
+    font-weight: bold;
+    font-size: 1.2em;
+}
+
+tt.descclassname {
+    background-color: transparent;
+}
+
+tt.xref, a tt {
+    background-color: transparent;
+    font-weight: bold;
+}
+
+.footnote:target  { background-color: #ffa }
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+    background-color: transparent;
+}
+
+.optional {
+    font-size: 1.3em;
+}
+
+.versionmodified {
+    font-style: italic;
+}
+
+form.comment {
+    margin: 0;
+    padding: 10px 30px 10px 30px;
+    background-color: #eee;
+}
+
+form.comment h3 {
+    background-color: #326591;
+    color: white;
+    margin: -10px -30px 10px -30px;
+    padding: 5px;
+    font-size: 1.4em;
+}
+
+form.comment input,
+form.comment textarea {
+    border: 1px solid #ccc;
+    padding: 2px;
+    font-family: sans-serif;
+    font-size: 100%;
+}
+
+form.comment input[type="text"] {
+    width: 240px;
+}
+
+form.comment textarea {
+    width: 100%;
+    height: 200px;
+    margin-bottom: 10px;
+}
+
+.system-message {
+    background-color: #fda;
+    padding: 5px;
+    border: 3px solid red;
+}
+
+/* :::: PRINT :::: */
+@media print {
+    div.document,
+    div.documentwrapper,
+    div.bodywrapper {
+        margin: 0;
+        width : 100%;
+    }
+
+    div.sphinxsidebar,
+    div.related,
+    div.footer,
+    div#comments div.new-comment-box,
+    #top-link {
+        display: none;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_templates/layout.html	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,196 @@
+{%- block doctype -%}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{%- endblock %}
+{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
+{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
+{%- macro relbar() %}
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        {%- for rellink in rellinks %}
+        <li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
+          <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags }}"
+             accesskey="{{ rellink[2] }}">{{ rellink[3] }}</a>
+          {%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
+        {%- endfor %}
+        {%- block rootrellink %}
+        <li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+        {%- endblock %}
+        {%- for parent in parents %}
+          <li><a href="{{ parent.link|e }}" accesskey="U">{{ parent.title }}</a>{{ reldelim1 }}</li>
+        {%- endfor %}
+        {%- block relbaritems %}{% endblock %}
+      </ul>
+    </div>
+{%- endmacro %}
+{%- macro sidebar() %}
+      {%- if builder != 'htmlhelp' %}
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+          {%- block sidebarlogo %}
+          {%- if logo %}
+            <p class="logo"><img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/></p>
+          {%- endif %}
+          {%- endblock %}
+          {%- block sidebartoc %}
+          {%- if display_toc %}
+            <h3>Table Of Contents</h3>
+            {{ toc }}
+          {%- endif %}
+          {%- endblock %}
+          {%- block sidebarrel %}
+          {%- if prev %}
+            <h4>Previous topic</h4>
+            <p class="topless"><a href="{{ prev.link|e }}" title="previous chapter">{{ prev.title }}</a></p>
+          {%- endif %}
+          {%- if next %}
+            <h4>Next topic</h4>
+            <p class="topless"><a href="{{ next.link|e }}" title="next chapter">{{ next.title }}</a></p>
+          {%- endif %}
+          {%- endblock %}
+          {%- if sourcename %}
+            <!--<h3>This Page</h3>
+            <ul class="this-page-menu">
+            {%- if builder == 'web' %}
+              <li><a href="#comments">Comments ({{ comments|length }} so far)</a></li>
+              <li><a href="{{ pathto('@edit/' + sourcename)|e }}">Suggest Change</a></li>
+              <li><a href="{{ pathto('@source/' + sourcename)|e }}">Show Source</a></li>
+            {%- elif builder == 'html' %}
+              <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}">Show Source</a></li>
+            {%- endif %}
+            </ul>-->
+          {%- endif %}
+          {%- if customsidebar %}
+          {{ rendertemplate(customsidebar) }}
+          {%- endif %}
+          {%- block sidebarsearch %}
+          {%- if pagename != "search" %}
+            <h3>{{ builder == 'web' and 'Keyword' or 'Quick' }} search</h3>
+            <form class="search" action="{{ pathto('search') }}" method="get">
+              <input type="text" name="q" size="18" /> <input type="submit" value="Go" />
+              <input type="hidden" name="check_keywords" value="yes" />
+              <input type="hidden" name="area" value="default" />
+            </form>
+            {%- if builder == 'web' %}
+            <p style="font-size: 90%">Enter a module, class or function name.</p>
+            {%- endif %}
+          {%- endif %}
+          {%- endblock %}
+        </div>
+      </div>
+      {%- endif %}
+{%- endmacro -%}
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    {%- if builder != 'htmlhelp' %}
+      {%- set titlesuffix = " &mdash; " + docstitle %}
+    {%- endif %}
+    <title>{{ title|striptags }}{{ titlesuffix }}</title>
+    {%- if builder == 'web' %}
+    <link rel="stylesheet" href="{{ pathto('index') }}?do=stylesheet{%
+      if in_admin_panel %}&admin=yes{% endif %}" type="text/css" />
+    {%- for link, type, title in page_links %}
+    <link rel="alternate" type="{{ type|e(true) }}" title="{{ title|e(true) }}" href="{{ link|e(true) }}" />
+    {%- endfor %}
+    {%- else %}
+    <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
+    <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
+    {%- endif %}
+    {%- if builder != 'htmlhelp' %}
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+          URL_ROOT:    '{{ pathto("", 1) }}',
+          VERSION:     '{{ release }}',
+          COLLAPSE_MODINDEX: false,
+          FILE_SUFFIX: '{{ file_suffix }}'
+      };
+    </script>
+    <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
+    <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
+    {%- if use_opensearch %}
+    <link rel="search" type="application/opensearchdescription+xml"
+          title="Search within {{ docstitle }}"
+          href="{{ pathto('_static/opensearch.xml', 1) }}"/>
+    {%- endif %}
+    {%- if favicon %}
+    <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
+    {%- endif %}
+    {%- endif %}
+{%- block rellinks %}
+    {%- if hasdoc('about') %}
+    <link rel="author" title="About these documents" href="{{ pathto('about') }}" />
+    {%- endif %}
+    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}" />
+    <link rel="index" title="Global index" href="{{ pathto('genindex') }}" />
+    <link rel="search" title="Search" href="{{ pathto('search') }}" />
+    {%- if hasdoc('copyright') %}
+    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}" />
+    {%- endif %}
+    <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}" />
+    {%- if parents %}
+    <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}" />
+    {%- endif %}
+    {%- if next %}
+    <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}" />
+    {%- endif %}
+    {%- if prev %}
+    <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}" />
+    {%- endif %}
+{%- endblock %}
+{%- block extrahead %}{% endblock %}
+  </head>
+  <body>
+
+{% block logilablogo %}
+<div class="logilablogo">
+	<a class="logogo" href="http://www.cubicweb.org"><img border="0" src="{{ pathto('_static/cubicweb.png', 1) }}"/></a>
+  </div>
+{% endblock %}
+
+{%- block relbar1 %}{{ relbar() }}{% endblock %}
+
+{%- block sidebar1 %}{# possible location for sidebar #}{% endblock %}
+
+{%- block document %}
+    <div class="document">
+      <div class="documentwrapper">
+      {%- if builder != 'htmlhelp' %}
+        <div class="bodywrapper">
+      {%- endif %}
+          <div class="body">
+            {% block body %}{% endblock %}
+          </div>
+      {%- if builder != 'htmlhelp' %}
+        </div>
+      {%- endif %}
+      </div>
+{%- endblock %}
+
+{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
+      <div class="clearer"></div>
+    </div>
+
+{%- block relbar2 %}{{ relbar() }}{% endblock %}
+
+{%- block footer %}
+    <div class="footer">
+    {%- if hasdoc('copyright') %}
+      &copy; <a href="{{ pathto('copyright') }}">Copyright</a> {{ copyright }}.
+    {%- else %}
+      &copy; Copyright {{ copyright }}.
+    {%- endif %}
+    {%- if last_updated %}
+      Last updated on {{ last_updated }}.
+    {%- endif %}
+    {%- if show_sphinx %}
+      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
+    {%- endif %}
+    </div>
+{%- endblock %}
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_themes/cubicweb/layout.html	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,61 @@
+{% extends "basic/layout.html" %}
+
+{%- block extrahead %}
+<!--[if lte IE 6]>
+<link rel="stylesheet" href="{{ pathto('_static/ie6.css', 1) }}" type="text/css" media="screen" charset="utf-8" />
+<![endif]-->
+{%- if theme_favicon %}
+<link rel="shortcut icon" href="{{ pathto('_static/'+theme_favicon, 1) }}"/>
+{%- endif %}
+
+{%- if theme_canonical_url %}
+<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html"/>
+{%- endif %}
+{% endblock %}
+
+{% block header %}
+
+{% if theme_in_progress|tobool %}
+    <img style="position: fixed; display: block; width: 165px; height: 165px; bottom: 60px; right: 0; border: 0;" src="{{ pathto('_static/in_progress.png', 1) }}" alt="Documentation in progress" />
+{% endif %}
+
+{% if theme_outdated|tobool %}
+    <div style="bottom: 60px; right: 20px;position: fixed;"><a href="{{ latest_url }}" class="btn btn-large btn-danger"><strong>&gt;</strong> Read the latest version of this page</a></div>
+{% endif %}
+
+<div class="header-small">
+	{%- if theme_logo %}
+	{% set img, ext = theme_logo.split('.', -1) %}
+	<div class="logo-small">
+		<a href="{{ pathto(master_doc) }}">
+      		<img class="logo" src="{{ pathto('_static/%s-small.%s' % (img, ext), 1)}}" alt="Logo"/>
+		</a>
+  	</div>
+  	{%- endif %}
+</div>
+{% endblock %}
+
+{%- macro relbar() %}
+<div class="related">
+	<h3>{{ _('Navigation') }}</h3>
+	<ul>
+		{%- for rellink in rellinks %}
+		<li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
+			<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
+			{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
+			{%- if not loop.first %}{{ reldelim2 }}{% endif %}
+		</li>
+		{%- endfor %}
+    	{%- block rootrellink %}
+    	<li><a href="{{ pathto(master_doc) }}">{{ docstitle|e }}</a>{{ reldelim1 }}</li>
+    	{%- endblock %}
+    	{%- for parent in parents %}
+          <li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
+        {%- endfor %}
+        {%- block relbaritems %} {% endblock %}
+  	</ul>
+</div>
+{%- endmacro %}
+
+{%- block sidebarlogo %}{%- endblock %}
+{%- block sidebarsourcelink %}{%- endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_themes/cubicweb/static/cubicweb.css_t	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,33 @@
+/*
+ * cubicweb.css_t
+ * ~~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- cubicweb theme.
+ *
+ * :copyright: Copyright 2014 by the Cubicweb team, see AUTHORS.
+ * :license: LGPL, see LICENSE for details.
+ *
+ */
+ 
+@import url("pyramid.css");
+
+div.header-small {
+  background-image: linear-gradient(white, #e2e2e2);
+  border-bottom: 1px solid #bbb;
+}
+
+div.logo-small {
+  padding: 10px;
+}
+
+img.logo {
+  width: 150px;
+}
+
+div.related a {
+  color: #e6820e;
+}
+
+a, a .pre {
+  color: #e6820e;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_themes/cubicweb/static/cubicweb.ico	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,1 @@
+../../../../../../web/data/favicon.ico
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_themes/cubicweb/static/logo-cubicweb-small.svg	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,1 @@
+logo-cubicweb.svg
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_themes/cubicweb/static/logo-cubicweb.svg	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,1 @@
+../../../../../../web/data/logo-cubicweb.svg
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/_themes/cubicweb/theme.conf	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,12 @@
+[theme]
+inherit = pyramid
+pygments_style = sphinx.pygments_styles.PyramidStyle
+stylesheet = cubicweb.css
+
+
+[options]
+logo = logo-cubicweb.svg
+favicon = cubicweb.ico
+in_progress = false
+outdated = false
+canonical_url = 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/MERGE_ME-tut-create-app.en.txt	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,386 @@
+.. -*- coding: utf-8 -*-
+
+
+Tutoriel : créer votre première application web pour Google AppEngine
+=====================================================================
+
+[TRANSLATE ME TO FRENCH]
+
+This tutorial will guide you step by step to build a blog application 
+and discover the unique features of `LAX`. It assumes that you followed
+the :ref:`installation` guidelines and that both the `AppEngine SDK` and the
+`LAX` framework are setup on your computer.
+
+Creating a new application
+--------------------------
+
+We choosed in this tutorial to develop a blog as an example of web application
+and will go through each required steps/actions to have it running with `LAX`.
+When you installed `LAX`, you saw a directory named ``skel``. Make a copy of
+this directory and call it ``BlogDemo``.
+
+The location of this directory does not matter. But once decided, make sure your ``PYTHONPATH`` is properly set (:ref:`installation`).
+
+
+Defining a schema
+-----------------
+
+With `LAX`, the schema/datamodel is the core of the application. This is where
+you will define the type of content you have to hanlde in your application.
+
+Let us start with something simple and improve on it iteratively. 
+
+In schema.py, we define two entities: ``Blog`` and ``BlogEntry``.
+
+::
+
+  class Blog(EntityType):
+      title = String(maxsize=50, required=True)
+      description = String()
+
+  class BlogEntry(EntityType):
+      title = String(maxsize=100, required=True)
+      publish_date = Date(default='TODAY')
+      text = String(fulltextindexed=True)
+      category = String(vocabulary=('important','business'))
+      entry_of = SubjectRelation('Blog', cardinality='?*')
+
+A Blog has a title and a description. The title is a string that is
+required by the class EntityType and must be less than 50 characters. 
+The description is a string that is not constrained.
+
+A BlogEntry has a title, a publish_date and a text. The title is a
+string that is required and must be less than 100 characters. The
+publish_date is a Date with a default value of TODAY, meaning that
+when a BlogEntry is created, its publish_date will be the current day
+unless it is modified. The text is a string that will be indexed in
+the full-text index and has no constraint.
+
+A BlogEntry also has a relationship ``entry_of`` that link it to a
+Blog. The cardinality ``?*`` means that a BlogEntry can be part of
+zero or one Blog (``?`` means `zero or one`) and that a Blog can
+have any number of BlogEntry (``*`` means `any number including
+zero`). For completeness, remember that ``+`` means `one or more`.
+
+Running the application
+-----------------------
+
+Defining this simple schema is enough to get us started. Make sure you
+followed the setup steps described in detail in the installation
+chapter (especially visiting http://localhost:8080/_load as an
+administrator), then launch the application with the command::
+
+   python dev_appserver.py BlogDemo
+
+and point your browser at http://localhost:8080/ (if it is easier for
+you, use the on-line demo at http://lax.appspot.com/).
+
+.. image:: images/lax-book.00-login.en.png
+   :alt: login screen
+
+After you log in, you will see the home page of your application. It
+lists the entity types: Blog and BlogEntry. If these links read
+``blog_plural`` and ``blogentry_plural`` it is because
+internationalization (i18n) is not working for you yet. Please ignore
+this for now.
+
+.. image:: images/lax-book.01-start.en.png
+   :alt: home page
+
+Creating system entities
+------------------------
+You can only create new users if you decided not to use google authentication.
+
+
+[WRITE ME : create users manages permissions etc]
+
+
+
+Creating application entites
+----------------------------
+
+Create a Blog
+~~~~~~~~~~~~~
+
+Let us create a few of these entities. Click on the [+] at the right
+of the link Blog.  Call this new Blog ``Tech-blog`` and type in
+``everything about technology`` as the description, then validate the
+form by clicking on ``Validate``.
+
+.. image:: images/lax-book.02-create-blog.en.png
+   :alt: from to create blog
+
+Click on the logo at top left to get back to the home page, then
+follow the Blog link that will list for you all the existing Blog.
+You should be seeing a list with a single item ``Tech-blog`` you
+just created.
+
+.. image:: images/lax-book.03-list-one-blog.en.png
+   :alt: displaying a list of a single blog
+
+Clicking on this item will get you to its detailed description except
+that in this case, there is not much to display besides the name and
+the phrase ``everything about technology``.
+
+.. image:: images/lax-book.04-detail-one-blog.en.png
+  :alt: displaying the detailed view of a blog
+
+Now get back to the home page by clicking on the top-left logo, then
+create a new Blog called ``MyLife`` and get back to the home page
+again to follow the Blog link for the second time. The list now
+has two items.
+
+.. image:: images/lax-book.05-list-two-blog.en.png
+   :alt: displaying a list of two blogs
+
+
+Create a BlogEntry
+~~~~~~~~~~~~~~~~~~
+
+Get back to the home page and click on [+] at the right of the link
+BlogEntry. Call this new entry ``Hello World`` and type in some text
+before clicking on ``Validate``. You added a new blog entry without
+saying to what blog it belongs. There is a box on the left entitled
+``actions``, click on the menu item ``modify``. You are back to the form
+to edit the blog entry you just created, except that the form now has
+another section with a combobox titled ``add relation``. Chose
+``entry_of`` in this menu and a second combobox appears where you pick
+``MyLife``. 
+
+You could also have, at the time you started to fill the form for a
+new entity BlogEntry, hit ``Apply`` instead of ``Validate`` and the 
+combobox titled ``add relation`` would have showed up.
+
+.. image:: images/lax-book.06-add-relation-entryof.en.png
+   :alt: editing a blog entry to add a relation to a blog
+
+Validate the changes by clicking ``Validate``. The entity BlogEntry
+that is displayed now includes a link to the entity Blog named
+``MyLife``.
+
+.. image:: images/lax-book.07-detail-one-blogentry.en.png
+   :alt: displaying the detailed view of a blogentry
+
+Remember that all of this was handled by the framework and that the
+only input that was provided so far is the schema. To get a graphical
+view of the schema, run the ``laxctl genschema BlogDemo`` command as
+explained in the installation section and point your browser to the
+URL http://localhost:8080/schema
+
+.. image:: images/lax-book.08-schema.en.png
+   :alt: graphical view of the schema (aka data-model)
+
+Site configuration
+------------------
+
+.. image:: images/lax-book.03-site-config-panel.en.png
+
+This panel allows you to configure the appearance of your application site.
+Six menus are available and we will go through each of them to explain how
+to use them.
+
+Navigation
+~~~~~~~~~~
+This menu provides you a way to adjust some navigation options depending on
+your needs, such as the number of entities to display by page of results.
+Follows the detailled list of available options:
+  
+* navigation.combobox-limit: maximum number of entities to display in related
+  combo box (sample format: 23)
+* navigation.page-size: maximum number of objects displayed by page of results 
+  (sample format: 23)
+* navigation.related-limit: maximum number of related entities to display in 
+  the primary view (sample format: 23)
+* navigation.short-line-size: maximum number of characters in short description
+  (sample format: 23)
+
+UI
+~~
+This menu provides you a way to customize the user interface settings such as
+date format or encoding in the produced html.
+Follows the detailled list of available options:
+
+* ui.date-format : how to format date in the ui ("man strftime" for format description)
+* ui.datetime-format : how to format date and time in the ui ("man strftime" for format
+  description)
+* ui.default-text-format : default text format for rich text fields.
+* ui.encoding : user interface encoding
+* ui.fckeditor : should html fields being edited using fckeditor (a HTML WYSIWYG editor).
+  You should also select text/html as default text format to actually get fckeditor.
+* ui.float-format : how to format float numbers in the ui
+* ui.language : language of the user interface
+* ui.main-template : id of main template used to render pages
+* ui.site-title	: site title, which is displayed right next to the logo in the header
+* ui.time-format : how to format time in the ui ("man strftime" for format description)
+
+
+Actions
+~~~~~~~
+This menu provides a way to configure the context in which you expect the actions
+to be displayed to the user and if you want the action to be visible or not. 
+You must have notice that when you view a list of entities, an action box is 
+available on the left column which display some actions as well as a drop-down 
+menu for more actions. 
+
+The context available are:
+
+* mainactions : actions listed in the left box
+* moreactions : actions listed in the `more` menu of the left box
+* addrelated : add actions listed in the left box
+* useractions : actions listed in the first section of drop-down menu 
+  accessible from the right corner user login link
+* siteactions : actions listed in the second section of drop-down menu
+  accessible from the right corner user login link
+* hidden : select this to hide the specific action
+
+Boxes
+~~~~~
+The application has already a pre-defined set of boxes you can use right away. 
+This configuration section allows you to place those boxes where you want in the
+application interface to customize it. 
+
+The available boxes are:
+
+* actions box : box listing the applicable actions on the displayed data
+
+* boxes_blog_archives_box : box listing the blog archives 
+
+* possible views box : box listing the possible views for the displayed data
+
+* rss box : RSS icon to get displayed data as a RSS thread
+
+* search box : search box
+
+* startup views box : box listing the configuration options available for 
+  the application site, such as `Preferences` and `Site Configuration`
+
+Components
+~~~~~~~~~~
+[WRITE ME]
+
+Contextual components
+~~~~~~~~~~~~~~~~~~~~~
+[WRITE ME]
+
+Set-up a workflow
+-----------------
+
+Before starting, make sure you refresh your mind by reading [link to
+definition_workflow chapter].
+
+We want to create a workflow to control the quality of the BlogEntry 
+submitted on your application. When a BlogEntry is created by a user
+its state should be `submitted`. To be visible to all, it needs to
+be in the state `published`. To move from `submitted` to `published`
+we need a transition that we can name `approve_blogentry`.
+
+We do not want every user to be allowed to change the state of a 
+BlogEntry. We need to define a group of user, `moderators`, and 
+this group will have appropriate permissions to approve BlogEntry
+to be published and visible to all.
+
+There are two ways to create a workflow, form the user interface,
+and also by defining it in ``migration/postcreate.py``. This script
+is executed each time a new ``./bin/laxctl db-init`` is done. 
+If you create the states and transitions through the user interface
+this means that next time you will need to initialize the database
+you will have to re-create all the entities. 
+We strongly recommand you create the workflow in ``migration\postcreate.py``
+and we will now show you how.
+The user interface would only be a reference for you to view the states 
+and transitions but is not the appropriate interface to define your
+application workflow.
+
+Update the schema
+~~~~~~~~~~~~~~~~~
+To enable a BlogEntry to have a State, we have to define a relation
+``in_state`` in the schema of BlogEntry. Please do as follows, add
+the line ``in_state (...)``::
+
+  class BlogEntry(EntityType):
+      title = String(maxsize=100, required=True)
+      publish_date = Date(default='TODAY')
+      text_format = String(meta=True, internationalizable=True, maxsize=50,
+                           default='text/rest', constraints=[format_constraint])
+      text = String(fulltextindexed=True)
+      category = String(vocabulary=('important','business'))
+      entry_of = SubjectRelation('Blog', cardinality='?*')
+      in_state = SubjectRelation('State', cardinality='1*')
+
+As you updated the schema, you will have re-execute ``./bin/laxctl db-init``
+to initialize the database and migrate your existing entities.
+[WRITE ABOUT MIGRATION]
+
+Create states, transitions and group permissions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+At the time the ``postcreate.py`` script is executed, several methods
+can be used. They are all defined in the ``class ServerMigrationHelper``.
+We will only discuss the method we use to create a wrokflow here.
+
+To define our workflow for BlogDemo, please add the following lines
+to ``migration/postcreate.py``::
+  
+  _ = unicode
+
+  moderators      = add_entity('CWGroup', name=u"moderators")
+
+  submitted = add_state(_('submitted'), 'BlogEntry', initial=True)
+  published = add_state(_('published'), 'BlogEntry')
+
+  add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),)
+
+  checkpoint()
+
+``add_entity`` is used here to define the new group of users that we
+need to define the transitions, `moderators`.
+If this group required by the transition is not defined before the
+transition is created, it will not create the relation `transition 
+require the group moderator`.
+
+``add_state`` expects as the first argument the name of the state you are
+willing to create, then the entity type on which the state can be applied, 
+and an optionnal argument to set if the state is the initial state
+of the entity type or not.
+
+``add_transition`` expects as the first argument the name of the 
+transition, then the entity type on which we can apply the transition,
+then the list of possible initial states from which the transition
+can be applied, the target state of the transition, and the permissions
+(e.g. list of the groups of users who can apply the transition).
+
+.. image:: images/lax-book.03-transitions-view.en.png
+
+You can now notice that in the actions box of a BlogEntry, the state
+is now listed as well as the possible transitions from this state
+defined by the workflow. This transition, as defined in the workflow,
+will only being displayed for the users belonging to the group
+moderators of managers.
+
+Change view permission
+~~~~~~~~~~~~~~~~~~~~~~
+
+
+
+Conclusion
+----------
+
+Exercise
+~~~~~~~~
+
+Create new blog entries in ``Tech-blog``.
+
+What we learned
+~~~~~~~~~~~~~~~
+
+Creating a simple schema was enough to set up a new application that
+can store blogs and blog entries. 
+
+What is next ?
+~~~~~~~~~~~~~~
+
+Although the application is fully functionnal, its look is very
+basic. In the following section we will learn to create views to
+customize how data is displayed.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/MERGE_ME-tut-create-gae-app.en.txt	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,218 @@
+.. -*- coding: utf-8 -*-
+
+.. _tutorielGAE:
+
+Tutoriel : créer votre première application web pour Google AppEngine
+=====================================================================
+
+Ce tutoriel va vous guider pas à pas a construire une apllication web 
+de gestion de Blog afin de vous faire découvrir les fonctionnalités de
+*CubicWeb*.
+
+Nous supposons que vous avec déjà suivi le guide :ref:`installationGAE`.
+
+
+Créez une nouvelle application
+------------------------------
+
+Nous choisissons dans ce tutoriel de développer un blog comme un exemple
+d'application web et nous allons expliciter toutes les étapes nécessaires
+à sa réalisation.  
+
+::
+  
+  cubicweb-ctl newgapp blogdemo
+
+`newgapp` est la commande permettant de créer une instance *CubicWeb* pour
+le datastore.
+
+Assurez-vous que votre variable d'environnement ``PYTHONPATH`` est correctement
+initialisée (:ref:`installationGAE`)
+
+Définissez un schéma
+--------------------
+
+Le modèle de données ou schéma est au coeur d'une application *CubicWeb*.
+C'est là où vous allez devoir définir le type de contenu que votre application
+devra gérer.
+
+Commençons par un schéma simple que nous améliorerons progressivemment.
+
+Une fois votre instance ``blogdemo`` crée, vous trouverez un fichier ``schema.py``
+contenant la définition des entités suivantes : ``Blog`` and ``BlogEntry``.
+
+::
+
+  class Blog(EntityType):
+      title = String(maxsize=50, required=True)
+      description = String()
+
+  class BlogEntry(EntityType):
+      title = String(maxsize=100, required=True)
+      publish_date = Date(default='TODAY')
+      text = String(fulltextindexed=True)
+      category = String(vocabulary=('important','business'))
+      entry_of = SubjectRelation('Blog', cardinality='?*')
+
+
+Un ``Blog`` a un titre et une description. Le titre est une chaîne 
+de caractères requise par la classe parente EntityType and ne doit
+pas excéder 50 caractères. La description est une chaîne de 
+caractères sans contraintes.
+
+Une ``BlogEntry`` a un titre, une date de publication et du texte
+étant son contenu. Le titre est une chaîne de caractères qui ne 
+doit pas excéder 100 caractères. La date de publication est de type Date et a
+pour valeur par défaut TODAY, ce qui signifie que lorsqu'une 
+``BlogEntry`` sera créée, sa date de publication sera la date
+courante a moins de modifier ce champ. Le texte est une chaîne de
+caractères qui sera indexée en plein texte et sans contraintes.
+
+Une ``BlogEntry`` a aussi une relation nommée ``entry_of`` qui la
+relie à un ``Blog``. La cardinalité ``?*`` signifie que BlogEntry
+peut faire partie de zero a un Blog (``?`` signifie `zero ou un`) et
+qu'un Blog peut avoir une infinité de BlogEntry (``*`` signifie
+`n'importe quel nombre incluant zero`). 
+Par soucis de complétude, nous rappellerons que ``+`` signifie
+`un ou plus`.
+
+Lancez l'application
+--------------------
+
+Définir ce simple schéma est suffisant pour commencer. Assurez-vous 
+que vous avez suivi les étapes décrites dans la section installation
+(en particulier visitez http://localhost:8080/_load en tant qu'administrateur
+afin d'initialiser le datastore), puis lancez votre application avec la commande ::
+   
+   python dev_appserver.py BlogDemo
+
+puis dirigez vous vers http://localhost:8080/ (ou si c'est plus facile
+vous pouvez utiliser la démo en ligne http://lax.appspot.com/).
+[FIXME] -- changer la demo en ligne en quelque chose qui marche (!)
+
+.. image:: images/lax-book.00-login.en.png
+   :alt: login screen
+
+Après vous être authentifié, vous arrivez sur la page d'accueil de votre 
+application. Cette page liste les types d'entités accessibles dans votre
+application, en l'occurrence : Blog et Articles. Si vous lisez ``blog_plural``
+et ``blogentry_plural`` cela signifie que l'internationalisation (i18n)
+n'a pas encore fonctionné. Ignorez cela pour le moment.
+
+.. image:: images/lax-book.01-start.en.png
+   :alt: home page
+
+Créez des entités système
+-------------------------
+
+Vous ne pourrez créer de nouveaux utilisateurs que dans le cas où vous
+avez choisi de ne pas utiliser l'authentification Google.
+
+
+[WRITE ME : create users manages permissions etc]
+
+
+
+Créez des entités applicatives
+------------------------------
+
+Créez un Blog
+~~~~~~~~~~~~~
+
+Créons à présent quelques entités. Cliquez sur `[+]` sur la
+droite du lien Blog. Appelez cette nouvelle entité Blog ``Tech-Blog``
+et tapez pour la description ``everything about technology``,
+puis validez le formulaire d'édition en cliquant sur le bouton
+``Validate``.
+
+
+.. image:: images/lax-book.02-create-blog.en.png
+   :alt: from to create blog
+
+En cliquant sur le logo situé dans le coin gauche de la fenêtre,
+vous allez être redirigé vers la page d'accueil. Ensuite, si vous allez 
+sur le lien Blog, vous devriez voir la liste des entités Blog, en particulier
+celui que vous venez juste de créer ``Tech-Blog``.
+
+.. image:: images/lax-book.03-list-one-blog.en.png
+   :alt: displaying a list of a single blog
+
+Si vous cliquez sur ``Tech-Blog`` vous devriez obtenir une description
+détaillée, ce qui dans notre cas, n'est rien de plus que le titre
+et la phrase ``everything about technology``
+
+
+.. image:: images/lax-book.04-detail-one-blog.en.png
+   :alt: displaying the detailed view of a blog
+
+Maintenant retournons sur la page d'accueil et créons un nouveau
+Blog ``MyLife`` et retournons sur la page d'accueil, puis suivons
+le lien Blog et nous constatons qu'à présent deux blogs sont listés.
+
+.. image:: images/lax-book.05-list-two-blog.en.png
+   :alt: displaying a list of two blogs
+
+Créons un article
+~~~~~~~~~~~~~~~~~
+
+Revenons sur la page d'accueil et cliquons sur `[+]` à droite du lien
+`articles`. Appellons cette nouvelle entité ``Hello World`` et introduisons
+un peut de texte avant de ``Valider``. Vous venez d'ajouter un article
+sans avoir précisé à quel Blog il appartenait. Dans la colonne de gauche
+se trouve une boite intitulé ``actions``, cliquez sur le menu ``modifier``.
+Vous êtes de retour sur le formulaire d'édition de l'article que vous 
+venez de créer, à ceci près que ce formulaire a maintenant une nouvelle
+section intitulée ``ajouter relation``. Choisissez ``entry_of`` dans ce menu,
+cela va faire apparaitre une deuxième menu déroulant dans lequel vous
+allez pouvoir séléctionner le Blog ``MyLife``.
+
+Vous auriez pu aussi, au moment où vous avez crée votre article, sélectionner
+``appliquer`` au lieu de ``valider`` et le menu ``ajouter relation`` serait apparu.
+
+.. image:: images/lax-book.06-add-relation-entryof.en.png
+   :alt: editing a blog entry to add a relation to a blog
+
+Validez vos modifications en cliquant sur ``Valider``. L'entité article
+qui est listée contient maintenant un lien vers le Blog auquel il 
+appartient, ``MyLife``.
+
+.. image:: images/lax-book.07-detail-one-blogentry.en.png
+   :alt: displaying the detailed view of a blogentry
+
+Rappelez-vous que pour le moment, tout a été géré par la plate-forme
+*CubicWeb* et que la seule chose qui a été fournie est le schéma de
+données. D'ailleurs pour obtenir une vue graphique du schéma, exécutez
+la commande ``laxctl genschema blogdemo`` et vous pourrez visualiser
+votre schéma a l'URL suivante : http://localhost:8080/schema
+
+.. image:: images/lax-book.08-schema.en.png
+   :alt: graphical view of the schema (aka data-model)
+
+
+Change view permission
+~~~~~~~~~~~~~~~~~~~~~~
+
+
+
+Conclusion
+----------
+
+Exercise
+~~~~~~~~
+
+Create new blog entries in ``Tech-blog``.
+
+What we learned
+~~~~~~~~~~~~~~~
+
+Creating a simple schema was enough to set up a new application that
+can store blogs and blog entries. 
+
+What is next ?
+~~~~~~~~~~~~~~
+
+Although the application is fully functionnal, its look is very
+basic. In the following section we will learn to create views to
+customize how data is displayed.
+
+
--- a/doc/book/README	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-====
-Book
-====
-
-----
-Part
-----
-
-Chapter
-=======
-
-.. _Level1AnchorForLaterReference:
-
-Level 1 section
----------------
-
-Level 2 section
-~~~~~~~~~~~~~~~
-
-Level 3 section
-```````````````
-
-
-
-*CubicWeb*
-
-
-inline directives:
-  :file:`directory/file`
-  :envvar:`AN_ENV_VARIABLE`
-  :command:`command --option arguments`
-
-  :ref:, :mod:
-
-
-.. sourcecode:: python
-
-   class SomePythonCode:
-     ...
-
-.. XXX a comment, wont be rendered
-
-
-a [foot note]_
-
-.. [foot note] the foot note content
-
-
-Boxes
-=====
-
-- warning box: 
-    .. warning::
-
-       Warning content
-- note box:
-    .. note::
-
-       Note content
-
-
-
-Cross references
-================
-
-To arbitrary section
---------------------
-
-:ref:`identifier` ou :ref:`label <identifier>`
-
-Label required of referencing node which as no title, else the node's title will be used.
-
-
-To API objects
---------------
-See the autodoc sphinx extension documentation. Quick overview:
-
-* ref to a class: :class:`cubicweb.devtools.testlib.AutomaticWebTest`
-
-* if you can to see only the class name in the generated documentation, add a ~:
-  :class:`~cubicweb.devtools.testlib.AutomaticWebTest`
-
-* you can also use :mod: (module), :exc: (exception), :func: (function), :meth: (method)...
-
-* syntax explained above to specify label explicitly may also be used
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/additionnal_services/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,14 @@
+Additional services
+===================
+
+In this chapter, we introduce services crossing the *web -
+repository - administration* organisation of the first parts of the
+CubicWeb book. Those services can be either proper services (like the
+undo functionality) or mere *topical cross-sections* across CubicWeb.
+
+.. toctree::
+   :maxdepth: 2
+
+   undo
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/additionnal_services/undo.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,337 @@
+Undoing changes in CubicWeb
+---------------------------
+
+Many desktop applications offer the possibility for the user to
+undo its last changes : this *undo feature* has now been
+integrated into the CubicWeb framework. This document will
+introduce you to the *undo feature* both from the end-user and the
+application developer point of view.
+
+But because a semantic web application and a common desktop
+application are not the same thing at all, especially as far as
+undoing is concerned, we will first introduce *what* is the *undo
+feature* for now.
+
+What's *undoing* in a CubicWeb application
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+What is an *undo feature* is quite intuitive in the context of a
+desktop application. But it is a bit subtler in the context of a
+Semantic Web application. This section introduces some of the main
+differences between a classical desktop and a Semantic Web
+applications to keep in mind in order to state precisely *what we
+want*.
+
+The notion transactions
+```````````````````````
+
+A CubicWeb application acts upon an *Entity-Relationship* model,
+described by a schema. This allows to ensure some data integrity
+properties. It also implies that changes are made by all-or-none
+groups called *transactions*, such that the data integrity is
+preserved whether the transaction is completely applied *or* none
+of it is applied.
+
+A transaction can thus include more actions than just those
+directly required by the main purpose of the user.  For example,
+when a user *just* writes a new blog entry, the underlying
+*transaction* holds several *actions* as illustrated below :
+
+* By admin on 2012/02/17 15:18 - Created Blog entry : Torototo
+
+  #. Created Blog entry : Torototo
+  #. Added relation : Torototo owned by admin
+  #. Added relation : Torototo blog entry of Undo Blog
+  #. Added relation : Torototo in state draft (draft)
+  #. Added relation : Torototo created by admin
+
+Because of the very nature (all-or-none) of the transactions, the
+"undoable stuff" are the transactions and not the actions !
+
+Public and private actions within a transaction
+```````````````````````````````````````````````
+
+Actually, within the *transaction* "Created Blog entry :
+Torototo", two of those *actions* are said to be *public* and
+the others are said to be *private*. *Public* here means that the
+public actions (1 and 3) were directly requested by the end user ;
+whereas *private* means that the other actions (2, 4, 5) were
+triggered "under the hood" to fulfill various requirements for the
+user operation (ensuring integrity, security, ... ).
+
+And because quite a lot of actions can be triggered by a "simple"
+end-user request, most of which the end-user is not (and does not
+need or wish to be) aware, only the so-called public actions will
+appear [1]_ in the description of the an undoable transaction.
+
+* By admin on 2012/02/17 15:18 - Created Blog entry : Torototo
+
+  #. Created Blog entry : Torototo
+  #. Added relation : Torototo blog entry of Undo Blog
+
+But note that both public and private actions will be undone
+together when the transaction is undone.
+
+(In)dependent transactions : the simple case
+````````````````````````````````````````````
+
+A CubicWeb application can be used *simultaneously* by different users
+(whereas a single user works on an given office document at a
+given time), so that there is not always a single history
+time-line in the CubicWeb case. Moreover CubicWeb provides
+security through the mechanism of *permissions* granted to each
+user. This can lead to some transactions *not* being undoable in
+some contexts.
+
+In the simple case two (unprivileged) users Alice and Bob make
+relatively independent changes : then both Alice and Bob can undo
+their changes. But in some case there is a clean dependency
+between Alice's and Bob's actions or between actions of one of
+them. For example let's suppose that :
+
+- Alice has created a blog,
+- then has published a first post inside,
+- then Bob has published a second post in the same blog,
+- and finally Alice has updated its post contents.
+
+Then it is clear that Alice can undo her contents changes and Bob
+can undo his post creation independently. But Alice can not undo
+her post creation while she has not first undone her changes.
+It is also clear that Bob should *not* have the
+permissions to undo any of Alice's transactions.
+
+
+More complex dependencies between transactions
+``````````````````````````````````````````````
+
+But more surprising things can quickly happen. Going back to the
+previous example, Alice *can* undo the creation of the blog after
+Bob has published its post in it ! But this is possible only
+because the schema does not *require* for a post to be in a
+blog. Would the *blog entry of* relation have been mandatory, then
+Alice could not have undone the blog creation because it would
+have broken integrity constraint for Bob's post.
+
+When a user attempts to undo a transaction the system will check
+whether a later transaction has explicit dependency on the
+would-be-undone transaction. In this case the system will not even
+attempt the undo operation and inform the user.
+
+If no such dependency is detected the system will attempt the undo
+operation but it can fail, typically because of integrity
+constraint violations. In such a case the undo operation is
+completely [3]_ rollbacked.
+
+
+The *undo feature* for CubicWeb end-users
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The exposition of the undo feature to the end-user through a Web
+interface is still quite basic and will be improved toward a
+greater usability. But it is already fully functional.  For now
+there are two ways to access the *undo feature* as long as the it
+has been activated in the instance configuration file with the
+option *undo-support=yes*.
+
+Immediately after having done the change to be canceled through
+the **undo** link in the message. This allows to undo an
+hastily action immediately. For example, just after having
+validated the creation of the blog entry *A second blog entry* we
+get the following message, allowing to undo the creation.
+
+.. image:: /images/undo_mesage_w600.png
+   :width: 600px
+   :alt: Screenshot of the undo link in the message
+   :align: center
+
+At any time we can access the **undo-history view** accessible from the
+start-up page.
+
+.. image:: /images/undo_startup-link_w600.png
+   :width: 600px
+   :alt: Screenshot of the startup menu with access to the history view
+   :align: center
+
+This view will provide inspection of the transaction and their (public)
+actions. Each transaction provides its own **undo** link. Only the
+transactions the user has permissions to see and undo will be shown.
+
+.. image:: /images/undo_history-view_w600.png
+   :width: 600px
+   :alt: Screenshot of the undo history main view
+   :align: center
+
+If the user attempts to undo a transaction which can't be undone or
+whose undoing fails, then a message will explain the situation and
+no partial undoing will be left behind.
+
+This is all for the end-user side of the undo mechanism : this is
+quite simple indeed ! Now, in the following section, we are going
+to introduce the developer side of the undo mechanism.
+
+The *undo feature* for CubicWeb application developers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A word of warning : this section is intended for developers,
+already having some knowledge of what's under CubicWeb's hood. If
+it is not *yet* the case, please refer to CubicWeb documentation
+http://docs.cubicweb.org/ .
+
+Overview
+````````
+
+The core of the undo mechanisms is at work in the *native source*,
+beyond the RQL. This does mean that *transactions* and *actions*
+are *no entities*. Instead they are represented at the SQL level
+and exposed through the *DB-API* supported by the repository
+*Connection* objects.
+
+Once the *undo feature* has been activated in the instance
+configuration file with the option *undo-support=yes*, each
+mutating operation (cf. [2]_) will be recorded in some special SQL
+table along with its associated transaction. Transaction are
+identified by a *txuuid* through which the functions of the
+*DB-API* handle them.
+
+On the web side the last commited transaction *txuuid* is
+remembered in the request's data to allow for imediate undoing
+whereas the *undo-history view* relies upon the *DB-API* to list
+the accessible transactions. The actual undoing is performed by
+the *UndoController* accessible at URL of the form
+`www.my.host/my/instance/undo?txuuid=...`
+
+The repository side
+```````````````````
+
+Please refer to the file `cubicweb/server/sources/native.py` and
+`cubicweb/transaction.py` for the details.
+
+The undoing information is mainly stored in three SQL tables:
+
+`transactions`
+    Stores the txuuid, the user eid and the date-and-time of
+    the transaction. This table is referenced by the two others.
+
+`tx_entity_actions`
+    Stores the undo information for actions on entities.
+
+`tx_relation_actions`
+    Stores the undo information for the actions on relations.
+
+When the undo support is activated, entries are added to those
+tables for each mutating operation on the data repository, and are
+deleted on each transaction undoing.
+
+Those table are accessible through the following methods of the
+repository `Connection` object :
+
+`undoable_transactions`
+    Returns a list of `Transaction` objects accessible to the user
+    and according to the specified filter(s) if any.
+
+`tx_info`
+    Returns a `Transaction` object from a `txuuid`
+
+`undo_transaction`
+    Returns the list of `Action` object for the given `txuuid`.
+
+    NB:  By default it only return *public* actions.
+
+The web side
+````````````
+
+The exposure of the *undo feature* to the end-user through the Web
+interface relies on the *DB-API* introduced above. This implies
+that the *transactions* and *actions* are not *entities* linked by
+*relations* on which the usual views can be applied directly.
+
+That's why the file `cubicweb/web/views/undohistory.py` defines
+some dedicated views to access the undo information :
+
+`UndoHistoryView`
+    This is a *StartupView*, the one accessible from the home
+    page of the instance which list all transactions.
+
+`UndoableTransactionView`
+    This view handles the display of a single `Transaction` object.
+
+`UndoableActionBaseView`
+    This (abstract) base class provides private methods to build
+    the display of actions whatever their nature.
+
+`Undoable[Add|Remove|Create|Delete|Update]ActionView`
+    Those views all inherit from `UndoableActionBaseView` and
+    each handles a specific kind of action.
+
+`UndoableActionPredicate`
+    This predicate is used as a *selector* to pick the appropriate
+    view for actions.
+
+Apart from this main *undo-history view* a `txuuid` is stored in
+the request's data `last_undoable_transaction` in order to allow
+immediate undoing of a hastily validated operation. This is
+handled in `cubicweb/web/application.py` in the `main_publish` and
+`add_undo_link_to_msg` methods for the storing and displaying
+respectively.
+
+Once the undo information is accessible, typically through a
+`txuuid` in an *undo* URL, the actual undo operation can be
+performed by the `UndoController` defined in
+`cubicweb/web/views/basecontrollers.py`. This controller basically
+extracts the `txuuid` and performs a call to `undo_transaction` and
+in case of an undo-specific error, lets the top level publisher
+handle it as a validation error.
+
+
+Conclusion
+~~~~~~~~~~
+
+The undo mechanism relies upon a low level recording of the
+mutating operation on the repository. Those records are accessible
+through some method added to the *DB-API* and exposed to the
+end-user either through a whole history view of through an
+immediate undoing link in the message box.
+
+The undo feature is functional but the interface and configuration
+options are still quite reduced. One major improvement would be to
+be able to filter with a finer grain which transactions or actions
+one wants to see in the *undo-history view*. Another critical
+improvement would be to enable the undo feature on a part only of
+the entity-relationship schema to avoid storing too much useless
+data and reduce the underlying overhead.
+
+But both functionality are related to the strong design choice not
+to represent transactions and actions as entities and
+relations. This has huge benefits in terms of safety and conceptual
+simplicity but prevents from using lots of convenient CubicWeb
+features such as *facets* to access undo information.
+
+Before developing further the undo feature or eventually revising
+this design choice, it appears that some return of experience is
+strongly needed. So don't hesitate to try the undo feature in your
+application and send us some feedback.
+
+
+Notes
+~~~~~
+
+.. [1] The end-user Web interface could be improved to enable
+       user to choose whether he wishes to see private actions.
+
+.. [2] There is only five kind of elementary actions (beyond
+       merely accessing data for reading):
+
+       * **C** : creating an entity
+       * **D** : deleting an entity
+       * **U** : updating an entity attributes
+       * **A** : adding a relation
+       * **R** : removing a relation
+
+.. [3] Meaning none of the actions in the transaction is
+       undone. Depending upon the application, it might make sense
+       to enable *partial* undo. That is to say undo in which some
+       actions could not be undo without preventing to undo the
+       others actions in the transaction (as long as it does not
+       break schema integrity). This is not forbidden by the
+       back-end but is deliberately not supported by the front-end
+       (for now at least).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/additional-tips.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,64 @@
+
+.. _Additional Tips:
+
+Backups (mostly with postgresql)
+--------------------------------
+
+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.
+
+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
+
+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
+
+Using :command:`cubicweb-ctl db-dump`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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>
+
+The postgres documentation for the `.pgpass` format can be found `here`_
+
+Then add the following command to the crontab of the user (`crontab -e`)::
+
+    # m h  dom mon dow   command
+    0 2 * * * cubicweb-ctl db-dump <instance>
+
+
+Backup ninja
+~~~~~~~~~~~~
+
+You can use a combination `backup-ninja`_ (which has a postgres script in the
+example directory), `backuppc`)_ (for versionning).
+
+Please note that in the *CubicWeb way* it adds a second location for your
+password which is error-prone.
+
+.. _`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).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/config.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,229 @@
+.. -*- coding: utf-8 -*-
+
+.. _ConfigEnv:
+
+Set-up of a *CubicWeb* environment
+==================================
+
+You can `configure the database`_ system of your choice:
+
+  - `PostgreSQL configuration`_
+  - `MySql configuration`_
+  - `SQLServer configuration`_
+  - `SQLite configuration`_
+
+For advanced features, have a look to:
+
+  - `Cubicweb resources configuration`_
+
+.. _`configure the database`: DatabaseInstallation_
+.. _`PostgreSQL configuration`: PostgresqlConfiguration_
+.. _`MySql configuration`: MySqlConfiguration_
+.. _`SQLServer configuration`: SQLServerConfiguration_
+.. _`SQLite configuration`: SQLiteConfiguration_
+.. _`Cubicweb resources configuration`: RessourcesConfiguration_
+
+
+
+.. _RessourcesConfiguration:
+
+Cubicweb resources configuration
+--------------------------------
+
+.. autodocstring:: cubicweb.cwconfig
+
+
+.. _DatabaseInstallation:
+
+Databases configuration
+-----------------------
+
+Each instance can be configured with its own database connection information,
+that will be stored in the instance's :file:`sources` file. The database to use
+will be chosen when creating the instance. CubicWeb is known to run with
+Postgresql (recommended), SQLServer and SQLite, and may run with MySQL.
+
+Other possible sources of data include CubicWeb, Subversion, LDAP and Mercurial,
+but at least one relational database is required for CubicWeb to work. You do
+not need to install a backend that you do not intend to use for one of your
+instances. SQLite is not fit for production use, but it works well for testing
+and ships with Python, which saves installation time when you want to get
+started quickly.
+
+.. _PostgresqlConfiguration:
+
+PostgreSQL
+~~~~~~~~~~
+
+Many Linux distributions ship with the appropriate PostgreSQL packages.
+Basically, you need to install the following packages:
+
+* `postgresql` and `postgresql-client`, which will pull the respective
+  versioned packages (e.g. `postgresql-9.1` and `postgresql-client-9.1`) and,
+  optionally,
+* a `postgresql-plpython-X.Y` package with a version corresponding to that of
+  the aforementioned packages (e.g. `postgresql-plpython-9.1`).
+
+If you run postgres version prior to 8.3, you'll also need the
+`postgresql-contrib-8.X` package for full-text search extension.
+
+If you run postgres on another host than the |cubicweb| repository, you should
+install the `postgresql-client` package on the |cubicweb| host, and others on the
+database host.
+
+For extra details concerning installation, please refer to the `PostgreSQL
+project online documentation`_.
+
+.. _`PostgreSQL project online documentation`: http://www.postgresql.org/docs
+
+
+Database cluster
+++++++++++++++++
+
+If you already have an existing cluster and PostgreSQL server running, you do
+not need to execute the initilization step of your PostgreSQL database unless
+you want a specific cluster for |cubicweb| databases or if your existing
+cluster doesn't use the UTF8 encoding (see note below).
+
+To initialize a PostgreSQL cluster, use the command ``initdb``::
+
+    $ initdb -E UTF8 -D /path/to/pgsql
+
+Notice the encoding specification. This is necessary since |cubicweb| usually
+want UTF8 encoded database. If you use a cluster with the wrong encoding, you'll
+get error like::
+
+  new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)
+  HINT:  Use the same encoding as in the template database, or use template0 as template.
+
+Once initialized, start the database server PostgreSQL with the command::
+
+  $ postgres -D /path/to/psql
+
+If you cannot execute this command due to permission issues, please make sure
+that your username has write access on the database.  ::
+
+  $ chown username /path/to/pgsql
+
+Database authentication
++++++++++++++++++++++++
+
+The database authentication is configured in `pg_hba.conf`. It can be either set
+to `ident sameuser` or `md5`.  If set to `md5`, make sure to use an existing
+user of your database.  If set to `ident sameuser`, make sure that your client's
+operating system user name has a matching user in the database. If not, please
+do as follow to create a user::
+
+  $ su
+  $ su - postgres
+  $ createuser -s -P username
+
+The option `-P` (for password prompt), will encrypt the password with the
+method set in the configuration file :file:`pg_hba.conf`.  If you do not use this
+option `-P`, then the default value will be null and you will need to set it
+with::
+
+  $ su postgres -c "echo ALTER USER username WITH PASSWORD 'userpasswd' | psql"
+
+The above login/password will be requested when you will create an instance with
+`cubicweb-ctl create` to initialize the database of your instance.
+
+Notice that the `cubicweb-ctl db-create` does database initialization that
+may requires a postgres superuser. That's why a login/password is explicitly asked
+at this step, so you can use there a superuser without using this user when running
+the instance. Things that require special privileges at this step:
+
+* database creation, require the 'create database' permission
+* install the plpython extension language (require superuser)
+* install the tsearch extension for postgres version prior to 8.3 (require superuser)
+
+To avoid using a super user each time you create an install, a nice trick is to
+install plpython (and tsearch when needed) on the special `template1` database,
+so they will be installed automatically when cubicweb databases are created
+without even with needs for special access rights. To do so, run ::
+
+  # Installation of plpythonu language by default ::
+  $ createlang -U pgadmin plpythonu template1
+  $ psql -U pgadmin template1
+  template1=# update pg_language set lanpltrusted=TRUE where lanname='plpythonu';
+
+Where `pgadmin` is a postgres superuser. The last command is necessary since by
+default plpython is an 'untrusted' language and as such can't be used by non
+superuser. This update fix that problem by making it trusted.
+
+To install the tsearch plain-text index extension on postgres prior to 8.3, run::
+
+    cat /usr/share/postgresql/8.X/contrib/tsearch2.sql | psql -U username template1
+
+
+.. _MySqlConfiguration:
+
+MySql
+~~~~~
+.. warning::
+    CubicWeb's MySQL support is not commonly used, so things may or may not work properly.
+
+You must add the following lines in ``/etc/mysql/my.cnf`` file::
+
+    transaction-isolation=READ-COMMITTED
+    default-storage-engine=INNODB
+    default-character-set=utf8
+    max_allowed_packet = 128M
+
+.. Note::
+    It is unclear whether mysql supports indexed string of arbitrary length or
+    not.
+
+
+.. _SQLServerConfiguration:
+
+SQLServer
+~~~~~~~~~
+
+As of this writing, support for SQLServer 2005 is functional but incomplete. You
+should be able to connect, create a database and go quite far, but some of the
+SQL generated from RQL queries is still currently not accepted by the
+backend. Porting to SQLServer 2008 is also an item on the backlog.
+
+The `source` configuration file may look like this (specific parts only are
+shown)::
+
+  [system]
+  db-driver=sqlserver2005
+  db-user=someuser
+  # database password not needed
+  #db-password=toto123
+  #db-create/init may ask for a pwd: just say anything
+  db-extra-arguments=Trusted_Connection
+  db-encoding=utf8
+
+
+You need to change the default settings on the database by running::
+
+ ALTER DATABASE <databasename> SET READ_COMMITTED_SNAPSHOT ON;
+
+The ALTER DATABASE command above requires some permissions that your
+user may not have. In that case you will have to ask your local DBA to
+run the query for you.
+
+You can check that the setting is correct by running the following
+query which must return '1'::
+
+   SELECT is_read_committed_snapshot_on
+     FROM sys.databases WHERE name='<databasename>';
+
+
+
+.. _SQLiteConfiguration:
+
+SQLite
+~~~~~~
+
+SQLite has the great advantage of requiring almost no configuration. Simply
+use 'sqlite' as db-driver, and set path to the dabase as db-name. Don't specify
+anything for db-user and db-password, they will be ignore anyway.
+
+.. Note::
+  SQLite is great for testing and to play with cubicweb but is not suited for
+  production environments.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/create-instance.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,100 @@
+.. -*- coding: utf-8 -*-
+
+Creation of your first instance
+===============================
+
+Instance creation
+-----------------
+
+Now that we created a cube, we can create an instance and access it via a web
+browser. We will use a `all-in-one` configuration to simplify things ::
+
+  cubicweb-ctl create -c all-in-one mycube myinstance
+
+.. note::
+  Please note that we created a new cube for a demo purposes but
+  you could have used an existing cube available in our standard library
+  such as blog or person for example.
+
+A series of questions will be prompted to you, the default answer is usually
+sufficient. You can anyway modify the configuration later on by editing
+configuration files. When a login/password are requested to access the database
+please use the credentials you created at the time you configured the database
+(:ref:`PostgresqlConfiguration`).
+
+It is important to distinguish here the user used to access the database and the
+user used to login to the cubicweb instance. When an instance starts, it uses
+the login/password for the database to get the schema and handle low level
+transaction. But, when :command:`cubicweb-ctl create` asks for a manager
+login/psswd of *CubicWeb*, it refers to the user you will use during the
+development to administrate your web instance. It will be possible, later on,
+to use this user to create other users for your final web instance.
+
+
+Instance administration
+-----------------------
+
+start / stop
+~~~~~~~~~~~~
+
+When this command is completed, the definition of your instance is
+located in :file:`~/etc/cubicweb.d/myinstance/*`. To launch it, you
+just type ::
+
+  cubicweb-ctl start -D myinstance
+
+The option `-D` specifies the *debug mode* : the instance is not
+running in server mode and does not disconnect from the terminal,
+which simplifies debugging in case the instance is not properly
+launched. You can see how it looks by visiting the URL
+`http://localhost:8080` (the port number depends of your
+configuration). To login, please use the cubicweb administrator
+login/password you defined when you created the instance.
+
+To shutdown the instance, Crtl-C in the terminal window is enough.
+If you did not use the option `-D`, then type ::
+
+  cubicweb-ctl stop myinstance
+
+This is it! All is settled down to start developping your data model...
+
+.. note::
+
+  The output of `cubicweb-ctl start -D myinstance` can be
+  overwhelming. It is possible to reduce the log level with the
+  `--loglevel` parameter as in `cubicweb-ctl start -D myinstance -l
+  info` to filter out all logs under `info` gravity.
+
+upgrade
+~~~~~~~
+
+A manual upgrade step is necessary whenever a new version of CubicWeb or
+a cube is installed, in order to synchronise the instance's
+configuration and schema with the new code.  The command is::
+
+  cubicweb-ctl upgrade myinstance
+
+A series of questions will be asked. It always starts with a proposal
+to make a backup of your sources (where it applies). Unless you know
+exactly what you are doing (i.e. typically fiddling in debug mode, but
+definitely NOT migrating a production instance), you should answer YES
+to that.
+
+The remaining questions concern the migration steps of |cubicweb|,
+then of the cubes that form the whole application, in reverse
+dependency order.
+
+In principle, if the migration scripts have been properly written and
+tested, you should answer YES to all questions.
+
+Somtimes, typically while debugging a migration script, something goes
+wrong and the migration fails. Unfortunately the databse may be in an
+incoherent state. You have two options here:
+
+* fix the bug, restore the database and restart the migration process
+  from scratch (quite recommended in a production environement)
+
+* try to replay the migration up to the last successful commit, that
+  is answering NO to all questions up to the step that failed, and
+  finish by answering YES to the remaining questions.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/cubicweb-ctl.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,111 @@
+.. -*- coding: utf-8 -*-
+
+.. _cubicweb-ctl:
+
+``cubicweb-ctl`` tool
+=====================
+
+`cubicweb-ctl` is the swiss knife to manage *CubicWeb* instances.
+The general syntax is ::
+
+  cubicweb-ctl <command> [options command] <arguments commands>
+
+To view available commands ::
+
+  cubicweb-ctl
+  cubicweb-ctl --help
+
+Please note that the commands available depends on the *CubicWeb* packages
+and cubes that have been installed.
+
+To view the help menu on specific command ::
+
+  cubicweb-ctl <command> --help
+
+Listing available cubes and instance
+-------------------------------------
+
+* ``list``, provides a list of the available configuration, cubes
+  and instances.
+
+
+Creation of a new cube
+-----------------------
+
+Create your new cube cube ::
+
+   cubicweb-ctl newcube
+
+This will create a new cube in
+``/path/to/grshell-cubicweb/cubes/<mycube>`` for a Mercurial
+installation, or in ``/usr/share/cubicweb/cubes`` for a debian
+packages installation.
+
+Create an instance
+-------------------
+
+You must ensure `~/etc/cubicweb.d/` exists prior to this. On windows, the
+'~' part will probably expand to 'Documents and Settings/user'.
+
+To create an instance from an existing cube, execute the following
+command ::
+
+   cubicweb-ctl create <cube_name> <instance_name>
+
+This command will create the configuration files of an instance in
+``~/etc/cubicweb.d/<instance_name>``.
+
+The tool ``cubicweb-ctl`` executes the command ``db-create`` and
+``db-init`` when you run ``create`` so that you can complete an
+instance creation in a single command. But of course it is possible
+to issue these separate commands separately, at a later stage.
+
+Command to create/initialize an instance database
+-------------------------------------------------
+
+* ``db-create``, creates the system database of an instance (tables and
+  extensions only)
+* ``db-init``, initializes the system database of an instance
+  (schema, groups, users, workflows...)
+
+Commands to control instances
+-----------------------------
+
+* ``start``, starts one or more or all instances
+
+of special interest::
+
+  start -D
+
+will start in debug mode (under windows, starting without -D will not
+work; you need instead to setup your instance as a service).
+
+* ``stop``, stops one or more or all instances
+* ``restart``, restarts one or more or all instances
+* ``status``, returns the status of the instance(s)
+
+Commands to maintain instances
+------------------------------
+
+* ``upgrade``, launches the existing instances migration when a new version
+  of *CubicWeb* or the cubes installed is available
+* ``shell``, opens a (Python based) migration shell for manual maintenance of the instance
+* ``db-dump``, creates a dump of the system database
+* ``db-restore``, restores a dump of the system database
+* ``db-check``, checks data integrity of an instance. If the automatic correction
+  is activated, it is recommanded to create a dump before this operation.
+* ``schema-sync``, synchronizes the persistent schema of an instance with
+  the instance schema. It is recommanded to create a dump before this operation.
+
+Commands to maintain i18n catalogs
+----------------------------------
+* ``i18ncubicweb``, regenerates messages catalogs of the *CubicWeb* library
+* ``i18ncube``, regenerates the messages catalogs of a cube
+* ``i18ninstance``, recompiles the messages catalogs of an instance.
+  This is automatically done while upgrading.
+
+See also chapter :ref:`internationalization`.
+
+Other commands
+--------------
+* ``delete``, deletes an instance (configuration files and database)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,28 @@
+.. -*- coding: utf-8 -*-
+
+.. _Part3:
+
+--------------
+Administration
+--------------
+
+This part is for installation and administration of the *CubicWeb* framework and
+instances based on that framework.
+
+.. toctree::
+   :maxdepth: 1
+   :numbered:
+
+   setup
+   setup-windows
+   config
+   cubicweb-ctl
+   create-instance
+   instance-config
+   site-config
+   multisources
+   ldap
+   migration
+   additional-tips
+   rql-logs
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/instance-config.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,200 @@
+.. -*- coding: utf-8 -*-
+
+
+Configure an instance
+=====================
+
+While creating an instance, a configuration file is generated in::
+
+    $ (CW_INSTANCES_DIR) / <instance> / <configuration name>.conf
+
+For example::
+
+    /etc/cubicweb.d/myblog/all-in-one.conf
+
+It is a simple text file in the INI format
+(http://en.wikipedia.org/wiki/INI_file). In the following description,
+each option name is prefixed with its own section and followed by its
+default value if necessary, e.g. "`<section>.<option>` [value]."
+
+.. _`WebServerConfig`:
+
+Configuring the Web server
+--------------------------
+:`web.auth-model` [cookie]:
+    authentication mode, cookie or http
+:`web.realm`:
+    realm of the instance in http authentication mode
+:`web.http-session-time` [0]:
+    period of inactivity of an HTTP session before it closes automatically.
+    Duration in seconds, 0 meaning no expiration (or more exactly at the
+    closing of the browser client)
+
+:`main.anonymous-user`, `main.anonymous-password`:
+    login and password to use to connect to the RQL server with
+    HTTP anonymous connection. CWUser account should exist.
+
+:`main.base-url`:
+    url base site to be used to generate the urls of web pages
+
+Https configuration
+```````````````````
+It is possible to make a site accessible for anonymous http connections
+and https for authenticated users. This requires to
+use apache (for example) for redirection and the variable `main.https-url`
+of configuration file.
+
+For this to work you have to activate the following apache modules :
+
+* rewrite
+* proxy
+* http_proxy
+
+The command on Debian based systems for that is ::
+
+  a2enmod rewrite http_proxy proxy
+  /etc/init.d/apache2 restart
+
+:Example:
+
+   For an apache redirection of a site accessible via `http://localhost/demo`
+   and `https://localhost/demo` and actually running on port 8080, it
+   takes to the http:::
+
+     ProxyPreserveHost On
+     RewriteEngine On
+     RewriteCond %{REQUEST_URI} ^/demo
+     RewriteRule ^/demo$ /demo/
+     RewriteRule ^/demo/(.*) http://127.0.0.1:8080/$1 [L,P]
+
+   and for the https:::
+
+     ProxyPreserveHost On
+     RewriteEngine On
+     RewriteCond %{REQUEST_URI} ^/ demo
+     RewriteRule ^/demo$/demo/
+     RewriteRule ^/demo/(.*) http://127.0.0.1:8080/https/$1 [L,P]
+
+
+   and we will file in the all-in-one.conf of the instance:::
+
+     base-url = http://localhost/demo
+     https-url = https://localhost/demo
+
+Notice that if you simply want a site accessible through https, not *both* http
+and https, simply set `base-url` to the https url and the first section into your
+apache configuration (as you would have to do for an http configuration with an
+apache front-end).
+
+Setting up the web client
+-------------------------
+:`web.embed-allowed`:
+    regular expression matching sites which could be "embedded" in
+    the site (controllers 'embed')
+:`web.submit-url`:
+    url where the bugs encountered in the instance can be mailed to
+
+
+RQL server configuration
+------------------------
+:`main.host`:
+    host name if it can not be detected correctly
+:`main.pid-file`:
+    file where will be written the server pid
+:`main.uid`:
+    user account to use for launching the server when it is
+    root launched by init
+:`main.session-time [30*60]`:
+    timeout of a RQL session
+:`main.query-log-file`:
+    file where all requests RQL executed by the server are written
+
+
+Configuring e-mail
+------------------
+RQL and web server side:
+
+:`email.mangle-mails [no]`:
+    indicates whether the email addresses must be displayed as is or
+    transformed
+
+RQL server side:
+
+:`email.smtp-host [mail]`:
+    hostname hosting the SMTP server to use for outgoing mail
+:`email.smtp-port [25]`:
+    SMTP server port to use for outgoing mail
+:`email.sender-name`:
+    name to use for outgoing mail of the instance
+:`email.sender-addr`:
+    address for outgoing mail of the instance
+:`email.default dest-addrs`:
+    destination addresses by default, if used by the configuration of the
+    dissemination of the model (separated by commas)
+:`email.supervising-addrs`:
+    destination addresses of e-mails of supervision (separated by
+    commas)
+
+
+Configuring logging
+-------------------
+:`main.log-threshold`:
+    level of filtering messages (DEBUG, INFO, WARNING, ERROR)
+:`main.log-file`:
+    file to write messages
+
+
+.. _PersistentProperties:
+
+Configuring persistent properties
+---------------------------------
+Other configuration settings are in the form of entities `CWProperty`
+in the database. It must be edited via the web interface or by
+RQL queries.
+
+:`ui.encoding`:
+    Character encoding to use for the web
+:`navigation.short-line-size`:
+    number of characters for "short" display
+:`navigation.page-size`:
+    maximum number of entities to show per results page
+:`navigation.related-limit`:
+    number of related entities to show up on primary entity view
+:`navigation.combobox-limit`:
+    number of entities unrelated to show up on the drop-down lists of
+    the sight on an editing entity view
+
+Cross-Origin Resource Sharing
+-----------------------------
+
+CubicWeb provides some support for the CORS_ protocol. For now, the
+provided implementation only deals with access to a CubicWeb instance
+as a whole. Support for a finer granularity may be considered in the
+future.
+
+Specificities of the provided implementation:
+
+- ``Access-Control-Allow-Credentials`` is always true
+- ``Access-Control-Allow-Origin`` header in response will never be
+  ``*``
+- ``Access-Control-Expose-Headers`` can be configured globally (see below)
+- ``Access-Control-Max-Age`` can be configured globally (see below)
+- ``Access-Control-Allow-Methods`` can be configured globally (see below)
+- ``Access-Control-Allow-Headers`` can be configured globally (see below)
+
+
+A few parameters can be set to configure the CORS_ capabilities of CubicWeb.
+
+.. _CORS: http://www.w3.org/TR/cors/
+
+:`access-control-allow-origin`:
+   comma-separated list of allowed origin domains or "*" for any domain
+:`access-control-allow-methods`:
+   comma-separated list of allowed HTTP methods
+:`access-control-max-age`:
+   maximum age of cross-origin resource sharing (in seconds)
+:`access-control-allow-headers`:
+   comma-separated list of allowed HTTP custom headers (used in simple requests)
+:`access-control-expose-headers`:
+   comma-separated list of allowed HTTP custom headers (used in preflight requests)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/ldap.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,134 @@
+.. _LDAP:
+
+LDAP integration
+================
+
+Overview
+--------
+
+Using LDAP as a source for user credentials and information is quite
+easy. The most difficult part lies in building an LDAP schema or
+using an existing one.
+
+At cube creation time, one is asked if more sources are wanted. LDAP
+is one possible option at this time. Of course, it is always possible
+to set it up later using the `CWSource` entity type, which we discuss
+there.
+
+It is possible to add as many LDAP sources as wanted, which translates
+in as many `CWSource` entities as needed.
+
+The general principle of the LDAP source is, given a proper
+configuration, to create local users matching the users available in
+the directory and deriving local user attributes from directory users
+attributes. Then a periodic task ensures local user information
+synchronization with the directory.
+
+Users handled by such a source should not be edited directly from
+within the application instance itself. Rather, updates should happen
+at the LDAP server level.
+
+Credential checks are _always_ done against the LDAP server.
+
+.. Note::
+
+  There are currently two ldap source types: the older `ldapuser` and
+  the newer `ldapfeed`. The older will be deprecated anytime soon, as
+  the newer has now gained all the features of the old and does not
+  suffer from some of its illnesses.
+
+  The ldapfeed creates real `CWUser` entities, and then
+  activate/deactivate them depending on their presence/absence in the
+  corresponding LDAP source. Their attribute and state
+  (activated/deactivated) are hence managed by the source mechanism;
+  they should not be altered by other means (as such alterations may
+  be overridden in some subsequent source synchronisation).
+
+
+Configuration of an LDAPfeed source
+-----------------------------------
+
+Additional sources are created at cube creation time or later through the
+user interface.
+
+Configure an `ldapfeed` source from the user interface under `Manage` then
+`data sources`:
+
+* At this point `type` has been set to `ldapfeed`.
+
+* The `parser` attribute shall be set to `ldapfeed`.
+
+* The `url` attribute shall be set to an URL such as ldap://ldapserver.domain/.
+
+* The `configuration` attribute contains many options. They are described in
+  detail in the next paragraph.
+
+
+Options of an LDAPfeed source
+-----------------------------
+
+Let us enumerate the options by categories (LDAP server connection,
+LDAP schema mapping information).
+
+LDAP server connection options:
+
+* `auth-mode`, (choices are simple, cram_md5, digest_md5, gssapi, support
+  for the later being partial as of now)
+
+* `auth-realm`, realm to use when using gssapi/kerberos authentication
+
+* `data-cnx-dn`, user dn to use to open data connection to the ldap (eg
+  used to respond to rql queries)
+
+* `data-cnx-password`, password to use to open data connection to the
+  ldap (eg used to respond to rql queries)
+
+If the LDAP server accepts anonymous binds, then it is possible to
+leave data-cnx-dn and data-cnx-password empty. This is, however, quite
+unlikely in practice. Beware that the LDAP server might hide attributes
+such as "userPassword" while the rest of the attributes remain visible
+through an anonymous binding.
+
+LDAP schema mapping options:
+
+* `user-base-dn`, base DN to lookup for users
+
+* `user-scope`, user search scope (valid values: "BASE", "ONELEVEL",
+  "SUBTREE")
+
+* `user-classes`, classes of user (with Active Directory, you want to
+  say "user" here)
+
+* `user-filter`, additional filters to be set in the ldap query to
+  find valid users
+
+* `user-login-attr`, attribute used as login on authentication (with
+  Active Directory, you want to use "sAMAccountName" here)
+
+* `user-default-group`, name of a group in which ldap users will be by
+  default. You can set multiple groups by separating them by a comma
+
+* `user-attrs-map`, map from ldap user attributes to cubicweb
+  attributes (with Active Directory, you want to use
+  sAMAccountName:login,mail:email,givenName:firstname,sn:surname)
+
+
+Other notes
+-----------
+
+* Cubicweb is able to start if ldap cannot be reached, even on
+  cubicweb-ctl start ... If some source ldap server cannot be used
+  while an instance is running, the corresponding users won't be
+  authenticated but their status will not change (e.g. they will not
+  be deactivated)
+
+* The user-base-dn is a key that helps cubicweb map CWUsers to LDAP
+  users: beware updating it
+
+* When a user is removed from an LDAP source, it is deactivated in the
+  CubicWeb instance; when a deactivated user comes back in the LDAP
+  source, it (automatically) is activated again
+
+* You can use the :class:`CWSourceHostConfig` to have variants for a source
+  configuration according to the host the instance is running on. To do so
+  go on the source's view from the sources management view.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/migration.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,38 @@
+.. -*- coding: utf-8 -*-
+
+Migrating cubicweb instances - benefits from a distributed architecture
+=======================================================================
+
+Migrate apache & cubicweb
+-------------------------
+
+**Aim** : do the migration for N cubicweb instances hosted on a server to another with no downtime.
+
+**Prerequisites** : have an explicit definition of the database host (not default or localhost). In our case, the database is hosted on another host.
+
+**Steps** :
+
+1. *on new machine* : install your environment (*pseudocode*) ::
+
+     apt-get install cubicweb cubicweb-applications apache2
+
+2. *on old machine* : copy your cubicweb and apache configuration to the new machine ::
+
+    scp /etc/cubicweb.d/ newmachine:/etc/cubicweb.d/
+    scp /etc/apache2/sites-available/ newmachine:/etc/apache2/sites-available/
+
+3. *on new machine* : start your instances ::
+
+     cubicweb start
+
+4. *on new machine* : enable sites and modules for apache and start it, test it using by modifying your /etc/host file.
+
+5. change dns entry from your oldmachine to newmachine
+
+6. shutdown your *old machine* (if it doesn't host other services or your database)
+
+7. That's it.
+
+**Possible enhancements** : use right from the start a pound server behind your apache, that way you can add backends and smoothily migrate by shuting down backends that pound will take into account.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/multisources.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,6 @@
+Multiple sources of data
+========================
+
+Data sources include SQL, LDAP, RQL, mercurial and subversion.
+
+.. XXX feed me
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/pyro.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,62 @@
+.. _UsingPyro:
+
+Working with a distributed client (using Pyro)
+==============================================
+
+In some circumstances, it is practical to split the repository and
+web-client parts of the application for load-balancing reasons. Or
+one wants to access the repository from independant scripts to consult
+or update the database.
+
+Prerequisites
+-------------
+
+For this to work, several steps have to be taken in order.
+
+You must first ensure that the appropriate software is installed and
+running (see :ref:`ConfigEnv`)::
+
+  pyro-nsd -x -p 6969
+
+Then you have to set appropriate options in your configuration. For
+instance::
+
+  pyro-server=yes
+  pyro-ns-host=localhost:6969
+
+  pyro-instance-id=myinstancename
+
+Connect to the CubicWeb repository from a python script
+-------------------------------------------------------
+
+Assuming pyro-nsd is running and your instance is configured with ``pyro-server=yes``,
+you will be able to use :mod:`cubicweb.dbapi` api to initiate the connection.
+
+.. note::
+    Regardless of whether your instance is pyro activated or not, you can still
+    achieve this by using cubicweb-ctl shell scripts in a simpler way, as by default
+    it creates a repository 'in-memory' instead of connecting through pyro. That
+    also means you've to be on the host where the instance is running.
+
+Finally, the client (for instance a python script) must connect specifically
+as in the following example code:
+
+.. sourcecode:: python
+
+    from cubicweb import dbapi
+
+    cnx = dbapi.connect(database='instance-id', user='admin', password='admin')
+    cnx.load_appobjects()
+    cur = cnx.cursor()
+    for name in (u'Personal', u'Professional', u'Computers'):
+        cur.execute('INSERT Tag T: T name %(n)s', {'n': name})
+    cnx.commit()
+
+Calling :meth:`cubicweb.dbapi.load_appobjects`, will populate the
+cubicweb registries (see :ref:`VRegistryIntro`) with the application
+objects installed on the host where the script runs. You'll then be
+allowed to use the ORM goodies and custom entity methods and views. Of
+course this is optional, without it you can still get the repository
+data through the connection but in a roughly way: only RQL cursors
+will be available, e.g. you can't even build entity objects from the
+result set.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/rql-logs.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,14 @@
+.. -*- coding: utf-8 -*-
+
+RQL logs
+========
+
+You can configure the *CubicWeb* instance to keep a log
+of the queries executed against your database. To do so,
+edit the configuration file of your instance
+``.../etc/cubicweb.d/myapp/all-in-one.conf`` and uncomment the
+variable ``query-log-file``::
+
+  # web instance query log file
+  query-log-file=/tmp/rql-myapp.log
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/setup-windows.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,146 @@
+.. -*- coding: utf-8 -*-
+
+.. _SetUpWindowsEnv:
+
+Installing a development environement on Windows
+================================================
+
+Setting up a Windows development environment is not too complicated
+but it requires a series of small steps.
+
+We propose an example of a typical |cubicweb| installation on Windows
+from sources. We assume everything goes into ``C:\\`` and for any
+package, without version specification, "the latest is
+the greatest".
+
+Mind that adjusting the installation drive should be straightforward.
+
+
+
+Install the required elements
+-----------------------------
+
+|cubicweb| requires some base elements that must be installed to run
+correctly. So, first of all, you must install them :
+
+* python >= 2.6 and < 3
+  (`Download Python <http://www.python.org/download/>`_).
+  You can also consider the Python(x,y) distribution
+  (`Download Python(x,y) <http://code.google.com/p/pythonxy/wiki/Downloads>`_)
+  as it makes things easier for Windows user by wrapping in a single installer
+  python 2.7 plus numerous useful third-party modules and
+  applications (including Eclipse + pydev, which is an arguably good
+  IDE for Python under Windows).
+
+* `Twisted <http://twistedmatrix.com/trac/>`_ is an event-driven
+  networking engine
+  (`Download Twisted <http://twistedmatrix.com/trac/>`_)
+
+* `lxml <http://codespeak.net/lxml/>`_ library
+  (version >=2.2.1) allows working with XML and HTML
+  (`Download lxml <http://pypi.python.org/pypi/lxml/2.2.1>`_)
+
+* `Postgresql <http://www.postgresql.org/>`_,
+  an object-relational database system
+  (`Download Postgresql <http://www.enterprisedb.com/products/pgdownload.do#windows>`_)
+  and its python drivers
+  (`Download psycopg <http://www.stickpeople.com/projects/python/win-psycopg/#Version2>`_)
+
+* A recent version of `gettext`
+  (`Download gettext <http://download.logilab.org/pub/gettext/gettext-0.17-win32-setup.exe>`_).
+
+* `rql <http://www.logilab.org/project/rql>`_,
+  the recent version of the Relationship Query Language parser.
+
+Install optional elements
+-------------------------
+
+We recommend you to install the following elements. They are not
+mandatory but they activate very interesting features in |cubicweb|:
+
+* `python-ldap <http://pypi.python.org/pypi/python-ldap>`_
+  provides access to LDAP/Active directory directories
+  (`Download python-ldap <http://www.osuch.org/python-ldap>`_).
+
+* `graphviz <http://www.graphviz.org/>`_
+  which allow schema drawings.
+  (`Download graphviz <http://www.graphviz.org/Download_windows.php>`_).
+  It is quite recommended (albeit not mandatory).
+
+Other elements will activate more features once installed. Take a look
+at :ref:`InstallDependencies`.
+
+Useful tools
+------------
+
+Some additional tools could be useful to develop :ref:`cubes <AvailableCubes>`
+with the framework.
+
+* `mercurial <http://mercurial.selenic.com/>`_ and its standard windows GUI
+  (`TortoiseHG <http://tortoisehg.bitbucket.org/>`_) allow you to get the source
+  code of |cubicweb| from control version repositories. So you will be able to
+  get the latest development version and pre-release bugfixes in an easy way
+  (`Download mercurial <http://bitbucket.org/tortoisehg/stable/wiki/download>`_).
+
+* You can also consider the ssh client `Putty` in order to peruse
+  mercurial over ssh (`Download <http://www.putty.org/>`_).
+
+* If you are an Eclipse user, mercurial can be integrated using the
+  `MercurialEclipse` plugin
+  (`Home page <http://www.vectrace.com/mercurialeclipse/>`_).
+
+Getting the sources
+-------------------
+
+There are two ways to get the sources of |cubicweb| and its
+:ref:`cubes <AvailableCubes>`:
+
+* download the latest release (:ref:`SourceInstallation`)
+* get the development version using Mercurial
+  (:ref:`MercurialInstallation`)
+
+Environment variables
+---------------------
+
+You will need some convenience environment variables once all is set up. These
+variables are settable through the GUI by getting at the `System properties`
+window (by righ-clicking on `My Computer` -> `properties`).
+
+In the `advanced` tab, there is an `Environment variables` button. Click on
+it. That opens a small window allowing edition of user-related and system-wide
+variables.
+
+We will consider only user variables. First, the ``PATH`` variable. Assuming
+you are logged as user *Jane*, add the following paths, separated by
+semi-colons::
+
+  C:\Documents and Settings\Jane\My Documents\Python\cubicweb\cubicweb\bin
+  C:\Program Files\Graphviz2.24\bin
+
+The ``PYTHONPATH`` variable should also contain::
+
+  C:\Documents and Settings\Jane\My Documents\Python\cubicweb\
+
+From now, on a fresh `cmd` shell, you should be able to type::
+
+  cubicweb-ctl list
+
+... and get a meaningful output.
+
+Running an instance as a service
+--------------------------------
+
+This currently assumes that the instances configurations is located at
+``C:\\etc\\cubicweb.d``. For a cube 'my_instance', you will find
+``C:\\etc\\cubicweb.d\\my_instance\\win32svc.py``.
+
+Now, register your instance as a windows service with::
+
+  win32svc install
+
+Then start the service with::
+
+  net start cubicweb-my_instance
+
+In case this does not work, you should be able to see error reports in
+the application log, using the windows event log viewer.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/setup.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,269 @@
+.. -*- coding: utf-8 -*-
+
+.. _SetUpEnv:
+
+Installation of a *CubicWeb* environment
+========================================
+
+Official releases are available from the `CubicWeb.org forge`_ and from
+`PyPI`_. Since CubicWeb is developed using `Agile software development
+<http://en.wikipedia.org/wiki/Agile_software_development>`_ techniques, releases
+happen frequently. In a version numbered X.Y.Z, X changes after a few years when
+the API breaks, Y changes after a few weeks when features are added and Z
+changes after a few days when bugs are fixed.
+
+Depending on your needs, you will chose a different way to install CubicWeb on
+your system:
+
+- `Installation on Debian/Ubuntu`_
+- `Installation on Windows`_
+- `Installation in a virtualenv`_
+- `Installation with pip`_
+- `Installation with easy_install`_
+- `Installation from tarball`_
+
+If you are a power-user and need the very latest features, you will
+
+- `Install from version control`_
+
+Once the software is installed, move on to :ref:`ConfigEnv` for better control
+and advanced features of |cubicweb|.
+
+.. _`Installation on Debian/Ubuntu`: DebianInstallation_
+.. _`Installation on Windows`: WindowsInstallation_
+.. _`Installation in a virtualenv`: VirtualenvInstallation_
+.. _`Installation with pip`: PipInstallation_
+.. _`Installation with easy_install`: EasyInstallInstallation_
+.. _`Installation from tarball`: TarballInstallation_
+.. _`Install from version control`: MercurialInstallation_
+
+
+.. _DebianInstallation:
+
+Debian/Ubuntu install
+---------------------
+
+|cubicweb| is packaged for Debian/Ubuntu (and derived
+distributions). Their integrated package-management system make
+installation and upgrade much easier for users since
+dependencies (like databases) are automatically installed.
+
+Depending on the distribution you are using, add the appropriate line to your
+`list of sources` (for example by editing ``/etc/apt/sources.list``).
+
+For Debian 7.0 Wheezy (stable)::
+
+  deb http://download.logilab.org/production/ wheezy/
+
+For Debian Sid (unstable)::
+
+  deb http://download.logilab.org/production/ sid/
+
+For Ubuntu 12.04 Precise Pangolin (Long Term Support) and newer::
+
+  deb http://download.logilab.org/production/ precise/
+
+The repositories are signed with the `Logilab's gnupg key`_. You can download
+and register the key to avoid warnings::
+
+  wget -q http://download.logilab.org/logilab-dists-key.asc -O- | sudo apt-key add -
+
+Update your list of packages and perform the installation::
+
+  apt-get update
+  apt-get install cubicweb cubicweb-dev
+
+``cubicweb`` installs the framework itself, allowing you to create new
+instances. ``cubicweb-dev`` installs the development environment
+allowing you to develop new cubes.
+
+There is also a wide variety of :ref:`cubes <AvailableCubes>`. You can access a
+list of available cubes using ``apt-cache search cubicweb`` or at the
+`CubicWeb.org forge`_.
+
+.. note::
+
+  `cubicweb-dev` will install basic sqlite support. You can easily setup
+  :ref:`cubicweb with other database <DatabaseInstallation>` using the following
+  virtual packages :
+
+  * `cubicweb-postgresql-support` contains the necessary dependencies for
+    using :ref:`cubicweb with postgresql datatabase <PostgresqlConfiguration>`
+
+  * `cubicweb-mysql-support` contains the necessary dependencies for using
+    :ref:`cubicweb with mysql database <MySqlConfiguration>`.
+
+.. _`list of sources`: http://wiki.debian.org/SourcesList
+.. _`Logilab's gnupg key`: http://download.logilab.org/logilab-dists-key.asc
+.. _`CubicWeb.org Forge`: http://www.cubicweb.org/project/
+
+.. _WindowsInstallation:
+
+Windows Install
+---------------
+
+You need to have `python`_ version >= 2.5 and < 3 installed.
+
+If you want an automated install, your best option is probably the
+:ref:`EasyInstallInstallation`. EasyInstall is a tool that helps users to
+install python packages along with their dependencies, searching for suitable
+pre-compiled binaries on the `The Python Package Index`_.
+
+If you want better control over the process as well as a suitable development
+environment or if you are having problems with `easy_install`, read on to
+:ref:`SetUpWindowsEnv`.
+
+.. _python:  http://www.python.org/
+.. _`The Python Package Index`: http://pypi.python.org
+
+.. _VirtualenvInstallation:
+
+`Virtualenv` install
+--------------------
+
+|cubicweb| can be safely installed, used and contained inside a
+`virtualenv`_. You can use either :ref:`pip <PipInstallation>` or
+:ref:`easy_install <EasyInstallInstallation>` to install |cubicweb|
+inside an activated virtual environment.
+
+.. _PipInstallation:
+
+`pip` install
+-------------
+
+`pip <http://pip.openplans.org/>`_ is a python tool that helps downloading,
+building, installing, and managing Python packages and their dependencies. It
+is fully compatible with `virtualenv`_ and installs the packages from sources
+published on the `The Python Package Index`_.
+
+.. _`virtualenv`: http://virtualenv.openplans.org/
+
+A working compilation chain is needed to build the modules that include C
+extensions. If you really do not want to compile anything, installing `lxml <http://lxml.de/>`_,
+`Twisted Web <http://twistedmatrix.com/trac/wiki/Downloads/>`_ and `libgecode
+<http://www.gecode.org/>`_ will help.
+
+For Debian, these minimal dependencies can be obtained by doing::
+
+  apt-get install gcc python-pip python-dev python-lxml
+
+or, if you prefer to get as much as possible from pip::
+
+  apt-get install gcc python-pip python-dev libxslt1-dev libxml2-dev
+
+For Windows, you can install pre-built packages (possible `source
+<http://www.lfd.uci.edu/~gohlke/pythonlibs/>`_). For a minimal setup, install:
+
+- pip http://www.lfd.uci.edu/~gohlke/pythonlibs/#pip
+- setuptools http://www.lfd.uci.edu/~gohlke/pythonlibs/#setuptools
+- libxml-python http://www.lfd.uci.edu/~gohlke/pythonlibs/#libxml-python>
+- lxml http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml and
+- twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
+
+Make sure to choose the correct architecture and version of Python.
+
+Finally, install |cubicweb| and its dependencies, by running::
+
+  pip install cubicweb
+
+Many other :ref:`cubes <AvailableCubes>` are available. A list is available at
+`PyPI <http://pypi.python.org/pypi?%3Aaction=search&term=cubicweb&submit=search>`_
+or at the `CubicWeb.org forge`_.
+
+For example, installing the *blog cube* is achieved by::
+
+  pip install cubicweb-blog
+
+.. _EasyInstallInstallation:
+
+`easy_install` install
+----------------------
+
+.. note::
+
+   If you are not a Windows user and you have a compilation environment, we
+   recommend you to use the PipInstallation_.
+
+`easy_install`_ is a python utility that helps downloading, installing, and
+managing python packages and their dependencies.
+
+Install |cubicweb| and its dependencies, run::
+
+  easy_install cubicweb
+
+There is also a wide variety of :ref:`cubes <AvailableCubes>`. You can access a
+list of available cubes on `PyPI
+<http://pypi.python.org/pypi?%3Aaction=search&term=cubicweb&submit=search>`_
+or at the `CubicWeb.org Forge`_.
+
+For example, installing the *blog cube* is achieved by::
+
+  easy_install cubicweb-blog
+
+.. note::
+
+  If you encounter problem with :ref:`cubes <AvailableCubes>` installation,
+  consider using :ref:`PipInstallation` which is more stable
+  but can not installed pre-compiled binaries.
+
+.. _`easy_install`: http://packages.python.org/distribute/easy_install.html
+
+
+.. _SourceInstallation:
+
+Install from source
+-------------------
+
+.. _TarballInstallation:
+
+You can download the archive containing the sources from
+`http://download.logilab.org/pub/cubicweb/ <http://download.logilab.org/pub/cubicweb/>`_.
+
+Make sure you also have all the :ref:`InstallDependencies`.
+
+Once uncompressed, you can install the framework from inside the uncompressed
+folder with::
+
+  python setup.py install
+
+Or you can run |cubicweb| directly from the source directory by
+setting the :ref:`resource mode <RessourcesConfiguration>` to `user`. This will
+ease the development with the framework.
+
+There is also a wide variety of :ref:`cubes <AvailableCubes>`. You can access a
+list of availble cubes at the `CubicWeb.org Forge`_.
+
+
+.. _MercurialInstallation:
+
+Install from version control system
+-----------------------------------
+
+To keep-up with on-going development, clone the :ref:`Mercurial
+<MercurialPresentation>` repository::
+
+  hg clone -u stable http://hg.logilab.org/cubicweb # stable branch
+  hg clone http://hg.logilab.org/cubicweb # development branch
+
+To get many of CubicWeb's dependencies and a nice set of base cubes, run the
+`clone_deps.py` script located in `cubicweb/bin/`::
+
+  python cubicweb/bin/clone_deps.py
+
+(Windows users should replace slashes with antislashes).
+
+This script will clone a set of mercurial repositories into the
+directory containing the ``cubicweb`` repository, and update them to the
+latest published version tag (if any).
+
+.. note::
+
+  In every cloned repositories, a `hg tags` will display a list of
+  tags in reverse chronological order. One reasonnable option is to go to a
+  tagged version: the latest published version or example, as done by
+  the `clone_deps` script)::
+
+   hg update cubicweb-version-3.12.2
+
+Make sure you also have all the :ref:`InstallDependencies`.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/admin/site-config.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,94 @@
+.. -*- coding: utf-8 -*-
+
+User interface for web site configuration
+=========================================
+
+.. image:: ../images/lax-book_03-site-config-panel_en.png
+
+This panel allows you to configure the appearance of your instance site.
+Six menus are available and we will go through each of them to explain how
+to use them.
+
+Navigation
+~~~~~~~~~~
+This menu provides you a way to adjust some navigation options depending on
+your needs, such as the number of entities to display by page of results.
+Follows the detailled list of available options :
+
+* navigation.combobox-limit : maximum number of entities to display in related
+  combo box (sample format: 23)
+* navigation.page-size : maximum number of objects displayed by page of results
+  (sample format: 23)
+* navigation.related-limit : maximum number of related entities to display in
+  the primary view (sample format: 23)
+* navigation.short-line-size : maximum number of characters in short description
+  (sample format: 23)
+
+UI
+~~
+This menu provides you a way to customize the user interface settings such as
+date format or encoding in the produced html.
+Follows the detailled list of available options :
+
+* ui.date-format : how to format date in the ui ("man strftime" for format description)
+* ui.datetime-format : how to format date and time in the ui ("man strftime" for format
+  description)
+* ui.default-text-format : default text format for rich text fields.
+* ui.encoding : user interface encoding
+* ui.fckeditor :should html fields being edited using fckeditor (a HTML WYSIWYG editor).
+  You should also select text/html as default text format to actually get fckeditor.
+* ui.float-format : how to format float numbers in the ui
+* ui.language : language of the user interface
+* ui.main-template : id of main template used to render pages
+* ui.site-title	: site title, which is displayed right next to the logo in the header
+* ui.time-format : how to format time in the ui ("man strftime" for format description)
+
+
+Actions
+~~~~~~~
+This menu provides a way to configure the context in which you expect the actions
+to be displayed to the user and if you want the action to be visible or not.
+You must have notice that when you view a list of entities, an action box is
+available on the left column which display some actions as well as a drop-down
+menu for more actions.
+
+The context available are :
+
+* mainactions : actions listed in the left box
+* moreactions : actions listed in the `more` menu of the left box
+* addrelated : add actions listed in the left box
+* useractions : actions listed in the first section of drop-down menu
+  accessible from the right corner user login link
+* siteactions : actions listed in the second section of drop-down menu
+  accessible from the right corner user login link
+* hidden : select this to hide the specific action
+
+Boxes
+~~~~~
+The instance has already a pre-defined set of boxes you can use right away.
+This configuration section allows you to place those boxes where you want in the
+instance interface to customize it.
+
+The available boxes are :
+
+* actions box : box listing the applicable actions on the displayed data
+
+* boxes_blog_archives_box : box listing the blog archives
+
+* possible views box : box listing the possible views for the displayed data
+
+* rss box : RSS icon to get displayed data as a RSS thread
+
+* search box : search box
+
+* startup views box : box listing the configuration options available for
+  the instance site, such as `Preferences` and `Site Configuration`
+
+Components
+~~~~~~~~~~
+[WRITE ME]
+
+Contextual components
+~~~~~~~~~~~~~~~~~~~~~
+[WRITE ME]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/depends.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,58 @@
+.. -*- coding: utf-8 -*-
+
+.. _InstallDependencies:
+
+Installation dependencies
+=========================
+
+When you run CubicWeb from source, either by downloading the tarball or
+cloning the mercurial tree, here is the list of tools and libraries you need
+to have installed in order for CubicWeb to work:
+
+* yapps - http://theory.stanford.edu/~amitp/yapps/ -
+  http://pypi.python.org/pypi/Yapps2
+
+* pygraphviz - http://networkx.lanl.gov/pygraphviz/ -
+  http://pypi.python.org/pypi/pygraphviz
+
+* docutils - http://docutils.sourceforge.net/ - http://pypi.python.org/pypi/docutils
+
+* lxml - http://codespeak.net/lxml - http://pypi.python.org/pypi/lxml
+
+* twisted - http://twistedmatrix.com/ - http://pypi.python.org/pypi/Twisted
+
+* logilab-common - http://www.logilab.org/project/logilab-common -
+  http://pypi.python.org/pypi/logilab-common/
+
+* logilab-database - http://www.logilab.org/project/logilab-database -
+  http://pypi.python.org/pypi/logilab-database/
+
+* logilab-constraint - http://www.logilab.org/project/logilab-constraint -
+  http://pypi.python.org/pypi/constraint/
+
+* logilab-mtconverter - http://www.logilab.org/project/logilab-mtconverter -
+  http://pypi.python.org/pypi/logilab-mtconverter
+
+* rql - http://www.logilab.org/project/rql - http://pypi.python.org/pypi/rql
+
+* yams - http://www.logilab.org/project/yams - http://pypi.python.org/pypi/yams
+
+* indexer - http://www.logilab.org/project/indexer -
+  http://pypi.python.org/pypi/indexer
+
+* passlib - https://code.google.com/p/passlib/ -
+  http://pypi.python.org/pypi/passlib
+
+If you're using a Postgresql database (recommended):
+
+* psycopg2 - http://initd.org/projects/psycopg2 - http://pypi.python.org/pypi/psycopg2
+* plpythonu extension
+
+Other optional packages:
+
+* fyzz - http://www.logilab.org/project/fyzz -
+  http://pypi.python.org/pypi/fyzz *to activate Sparql querying*
+
+
+Any help with the packaging of CubicWeb for more than Debian/Ubuntu (including
+eggs, buildouts, etc) will be greatly appreciated.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/docstrings-conventions.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,106 @@
+Javascript docstrings
+=====================
+
+Whereas in Python source code we only need to include a module docstrings
+using the directive `.. automodule:: mypythonmodule`, we will have to
+explicitely define Javascript modules and functions in the doctrings since
+there is no native directive to include Javascript files.
+
+Rest generation
+---------------
+
+`pyjsrest` is a small utility parsing Javascript doctrings and generating the
+corresponding Restructured file used by Sphinx to generate HTML documentation.
+This script will have the following structure::
+
+  ===========
+  filename.js
+  ===========
+  .. module:: filename.js
+
+We use the `.. module::` directive to register a javascript library
+as a Python module for Sphinx. This provides an entry in the module index.
+
+The contents of the docstring found in the javascript file will be added as is
+following the module declaration. No treatment will be done on the doctring.
+All the documentation structure will be in the docstrings and will comply
+with the following rules.
+
+Docstring structure
+-------------------
+
+Basically we document javascript with RestructuredText docstring
+following the same convention as documenting Python code.
+
+The doctring in Javascript files must be contained in standard
+Javascript comment signs, starting with `/**` and ending with `*/`,
+such as::
+
+ /**
+  * My comment starts here.
+  * This is the second line prefixed with a `*`.
+  * ...
+  * ...
+  * All the follwing line will be prefixed with a `*` followed by a space.
+  * ...
+  * ...
+  */
+
+
+Comments line prefixed by `//` will be ignored. They are reserved for source
+code comments dedicated to developers.
+
+
+Javscript functions docstring
+-----------------------------
+
+By default, the `function` directive describes a module-level function.
+
+`function` directive
+~~~~~~~~~~~~~~~~~~~~
+
+Its purpose is to define the function prototype such as::
+
+    .. function:: loadxhtml(url, data, reqtype, mode)
+
+If any namespace is used, we should add it in the prototype for now,
+until we define an appropriate directive::
+
+    .. function:: jQuery.fn.loadxhtml(url, data, reqtype, mode)
+
+Function parameters
+~~~~~~~~~~~~~~~~~~~
+
+We will define function parameters as a bulleted list, where the
+parameter name will be backquoted and followed by its description.
+
+Example of a javascript function docstring::
+
+    .. function:: loadxhtml(url, data, reqtype, mode)
+
+    cubicweb loadxhtml plugin to make jquery handle xhtml response
+
+    fetches `url` and replaces this's content with the result
+
+    Its arguments are:
+
+    * `url`
+
+    * `mode`, how the replacement should be done (default is 'replace')
+       Possible values are :
+           - 'replace' to replace the node's content with the generated HTML
+           - 'swap' to replace the node itself with the generated HTML
+           - 'append' to append the generated HTML to the node's content
+
+
+Optional parameter specification
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Javascript functions handle arguments not listed in the function signature.
+In the javascript code, they will be flagged using `/* ... */`. In the docstring,
+we flag those optional arguments the same way we would define it in
+Python::
+
+    .. function:: asyncRemoteExec(fname, arg1=None, arg2=None)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/faq.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,437 @@
+.. -*- coding: utf-8 -*-
+
+Frequently Asked Questions (FAQ)
+================================
+
+
+Generalities
+````````````
+
+Why do you use the LGPL license to prevent me from doing X ?
+------------------------------------------------------------
+
+LGPL means that *if* you redistribute your application, you need to
+redistribute the changes you made to CubicWeb under the LGPL licence.
+
+Publishing a web site has nothing to do with redistributing source
+code according to the terms of the LGPL. A fair amount of companies
+use modified LGPL code for internal use. And someone could publish a
+*CubicWeb* component under a BSD licence for others to plug into a
+LGPL framework without any problem. The only thing we are trying to
+prevent here is someone taking the framework and packaging it as
+closed source to his own clients.
+
+Why does not CubicWeb have a template language ?
+------------------------------------------------
+
+There are enough template languages out there. You can use your
+preferred template language if you want. [explain how to use a
+template language]
+
+*CubicWeb* does not define its own templating language as this was
+not our goal. Based on our experience, we realized that
+we could gain productivity by letting designers use design tools
+and developpers develop without the use of the templating language
+as an intermediary that could not be anyway efficient for both parties.
+Python is the templating language that we use in *CubicWeb*, but again,
+it does not prevent you from using a templating language.
+
+Moreover, CubicWeb currently supports `simpletal`_ out of the box and
+it is also possible to use the `cwtags`_ library to build html trees
+using the `with statement`_ with more comfort than raw strings.
+
+.. _`simpletal`: http://www.owlfish.com/software/simpleTAL/
+.. _`cwtags`: http://www.cubicweb.org/project/cwtags
+.. _`with statement`: http://www.python.org/dev/peps/pep-0343/
+
+Why do you think using pure python is better than using a template language ?
+-----------------------------------------------------------------------------
+
+Python is an Object Oriented Programming language and as such it
+already provides a consistent and strong architecture and syntax
+a templating language would not reach.
+
+Using Python instead of a template langage for describing the user interface
+makes it to maintain with real functions/classes/contexts without the need of
+learning a new dialect. By using Python, we use standard OOP techniques and
+this is a key factor in a robust application.
+
+CubicWeb looks pretty recent. Is it stable ?
+--------------------------------------------
+
+It is constantly evolving, piece by piece.  The framework has evolved since
+2001 and data has been migrated from one schema to the other ever since. There
+is a well-defined way to handle data and schema migration.
+
+You can see the roadmap there:
+http://www.cubicweb.org/project/cubicweb?tab=projectroadmap_tab.
+
+
+Why is the RQL query language looking similar to X ?
+----------------------------------------------------
+
+It may remind you of SQL but it is higher level than SQL, more like
+SPARQL. Except that SPARQL did not exist when we started the project.
+With version 3.4, CubicWeb has support for SPARQL.
+
+The RQL language is what is going to make a difference with django-
+like frameworks for several reasons.
+
+1. accessing data is *much* easier with it. One can write complex
+   queries with RQL that would be tedious to define and hard to maintain
+   using an object/filter suite of method calls.
+
+2. it offers an abstraction layer allowing your applications to run
+   on multiple back-ends. That means not only various SQL backends
+   (postgresql, sqlite, sqlserver, mysql), but also non-SQL data stores like
+   LDAP directories and subversion/mercurial repositories (see the `vcsfile`
+   component).
+
+Which ajax library is CubicWeb using ?
+--------------------------------------
+
+CubicWeb uses jQuery_ and provides a few helpers on top of that. Additionally,
+some jQuery plugins are provided (some are provided in specific cubes).
+
+.. _jQuery: http://jquery.com
+
+
+Development
+```````````
+
+How to change the instance logo ?
+---------------------------------
+
+The logo is managed by css. You must provide a custom css that will contain
+the code below: 
+
+::
+   
+     #logo {
+        background-image: url("logo.jpg");
+     }
+
+
+``logo.jpg`` is in ``mycube/data`` directory.
+
+How to create an anonymous user ?
+---------------------------------
+
+This allows to browse the site without being authenticated. In the
+``all-in-one.conf`` file of your instance, define the anonymous user
+as follows ::
+
+  # login of the CubicWeb user account to use for anonymous user (if you want to
+  # allow anonymous)
+  anonymous-user=anon
+
+  # password of the CubicWeb user account matching login
+  anonymous-password=anon
+
+You also must ensure that this `anon` user is a registered user of
+the DB backend. If not, you can create through the administation
+interface of your instance by adding a user with in the group `guests`.
+
+.. note::
+    While creating a new instance, you can decide to allow access
+    to anonymous user, which will automatically execute what is
+    decribed above.
+
+How to load data from a python script ?
+---------------------------------------
+Please, refer to :ref:`UsingPyro`.
+
+
+How to format an entity date attribute ?
+----------------------------------------
+
+If your schema has an attribute of type `Date` or `Datetime`, you usually want to
+format it when displaying it. First, you should define your preferred format
+using the site configuration panel
+``http://appurl/view?vid=systempropertiesform`` and then set ``ui.date`` and/or
+``ui.datetime``.  Then in the view code, use:
+
+.. sourcecode:: python
+
+    entity.printable_value(date_attribute)
+
+which will always return a string whatever the attribute's type (so it's
+recommended also for other attribute types). By default it expects to generate
+HTML, so it deals with rich text formating, xml escaping...
+
+How to update a database after a schema modification ?
+------------------------------------------------------
+
+It depends on what has been modified in the schema.
+
+* update the permissions and properties of an entity or a relation:
+  ``sync_schema_props_perms('MyEntityOrRelation')``.
+
+* add an attribute: ``add_attribute('MyEntityType', 'myattr')``.
+
+* add a relation: ``add_relation_definition('SubjRelation', 'MyRelation', 'ObjRelation')``.
+
+I get `NoSelectableObject` exceptions, how do I debug selectors ?
+-----------------------------------------------------------------
+
+You just need to put the appropriate context manager around view/component
+selection. One standard place for components is in cubicweb/vregistry.py: 
+
+.. sourcecode:: python
+
+    def possible_objects(self, *args, **kwargs):
+        """return an iterator on possible objects in this registry for the given
+        context
+        """
+        from logilab.common.registry import traced_selection
+        with traced_selection():
+            for appobjects in self.itervalues():
+                try:
+                    yield self._select_best(appobjects, *args, **kwargs)
+                except NoSelectableObject:
+                    continue
+
+This will yield additional WARNINGs, like this::
+
+    2009-01-09 16:43:52 - (cubicweb.selectors) WARNING: selector one_line_rset returned 0 for <class 'cubicweb.web.views.basecomponents.WFHistoryVComponent'>
+
+For views, you can put this context in `cubicweb/web/views/basecontrollers.py` in
+the `ViewController`:
+
+.. sourcecode:: python
+
+    def _select_view_and_rset(self, rset):
+        ...
+        try:
+            from logilab.common.registry import traced_selection
+            with traced_selection():
+                view = self._cw.vreg['views'].select(vid, req, rset=rset)
+        except ObjectNotFound:
+            self.warning("the view %s could not be found", vid)
+            req.set_message(req._("The view %s could not be found") % vid)
+            vid = vid_from_rset(req, rset, self._cw.vreg.schema)
+            view = self._cw.vreg['views'].select(vid, req, rset=rset)
+        ...
+
+I get "database is locked" when executing tests
+-----------------------------------------------
+
+If you have "database is locked" as error when you are executing security tests,
+it is usually because commit or rollback are missing before login() calls.
+
+You can also use a context manager, to avoid such errors, as described
+here: :ref:`securitytest`.
+
+
+What are hooks used for ?
+-------------------------
+
+Hooks are executed around (actually before or after) events.  The most common
+events are data creation, update and deletion.  They permit additional constraint
+checking (those not expressible at the schema level), pre and post computations
+depending on data movements.
+
+As such, they are a vital part of the framework.
+
+Other kinds of hooks, called Operations, are available
+for execution just before commit.
+
+For more information, read :ref:`hooks` section.
+
+
+Configuration
+`````````````
+
+How to configure a LDAP source ?
+--------------------------------
+
+See :ref:`LDAP`.
+
+How to import LDAP users in |cubicweb| ?
+----------------------------------------
+
+  Here is a useful script which enables you to import LDAP users
+  into your *CubicWeb* instance by running the following:
+
+.. sourcecode:: python
+
+    import os
+    import pwd
+    import sys
+
+    from logilab.database import get_connection
+
+    def getlogin():
+        """avoid using os.getlogin() because of strange tty/stdin problems
+        (man 3 getlogin)
+        Another solution would be to use $LOGNAME, $USER or $USERNAME
+        """
+        return pwd.getpwuid(os.getuid())[0]
+
+
+    try:
+        database = sys.argv[1]
+    except IndexError:
+        print 'USAGE: python ldap2system.py <database>'
+        sys.exit(1)
+
+    if raw_input('update %s db ? [y/n]: ' % database).strip().lower().startswith('y'):
+        cnx = get_connection(user=getlogin(), database=database)
+        cursor = cnx.cursor()
+
+        insert = ('INSERT INTO euser (creation_date, eid, modification_date, login, '
+                  ' firstname, surname, last_login_time, upassword) '
+                  "VALUES (%(mtime)s, %(eid)s, %(mtime)s, %(login)s, %(firstname)s, "
+                  "%(surname)s, %(mtime)s, './fqEz5LeZnT6');")
+        update = "UPDATE entities SET source='system' WHERE eid=%(eid)s;"
+        cursor.execute("SELECT eid,type,source,extid,mtime FROM entities WHERE source!='system'")
+        for eid, type, source, extid, mtime in cursor.fetchall():
+            if type != 'CWUser':
+                print "don't know what to do with entity type", type
+                continue
+            if source != 'ldapuser':
+                print "don't know what to do with source type", source
+                continue
+            ldapinfos = dict(x.strip().split('=') for x in extid.split(','))
+            login = ldapinfos['uid']
+            firstname = ldapinfos['uid'][0].upper()
+            surname = ldapinfos['uid'][1:].capitalize()
+            if login != 'jcuissinat':
+                args = dict(eid=eid, type=type, source=source, login=login,
+                            firstname=firstname, surname=surname, mtime=mtime)
+                print args
+                cursor.execute(insert, args)
+                cursor.execute(update, args)
+
+        cnx.commit()
+        cnx.close()
+
+
+Security
+````````
+
+How to reset the password for user joe ?
+----------------------------------------
+
+If you want to reset the admin password for ``myinstance``, do::
+
+    $ cubicweb-ctl reset-admin-pwd myinstance
+
+You need to generate a new encrypted password::
+
+    $ python
+    >>> from cubicweb.server.utils import crypt_password
+    >>> crypt_password('joepass')
+    'qHO8282QN5Utg'
+    >>>
+
+and paste it in the database::
+
+    $ psql mydb
+    mydb=> update cw_cwuser set cw_upassword='qHO8282QN5Utg' where cw_login='joe';
+    UPDATE 1
+
+if you're running over SQL Server, you need to use the CONVERT
+function to convert the string to varbinary(255). The SQL query is
+therefore::
+
+    update cw_cwuser set cw_upassword=CONVERT(varbinary(255), 'qHO8282QN5Utg') where cw_login='joe';
+
+Be careful, the encryption algorithm is different on Windows and on
+Unix. You cannot therefore use a hash generated on Unix to fill in a
+Windows database, nor the other way round.
+
+
+You can prefer use a migration script similar to this shell invocation instead::
+
+    $ cubicweb-ctl shell <instance>
+    >>> from cubicweb import Binary
+    >>> from cubicweb.server.utils import crypt_password
+    >>> crypted = crypt_password('joepass')
+    >>> rset = rql('Any U WHERE U is CWUser, U login "joe"')
+    >>> joe = rset.get_entity(0,0)
+    >>> joe.cw_set(upassword=Binary(crypted))
+
+Please, refer to the script example is provided in the `misc/examples/chpasswd.py` file.
+
+The more experimented people would use RQL request directly::
+
+    >>> rql('SET X upassword %(a)s WHERE X is CWUser, X login "joe"',
+    ...     {'a': crypted})
+
+I've just created a user in a group and it doesn't work !
+---------------------------------------------------------
+
+You are probably getting errors such as ::
+
+  remove {'PR': 'Project', 'C': 'CWUser'} from solutions since your_user has no read access to cost
+
+This is because you have to put your user in the "users" group. The user has to
+be in both groups.
+
+How is security implemented ?
+------------------------------
+
+The basis for security is a mapping from operations to groups or
+arbitrary RQL expressions. These mappings are scoped to entities and
+relations.
+
+This is an example for an Entity Type definition:
+
+.. sourcecode:: python
+
+    class Version(EntityType):
+        """a version is defining the content of a particular project's
+        release"""
+        # definition of attributes is voluntarily missing
+        __permissions__ = {'read': ('managers', 'users', 'guests',),
+                           'update': ('managers', 'logilab', 'owners'),
+                           'delete': ('managers',),
+                           'add': ('managers', 'logilab',
+                                   ERQLExpression('X version_of PROJ, U in_group G, '
+                                                  'PROJ require_permission P, '
+                                                  'P name "add_version", P require_group G'),)}
+
+The above means that permission to read a Version is granted to any
+user that is part of one of the groups 'managers', 'users', 'guests'.
+The 'add' permission is granted to users in group 'managers' or
+'logilab' or to users in group G, if G is linked by a permission
+entity named "add_version" to the version's project.
+
+An example for a Relation Definition (RelationType both defines a
+relation type and implicitly one relation definition, on which the
+permissions actually apply):
+
+.. sourcecode:: python
+
+    class version_of(RelationType):
+        """link a version to its project. A version is necessarily linked
+        to one and only one project. """
+        # some lines voluntarily missing
+        __permissions__ = {'read': ('managers', 'users', 'guests',),
+                           'delete': ('managers', ),
+                           'add': ('managers', 'logilab',
+                                   RRQLExpression('O require_permission P, P name "add_version", '
+                                                  'U in_group G, P require_group G'),) }
+
+The main difference lies in the basic available operations (there is
+no 'update' operation) and the usage of an RRQLExpression (rql
+expression for a relation) instead of an ERQLExpression (rql
+expression for an entity).
+
+You can find additional information in the section :ref:`securitymodel`.
+
+Is it possible to bypass security from the UI (web front) part ?
+----------------------------------------------------------------
+
+No. Only Hooks/Operations can do that.
+
+Can PostgreSQL and CubicWeb authentication work with kerberos ?
+----------------------------------------------------------------
+
+If you have PostgreSQL set up to accept kerberos authentication, you can set
+the db-host, db-name and db-user parameters in the `sources` configuration
+file while leaving the password blank. It should be enough for your
+instance to connect to postgresql with a kerberos ticket.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,19 @@
+.. -*- coding: utf-8 -*-
+
+.. _Part4:
+
+----------
+Appendixes
+----------
+
+The following chapters are reference material.
+
+.. toctree::
+   :maxdepth: 1
+   :numbered:
+
+   faq
+   rql/index
+   mercurial
+   depends
+   docstrings-conventions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/mercurial.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,131 @@
+.. -*- coding: utf-8 -*-
+
+.. _MercurialPresentation:
+
+Introducing Mercurial
+=====================
+
+Introduction
+````````````
+Mercurial_ manages a distributed repository containing revisions
+trees (each revision indicates the changes required to obtain the
+next, and so on). Locally, we have a repository containing revisions
+tree, and a working directory. It is possible
+to put in its working directory, one of the versions of its local repository,
+modify and then push it in its repository.
+It is also possible to get revisions from another repository or to export
+its own revisions from the local repository to another repository.
+
+.. _Mercurial: http://www.selenic.com/mercurial/
+
+In contrast to CVS/Subversion, we usually create a repository per
+project to manage.
+
+In a collaborative development, we usually create a central repository
+accessible to all developers of the project. These central repository is used
+as a reference. According to their needs, everyone can have a local repository,
+that they will have to synchronize with the central repository from time to time.
+
+
+Major commands
+``````````````
+* Create a local repository::
+
+     hg clone ssh://myhost//home/src/repo
+
+* See the contents of the local repository (graphical tool in Qt)::
+
+     hgview
+
+* Add a sub-directory or file in the current directory::
+
+     hg add subdir
+
+* Move to the working directory a specific revision (or last
+  revision) from the local repository::
+
+     hg update [identifier-revision]
+     hg up [identifier-revision]
+
+* Get in its local repository, the tree of revisions contained in a
+  remote repository (this does not change the local directory)::
+
+     hg pull ssh://myhost//home/src/repo
+     hg pull -u ssh://myhost//home/src/repo # equivalent to pull + update
+
+* See what are the heads of branches of the local repository if a `pull`
+  returned a new branch::
+
+     hg heads
+
+* Submit the working directory in the local repository (and create a new
+  revision)::
+
+     hg commit
+     hg ci
+
+* Merge with the mother revision of local directory, another revision from
+  the local respository (the new revision will be then two mothers
+  revisions)::
+
+     hg merge identifier-revision
+
+* Export to a remote repository, the tree of revisions in its content
+  local respository (this does not change the local directory)::
+
+     hg push ssh://myhost//home/src/repo
+
+* See what local revisions are not in another repository::
+
+     hg outgoing ssh://myhost//home/src/repo
+
+* See what are the revisions of a repository not found locally::
+
+     hg incoming ssh://myhost//home/src/repo
+
+* See what is the revision of the local repository which has been taken out
+  from the working directory and amended::
+
+     hg parent
+
+* See the differences between the working directory and the mother revision
+  of the local repository, possibly to submit them in the local repository::
+
+     hg diff
+     hg commit-tool
+     hg ct
+
+
+Best Practices
+``````````````
+* Remember to `hg pull -u` regularly, and particularly before
+   a `hg commit`.
+
+* Remember to `hg push` when your repository contains a version
+  relatively stable of your changes.
+
+* If a `hg pull -u` created a new branch head:
+
+   1. find its identifier with `hg head`
+   2. merge with `hg merge`
+   3. `hg ci`
+   4. `hg push`
+
+Installation of the guestrepo extension
+```````````````````````````````````````
+
+Set up the guestrepo extension by getting a copy of the sources
+from https://bitbucket.org/selinc/guestrepo and adding the following
+lines to your ``~/.hgrc``: ::
+
+   [extensions]
+   guestrepo=/path/to/guestrepo/guestrepo
+
+
+More information
+````````````````
+
+For more information about Mercurial, please refer to the Mercurial project online documentation_.
+
+.. _documentation: http://www.selenic.com/mercurial/wiki/
+
Binary file doc/book/annexes/rql/Graph-ex.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/rql/debugging.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,55 @@
+.. -*- coding: utf-8 -*-
+
+.. _DEBUGGING:
+
+Debugging RQL
+-------------
+
+Available levels
+~~~~~~~~~~~~~~~~
+
+Server debugging flags. They may be combined using binary operators.
+
+.. autodata:: cubicweb.server.DBG_NONE
+.. autodata:: cubicweb.server.DBG_RQL
+.. autodata:: cubicweb.server.DBG_SQL
+.. autodata:: cubicweb.server.DBG_REPO
+.. autodata:: cubicweb.server.DBG_MS
+.. autodata:: cubicweb.server.DBG_HOOKS
+.. autodata:: cubicweb.server.DBG_OPS
+.. autodata:: cubicweb.server.DBG_MORE
+.. autodata:: cubicweb.server.DBG_ALL
+
+
+Enable verbose output
+~~~~~~~~~~~~~~~~~~~~~
+
+To debug your RQL statements, it can be useful to enable a verbose output:
+
+.. sourcecode:: python
+
+    from cubicweb import server
+    server.set_debug(server.DBG_RQL|server.DBG_SQL|server.DBG_ALL)
+
+.. autofunction:: cubicweb.server.set_debug
+
+Another example showing how to debug hooks at a specific code site:
+
+.. sourcecode:: python
+
+    from cubicweb.server import debugged, DBG_HOOKS
+    with debugged(DBG_HOOKS):
+        person.cw_set(works_for=company)
+
+
+Detect largest RQL queries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+See `Profiling and performance` chapter (see :ref:`PROFILING`).
+
+
+API
+~~~
+
+.. autoclass:: cubicweb.server.debugged
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/rql/implementation.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,159 @@
+
+
+Implementation
+--------------
+
+BNF grammar
+~~~~~~~~~~~
+
+The terminal elements are in capital letters, non-terminal in lowercase.
+The value of the terminal elements (between quotes) is a Python regular
+expression.
+::
+
+     statement ::= (select | delete | insert | update) ';'
+
+
+     # select specific rules
+     select      ::= 'DISTINCT'? E_TYPE selected_terms restriction? group? sort?
+
+     selected_terms ::= expression ( ',' expression)*
+
+     group       ::= 'GROUPBY' VARIABLE ( ',' VARIABLE)*
+
+     sort        ::= 'ORDERBY' sort_term ( ',' sort_term)*
+
+     sort_term   ::=  VARIABLE sort_method =?
+
+     sort_method ::= 'ASC' | 'DESC'
+
+
+     # delete specific rules
+     delete ::= 'DELETE' (variables_declaration | relations_declaration) restriction?
+
+
+     # insert specific rules
+     insert ::= 'INSERT' variables_declaration ( ':' relations_declaration)? restriction?
+
+
+     # update specific rules
+     update ::= 'SET' relations_declaration restriction
+
+
+     # common rules
+     variables_declaration ::= E_TYPE VARIABLE (',' E_TYPE VARIABLE)*
+
+     relations_declaration ::= simple_relation (',' simple_relation)*
+
+     simple_relation ::= VARIABLE R_TYPE expression
+
+     restriction ::= 'WHERE' relations
+
+     relations   ::= relation (LOGIC_OP relation)*
+                   | '(' relations')'
+
+     relation    ::= 'NOT'? VARIABLE R_TYPE COMP_OP? expression
+                   | 'NOT'? R_TYPE VARIABLE 'IN' '(' expression (',' expression)* ')'
+
+     expression  ::= var_or_func_or_const (MATH_OP var_or_func_or_const) *
+                   | '(' expression ')'
+
+     var_or_func_or_const ::= VARIABLE | function | constant
+
+     function    ::= FUNCTION '(' expression ( ',' expression) * ')'
+
+     constant    ::= KEYWORD | STRING | FLOAT | INT
+
+     # tokens
+     LOGIC_OP ::= ',' | 'OR' | 'AND'
+     MATH_OP  ::= '+' | '-' | '/' | '*'
+     COMP_OP  ::= '>' | '>=' | '=' | '<=' | '<' | '~=' | 'LIKE'
+
+     FUNCTION ::= 'MIN' | 'MAX' | 'SUM' | 'AVG' | 'COUNT' | 'UPPER' | 'LOWER'
+
+     VARIABLE ::= '[A-Z][A-Z0-9]*'
+     E_TYPE   ::= '[A-Z]\w*'
+     R_TYPE   ::= '[a-z_]+'
+
+     KEYWORD  ::= 'TRUE' | 'FALSE' | 'NULL' | 'TODAY' | 'NOW'
+     STRING   ::= "'([^'\]|\\.)*'" |'"([^\"]|\\.)*\"'
+     FLOAT    ::= '\d+\.\d*'
+     INT      ::= '\d+'
+
+
+Internal representation (syntactic tree)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The tree research does not contain the selected variables
+(e.g. there is only what follows "WHERE").
+
+The insertion tree does not contain the variables inserted or relations
+defined on these variables (e.g. there is only what follows "WHERE").
+
+The removal tree does not contain the deleted variables and relations
+(e.g. there is only what follows the "WHERE").
+
+The update tree does not contain the variables and relations updated
+(e.g. there is only what follows the "WHERE").
+
+::
+
+     Select         ((Relationship | And | Or)?, Group?, Sort?)
+     Insert         (Relations | And | Or)?
+     Delete         (Relationship | And | Or)?
+     Update         (Relations | And | Or)?
+
+     And            ((Relationship | And | Or), (Relationship | And | Or))
+     Or             ((Relationship | And | Or), (Relationship | And | Or))
+
+     Relationship   ((VariableRef, Comparison))
+
+     Comparison     ((Function | MathExpression | Keyword | Constant | VariableRef) +)
+
+     Function       (())
+     MathExpression ((MathExpression | Keyword | Constant | VariableRef), (MathExpression | Keyword | Constant | VariableRef))
+
+     Group          (VariableRef +)
+     Sort           (SortTerm +)
+     SortTerm       (VariableRef +)
+
+     VariableRef    ()
+     Variable       ()
+     Keyword        ()
+     Constant       ()
+
+
+Known limitations
+~~~~~~~~~~~~~~~~~
+
+- The current implementation does not support linking two relations of type 'is'
+  with an OR. I do not think that the negation is supported on this type of
+  relation (XXX to be confirmed).
+
+- missing COALESCE and certainly other things...
+
+- writing an rql query requires knowledge of the used schema (with real relation
+  names and entities, not those viewed in the user interface). On the other
+  hand, we cannot really bypass that, and it is the job of a user interface to
+  hide the RQL.
+
+
+Topics
+~~~~~~
+
+It would be convenient to express the schema matching
+relations (non-recursive rules)::
+
+     Document class Type <-> Document occurence_of Fiche class Type
+     Sheet class Type    <-> Form collection Collection class Type
+
+Therefore 1. becomes::
+
+     Document X where
+     X class C, C name 'Cartoon'
+     X owned_by U, U login 'syt'
+     X available true
+
+I'm not sure that we should handle this at RQL level ...
+
+There should also be a special relation 'anonymous'.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/rql/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,14 @@
+.. _RQLChapter:
+
+Relation Query Language (RQL)
+=============================
+
+This chapter describes the Relation Query Language syntax and its implementation in CubicWeb.
+
+.. toctree::
+   :maxdepth: 2
+
+   intro
+   language
+   debugging
+   implementation
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/rql/intro.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,162 @@
+
+.. _rql_intro:
+
+Introduction
+------------
+
+Goals of RQL
+~~~~~~~~~~~~
+
+The goal is to have a semantic language in order to:
+
+- query relations in a clear syntax
+- empowers access to data repository manipulation
+- making attributes/relations browsing easy
+
+As such, attributes will be regarded as cases of special relations (in
+terms of usage, the user should see no syntactic difference between an
+attribute and a relation).
+
+Comparison with existing languages
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SQL
+```
+
+RQL may remind of SQL but works at a higher abstraction level (the *CubicWeb*
+framework generates SQL from RQL to fetch data from relation databases). RQL is
+focused on browsing relations. The user needs only to know about the *CubicWeb*
+data model he is querying, but not about the underlying SQL model.
+
+Sparql
+``````
+
+The query language most similar to RQL is SPARQL_, defined by the W3C to serve
+for the semantic web.
+
+Versa
+`````
+
+We should look in more detail, but here are already some ideas for the moment
+... Versa_ is the language most similar to what we wanted to do, but the model
+underlying data being RDF, there are some things such as namespaces or
+handling of the RDF types which does not interest us. On the functionality
+level, Versa_ is very comprehensive including through many functions of
+conversion and basic types manipulation, which we may want to look at one time
+or another.  Finally, the syntax is a little esoteric.
+
+Datalog
+```````
+
+Datalog_ is a prolog derived query langage which applies to relational
+databases. It is more expressive than RQL in that it accepts either
+extensional_ and intensional_ predicates (or relations). As of now,
+RQL only deals with intensional relations.
+
+The different types of queries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Search (`Any`)
+   Extract entities and attributes of entities.
+
+Insert entities (`INSERT`)
+   Insert new entities or relations in the database.
+   It can also directly create relationships for the newly created entities.
+
+Update entities, create relations (`SET`)
+   Update existing entities in the database,
+   or create relations between existing entities.
+
+Delete entities or relationship (`DELETE`)
+   Remove entities or relations existing in the database.
+
+
+RQL relation expressions
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+RQL expressions apply to a live database defined by a
+:ref:`datamodel_definition`. Apart from the main type, or head, of the
+expression (search, insert, etc.) the most common constituent of an
+RQL expression is a (set of) relation expression(s).
+
+An RQL relation expression contains three components:
+
+* the subject, which is an entity type
+* the predicate, which is a relation definition (an arc of the schema)
+* the object, which is either an attribute or a relation to another entity
+
+.. image:: Graph-ex.gif
+    :alt: <subject> <predicate> <object>
+    :align: center
+
+.. warning::
+
+ A relation is always expressed in the order: ``subject``,
+ ``predicate``, ``object``.
+
+ It is important to determine if the entity type is subject or object
+ to construct a valid expression. Inverting the subject/object is an
+ error since the relation cannot be found in the schema.
+
+ If one does not have access to the code, one can find the order by
+ looking at the schema image in manager views (the subject is located
+ at the beginning of the arrow).
+
+An example of two related relation expressions::
+
+  P works_for C, P name N
+
+RQL variables represent typed entities. The type of entities is
+either automatically inferred (by looking at the possible relation
+definitions, see :ref:`RelationDefinition`) or explicitely constrained
+using the ``is`` meta relation.
+
+In the example above, we barely need to look at the schema. If
+variable names (in the RQL expression) and relation type names (in the
+schema) are expresssively designed, the human reader can infer as much
+as the |cubicweb| querier.
+
+The ``P`` variable is used twice but it always represent the same set
+of entities. Hence ``P works_for C`` and ``P name N`` must be
+compatible in the sense that all the Ps (which *can* refer to
+different entity types) must accept the ``works_for`` and ``name``
+relation types. This does restrict the set of possible values of P.
+
+Adding another relation expression::
+
+  P works_for C, P name N, C name "logilab"
+
+This further restricts the possible values of P through an indirect
+constraint on the possible values of ``C``. The RQL-level unification_
+happening there is translated to one (or several) joins_ at the
+database level.
+
+.. note::
+
+ In |cubicweb|, the term `relation` is often found without ambiguity
+ instead of `predicate`.  This predicate is also known as the
+ `property` of the triple in `RDF concepts`_
+
+
+RQL Operators
+~~~~~~~~~~~~~
+
+An RQL expression's head can be completed using various operators such
+as ``ORDERBY``, ``GROUPBY``, ``HAVING``, ``LIMIT`` etc.
+
+RQL relation expressions can be grouped with ``UNION`` or
+``WITH``. Predicate oriented keywords such as ``EXISTS``, ``OR``,
+``NOT`` are available.
+
+The complete zoo of RQL operators is described extensively in the
+following chapter (:ref:`RQL`).
+
+.. _RDF concepts: http://www.w3.org/TR/rdf-concepts/
+.. _Versa: http://wiki.xml3k.org/Versa
+.. _SPARQL: http://www.w3.org/TR/rdf-sparql-query/
+.. _unification: http://en.wikipedia.org/wiki/Unification_(computing)
+.. _joins: http://en.wikipedia.org/wiki/Join_(SQL)
+.. _Datalog: http://en.wikipedia.org/wiki/Datalog
+.. _intensional: http://en.wikipedia.org/wiki/Intensional_definition
+.. _extensional: http://en.wikipedia.org/wiki/Extension_(predicate_logic)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/annexes/rql/language.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,804 @@
+.. -*- coding: utf-8 -*-
+
+.. _RQL:
+
+RQL syntax
+----------
+
+.. _RQLKeywords:
+
+Reserved keywords
+~~~~~~~~~~~~~~~~~
+
+::
+
+  AND, ASC, BEING, DELETE, DESC, DISTINCT, EXISTS, FALSE, GROUPBY,
+  HAVING, ILIKE, INSERT, LIKE, LIMIT, NOT, NOW, NULL, OFFSET,
+  OR, ORDERBY, SET, TODAY, TRUE, UNION, WHERE, WITH
+
+The keywords are not case sensitive. You should not use them when defining your
+schema, or as RQL variable names.
+
+
+.. _RQLCase:
+
+Case
+~~~~
+
+* Variables should be all upper-cased.
+
+* Relation should be all lower-cased and match exactly names of relations defined
+  in the schema.
+
+* Entity types should start with an upper cased letter and be followed by at least
+  a lower cased latter.
+
+
+.. _RQLVariables:
+
+Variables and typing
+~~~~~~~~~~~~~~~~~~~~
+
+Entities and values to browse and/or select are represented in the query by
+*variables* that must be written in capital letters.
+
+With RQL, we do not distinguish between entities and attributes. The value of an
+attribute is considered as an entity of a particular type (see below), linked to
+one (real) entity by a relation called the name of the attribute, where the
+entity is the subject and the attribute the object.
+
+The possible type(s) for each variable is derived from the schema according to
+the constraints expressed above and thanks to the relations between each
+variable.
+
+We can restrict the possible types for a variable using the special relation
+**is** in the restrictions.
+
+
+.. _VirtualRelations:
+
+Virtual relations
+~~~~~~~~~~~~~~~~~
+
+Those relations may only be used in RQL query but are not actual attributes of
+your entities.
+
+* `has_text`: relation to use to query the full text index (only for entities
+  having fulltextindexed attributes).
+
+* `identity`: relation to use to tell that a RQL variable is the same as another
+  when you've to use two different variables for querying purpose. On the
+  opposite it's also useful together with the ``NOT`` operator to tell that two
+  variables should not identify the same entity
+
+
+.. _RQLLiterals:
+
+Literal expressions
+~~~~~~~~~~~~~~~~~~~
+
+Bases types supported by RQL are those supported by yams schema. Literal values
+are expressed as explained below:
+
+* string should be between double or single quotes. If the value contains a
+  quote, it should be preceded by a backslash '\\'
+
+* floats separator is dot '.'
+
+* boolean values are ``TRUE`` and ``FALSE`` keywords
+
+* date and time should be expressed as a string with ISO notation : YYYY/MM/DD
+  [hh:mm], or using keywords ``TODAY`` and ``NOW``
+
+You may also use the ``NULL`` keyword, meaning 'unspecified'.
+
+
+.. _RQLOperators:
+
+Operators
+~~~~~~~~~
+
+.. _RQLLogicalOperators:
+
+Logical operators
+`````````````````
+::
+
+     AND, OR, NOT, ','
+
+',' is equivalent to 'AND' but with the smallest among the priority of logical
+operators (see :ref:`RQLOperatorsPriority`).
+
+.. _RQLMathematicalOperators:
+
+Mathematical operators
+``````````````````````
+
++----------+---------------------+-----------+--------+
+| Operator |    Description      | Example   | Result |
++==========+=====================+===========+========+
+|  `+`     | addition            | 2 + 3     | 5      |
++----------+---------------------+-----------+--------+
+|  `-`     | subtraction         | 2 - 3     | -1     |
++----------+---------------------+-----------+--------+
+|  `*`     | multiplication      | 2 * 3     | 6      |
++----------+---------------------+-----------+--------+
+|  /       | division            | 4 / 2     | 2      |
++----------+---------------------+-----------+--------+
+|  %       | modulo (remainder)  | 5 % 4     | 1      |
++----------+---------------------+-----------+--------+
+|  ^       | exponentiation      | 2.0 ^ 3.0 | 8      |
++----------+---------------------+-----------+--------+
+|  &       | bitwise AND         | 91 & 15   | 11     |
++----------+---------------------+-----------+--------+
+|  `|`     | bitwise OR          | 32 | 3    | 35     |
++----------+---------------------+-----------+--------+
+|  #       | bitwise XOR         | 17 # 5    | 20     |
++----------+---------------------+-----------+--------+
+|  ~       | bitwise NOT         | ~1        | -2     |
++----------+---------------------+-----------+--------+
+|  <<      | bitwise shift left  | 1 << 4    | 16     |
++----------+---------------------+-----------+--------+
+|  >>      | bitwise shift right | 8 >> 2    | 2      |
++----------+---------------------+-----------+--------+
+
+
+Notice integer division truncates results depending on the backend behaviour. For
+instance, postgresql does.
+
+
+.. _RQLComparisonOperators:
+
+Comparison operators
+````````````````````
+ ::
+
+     =, !=, <, <=, >=, >, IN
+
+
+The syntax to use comparison operators is:
+
+    `VARIABLE attribute <operator> VALUE`
+
+The `=` operator is the default operator and can be omitted, i.e. :
+
+    `VARIABLE attribute = VALUE`
+
+is equivalent to
+
+    `VARIABLE attribute VALUE`
+
+
+The operator `IN` provides a list of possible values:
+
+.. sourcecode:: sql
+
+    Any X WHERE X name IN ('chauvat', 'fayolle', 'di mascio', 'thenault')
+
+
+.. _RQLStringOperators:
+
+String operators
+````````````````
+::
+
+  LIKE, ILIKE, ~=, REGEXP
+
+The ``LIKE`` string operator can be used with the special character `%` in
+a string as wild-card:
+
+.. sourcecode:: sql
+
+     -- match every entity whose name starts with 'Th'
+     Any X WHERE X name ~= 'Th%'
+     -- match every entity whose name endswith 'lt'
+     Any X WHERE X name LIKE '%lt'
+     -- match every entity whose name contains a 'l' and a 't'
+     Any X WHERE X name LIKE '%l%t%'
+
+``ILIKE`` is the case insensitive version of ``LIKE``. It's not
+available on all backend (e.g. sqlite doesn't support it). If not available for
+your backend, ``ILIKE`` will behave like ``LIKE``.
+
+`~=` is a shortcut version of ``ILIKE``, or of ``LIKE`` when the
+former is not available on the back-end.
+
+
+The ``REGEXP`` is an alternative to ``LIKE`` that supports POSIX
+regular expressions:
+
+.. sourcecode:: sql
+
+   -- match entities whose title starts with a digit
+   Any X WHERE X title REGEXP "^[0-9].*"
+
+
+The underlying SQL operator used is back-end-dependent :
+
+- the ``~`` operator is used for postgresql,
+- the ``REGEXP`` operator for mysql and sqlite.
+
+Other back-ends are not supported yet.
+
+
+.. _RQLOperatorsPriority:
+
+Operators priority
+``````````````````
+
+#. `(`, `)`
+#. `^`, `<<`, `>>`
+#. `*`, `/`, `%`, `&`
+#. `+`, `-`, `|`, `#`
+#. `NOT`
+#. `AND`
+#. `OR`
+#. `,`
+
+
+.. _RQLSearchQuery:
+
+Search Query
+~~~~~~~~~~~~
+
+Simplified grammar of search query: ::
+
+   [ `DISTINCT`] `Any` V1 (, V2) \*
+   [ `GROUPBY` V1 (, V2) \*] [ `ORDERBY` <orderterms>]
+   [ `LIMIT` <value>] [ `OFFSET` <value>]
+   [ `WHERE` <triplet restrictions>]
+   [ `WITH` V1 (, V2)\* BEING (<query>)]
+   [ `HAVING` <other restrictions>]
+   [ `UNION` <query>]
+
+Selection
+`````````
+
+The fist occuring clause is the selection of terms that should be in the result
+set.  Terms may be variable, literals, function calls, arithmetic, etc. and each
+term is separated by a comma.
+
+There will be as much column in the result set as term in this clause, respecting
+order.
+
+Syntax for function call is somewhat intuitive, for instance:
+
+.. sourcecode:: sql
+
+    Any UPPER(N) WHERE P firstname N
+
+
+Grouping and aggregating
+````````````````````````
+
+The ``GROUPBY`` keyword is followed by a list of terms on which results
+should be grouped. They are usually used with aggregate functions, responsible to
+aggregate values for each group (see :ref:`RQLAggregateFunctions`).
+
+For grouped queries, all selected variables must be either aggregated (i.e. used
+by an aggregate function) or grouped (i.e. listed in the ``GROUPBY``
+clause).
+
+
+Sorting
+```````
+
+The ``ORDERBY`` keyword if followed by the definition of the selection
+order: variable or column number followed by sorting method (``ASC``,
+``DESC``), ``ASC`` being the default. If the sorting method is not
+specified, then the sorting is ascendant (`ASC`).
+
+
+Pagination
+``````````
+
+The ``LIMIT`` and ``OFFSET`` keywords may be respectively used to
+limit the number of results and to tell from which result line to start (for
+instance, use `LIMIT 20` to get the first 20 results, then `LIMIT 20 OFFSET 20`
+to get the next 20.
+
+
+Restrictions
+````````````
+
+The ``WHERE`` keyword introduce one of the "main" part of the query, where
+you "define" variables and add some restrictions telling what you're interested
+in.
+
+It's a list of triplets "subject relation object", e.g. `V1 relation
+(V2 | <static value>)`. Triplets are separated using :ref:`RQLLogicalOperators`.
+
+.. note::
+
+  About the negation operator (``NOT``):
+
+  * ``NOT X relation Y`` is equivalent to ``NOT EXISTS(X relation Y)``
+
+  * ``Any X WHERE NOT X owned_by U`` means "entities that have no relation
+    ``owned_by``".
+
+  * ``Any X WHERE NOT X owned_by U, U login "syt"`` means "the entity have no
+     relation ``owned_by`` with the user syt". They may have a relation "owned_by"
+     with another user.
+
+In this clause, you can also use ``EXISTS`` when you want to know if some
+expression is true and do not need the complete set of elements that make it
+true. Testing for existence is much faster than fetching the complete set of
+results, especially when you think about using ``OR`` against several expressions. For instance
+if you want to retrieve versions which are in state "ready" or tagged by
+"priority", you should write :
+
+.. sourcecode:: sql
+
+    Any X ORDERBY PN,N
+    WHERE X num N, X version_of P, P name PN,
+          EXISTS(X in_state S, S name "ready")
+          OR EXISTS(T tags X, T name "priority")
+
+not
+
+.. sourcecode:: sql
+
+    Any X ORDERBY PN,N
+    WHERE X num N, X version_of P, P name PN,
+          (X in_state S, S name "ready")
+          OR (T tags X, T name "priority")
+
+Both queries aren't at all equivalent :
+
+* the former will retrieve all versions, then check for each one which are in the
+  matching state of or tagged by the expected tag,
+
+* the later will retrieve all versions, state and tags (cartesian product!),
+  compute join and then exclude each row which are in the matching state or
+  tagged by the expected tag. This implies that you won't get any result if the
+  in_state or tag tables are empty (ie there is no such relation in the
+  application). This is usually NOT what you want.
+
+Another common case where you may want to use ``EXISTS`` is when you
+find yourself using ``DISTINCT`` at the beginning of your query to
+remove duplicate results. The typical case is when you have a
+multivalued relation such as Version version_of Project and you want
+to retrieve projects which have a version:
+
+.. sourcecode:: sql
+
+  Any P WHERE V version_of P
+
+will return each project number of versions times. So you may be
+tempted to use:
+
+.. sourcecode:: sql
+
+  DISTINCT ANY P WHERE V version_of P
+
+This will work, but is not efficient, as it will use the ``SELECT
+DISTINCT`` SQL predicate, which needs to retrieve all projects, then
+sort them and discard duplicates, which can have a very high cost for
+large result sets. So the best way to write this is:
+
+.. sourcecode:: sql
+
+  ANY P WHERE EXISTS V version_of P
+
+
+You can also use the question mark (`?`) to mark optional relations. This allows
+you to select entities related **or not** to another. It is a similar concept
+to `Left outer join`_:
+
+    the result of a left outer join (or simply left join) for table A and B
+    always contains all records of the "left" table (A), even if the
+    join-condition does not find any matching record in the "right" table (B).
+
+You must use the `?` behind a variable to specify that the relation to
+that variable is optional. For instance:
+
+- Bugs of a project attached or not to a version
+
+   .. sourcecode:: sql
+
+       Any X, V WHERE X concerns P, P eid 42, X corrected_in V?
+
+  You will get a result set containing all the project's tickets, with either the
+  version in which it's fixed or None for tickets not related to a version.
+
+
+- All cards and the project they document if any
+
+  .. sourcecode:: sql
+
+       Any C, P WHERE C is Card, P? documented_by C
+
+Notice you may also use outer join:
+
+- on the RHS of attribute relation, e.g.
+
+  .. sourcecode:: sql
+
+       Any X WHERE X ref XR, Y name XR?
+
+  so that Y is outer joined on X by ref/name attributes comparison
+
+
+- on any side of an ``HAVING`` expression, e.g.
+
+  .. sourcecode:: sql
+
+       Any X WHERE X creation_date XC, Y creation_date YC
+       HAVING YEAR(XC)=YEAR(YC)?
+
+  so that Y is outer joined on X by comparison of the year extracted from their
+  creation date.
+
+  .. sourcecode:: sql
+
+       Any X WHERE X creation_date XC, Y creation_date YC
+       HAVING YEAR(XC)?=YEAR(YC)
+
+  would outer join X on Y instead.
+
+
+Having restrictions
+```````````````````
+
+The ``HAVING`` clause, as in SQL, may be used to restrict a query
+according to value returned by an aggregate function, e.g.
+
+.. sourcecode:: sql
+
+    Any X GROUPBY X WHERE X relation Y HAVING COUNT(Y) > 10
+
+It may however be used for something else: In the ``WHERE`` clause, we are
+limited to triplet expressions, so some things may not be expressed there. Let's
+take an example : if you want to get people whose upper-cased first name equals to
+another person upper-cased first name. There is no proper way to express this
+using triplet, so you should use something like:
+
+.. sourcecode:: sql
+
+    Any X WHERE X firstname XFN, Y firstname YFN, NOT X identity Y HAVING UPPER(XFN) = UPPER(YFN)
+
+Another example: imagine you want person born in 2000:
+
+.. sourcecode:: sql
+
+    Any X WHERE X birthday XB HAVING YEAR(XB) = 2000
+
+Notice that while we would like this to work without the HAVING clause, this
+can't be currently be done because it introduces an ambiguity in RQL's grammar
+that can't be handled by Yapps_, the parser's generator we're using.
+
+
+Sub-queries
+```````````
+
+The ``WITH`` keyword introduce sub-queries clause. Each sub-query has the
+form:
+
+  V1(,V2) BEING (rql query)
+
+Variables at the left of the ``BEING`` keyword defines into which
+variables results from the sub-query will be mapped to into the outer query.
+Sub-queries are separated from each other using a comma.
+
+Let's say we want to retrieve for each project its number of versions and its
+number of tickets. Due to the nature of relational algebra behind the scene, this
+can't be achieved using a single query. You have to write something along the
+line of:
+
+.. sourcecode:: sql
+
+  Any X, VC, TC WHERE X identity XX
+  WITH X, VC BEING (Any X, COUNT(V) GROUPBY X WHERE V version_of X),
+       XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)
+
+Notice that we can't reuse a same variable name as alias for two different
+sub-queries, hence the usage of 'X' and 'XX' in this example, which are then
+unified using the special `identity` relation (see :ref:`VirtualRelations`).
+
+.. warning::
+
+  Sub-queries define a new variable scope, so even if a variable has the same name
+  in the outer query and in the sub-query, they technically **aren't** the same
+  variable. So:
+
+  .. sourcecode:: sql
+
+     Any W, REF WITH W, REF BEING
+         (Any W, REF WHERE W is Workcase, W ref REF,
+                           W concerned_by D, D name "Logilab")
+
+  could be written:
+
+  .. sourcecode:: sql
+
+     Any W, REF WITH W, REF BEING
+        (Any W1, REF1 WHERE W1 is Workcase, W1 ref REF1,
+                            W1 concerned_by D, D name "Logilab")
+
+  Also, when a variable is coming from a sub-query, you currently can't reference
+  its attribute or inlined relations in the outer query, you've to fetch them in
+  the sub-query. For instance, let's say we want to sort by project name in our
+  first example, we would have to write:
+
+  .. sourcecode:: sql
+
+
+    Any X, VC, TC ORDERBY XN WHERE X identity XX
+    WITH X, XN, VC BEING (Any X, COUNT(V) GROUPBY X,XN WHERE V version_of X, X name XN),
+         XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)
+
+  instead of:
+
+  .. sourcecode:: sql
+
+    Any X, VC, TC ORDERBY XN WHERE X identity XX, X name XN,
+    WITH X, XN, VC BEING (Any X, COUNT(V) GROUPBY X WHERE V version_of X),
+         XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)
+
+  which would result in a SQL execution error.
+
+
+Union
+`````
+
+You may get a result set containing the concatenation of several queries using
+the ``UNION``. The selection of each query should have the same number of
+columns.
+
+.. sourcecode:: sql
+
+    (Any X, XN WHERE X is Person, X surname XN) UNION (Any X,XN WHERE X is Company, X name XN)
+
+
+.. _RQLFunctions:
+
+Available functions
+~~~~~~~~~~~~~~~~~~~
+
+Below is the list of aggregate and transformation functions that are supported
+nativly by the framework. Notice that cubes may define additional functions.
+
+.. _RQLAggregateFunctions:
+
+Aggregate functions
+```````````````````
++------------------------+----------------------------------------------------------+
+| ``COUNT(Any)``         | return the number of rows                                |
++------------------------+----------------------------------------------------------+
+| ``MIN(Any)``           | return the minimum value                                 |
++------------------------+----------------------------------------------------------+
+| ``MAX(Any)``           | return the maximum value                                 |
++------------------------+----------------------------------------------------------+
+| ``AVG(Any)``           | return the average value                                 |
++------------------------+----------------------------------------------------------+
+| ``SUM(Any)``           | return the sum of values                                 |
++------------------------+----------------------------------------------------------+
+| ``COMMA_JOIN(String)`` | return each value separated by a comma (for string only) |
++------------------------+----------------------------------------------------------+
+
+All aggregate functions above take a single argument. Take care some aggregate
+functions (e.g. ``MAX``, ``MIN``) may return `None` if there is no
+result row.
+
+.. _RQLStringFunctions:
+
+String transformation functions
+```````````````````````````````
+
++-----------------------------------------------+-----------------------------------------------------------------+
+| ``UPPER(String)``                             | upper case the string                                           |
++-----------------------------------------------+-----------------------------------------------------------------+
+| ``LOWER(String)``                             | lower case the string                                           |
++-----------------------------------------------+-----------------------------------------------------------------+
+| ``LENGTH(String)``                            | return the length of the string                                 |
++-----------------------------------------------+-----------------------------------------------------------------+
+| ``SUBSTRING(String, start, length)``          | extract from the string a string starting at given index and of |
+|                                               | given length                                                    |
++-----------------------------------------------+-----------------------------------------------------------------+
+| ``LIMIT_SIZE(String, max size)``              | if the length of the string is greater than given max size,     |
+|                                               | strip it and add ellipsis ("..."). The resulting string will    |
+|                                               | hence have max size + 3 characters                              |
++-----------------------------------------------+-----------------------------------------------------------------+
+| ``TEXT_LIMIT_SIZE(String, format, max size)`` | similar to the above, but allow to specify the MIME type of the |
+|                                               | text contained by the string. Supported formats are text/html,  |
+|                                               | text/xhtml and text/xml. All others will be considered as plain |
+|                                               | text. For non plain text format, sgml tags will be first removed|
+|                                               | before limiting the string.                                     |
++-----------------------------------------------+-----------------------------------------------------------------+
+
+.. _RQLDateFunctions:
+
+Date extraction functions
+`````````````````````````
+
++----------------------+----------------------------------------+
+| ``YEAR(Date)``       | return the year of a date or datetime  |
++----------------------+----------------------------------------+
+| ``MONTH(Date)``      | return the month of a date or datetime |
++----------------------+----------------------------------------+
+| ``DAY(Date)``        | return the day of a date or datetime   |
++----------------------+----------------------------------------+
+| ``HOUR(Datetime)``   | return the hours of a datetime         |
++----------------------+----------------------------------------+
+| ``MINUTE(Datetime)`` | return the minutes of a datetime       |
++----------------------+----------------------------------------+
+| ``SECOND(Datetime)`` | return the seconds of a datetime       |
++----------------------+----------------------------------------+
+| ``WEEKDAY(Date)``    | return the day of week of a date or    |
+|                      | datetime.  Sunday == 1, Saturday == 7. |
++----------------------+----------------------------------------+
+
+.. _RQLOtherFunctions:
+
+Other functions
+```````````````
++-------------------+--------------------------------------------------------------------+
+| ``ABS(num)``      |  return the absolute value of a number                             |
++-------------------+--------------------------------------------------------------------+
+| ``RANDOM()``      | return a pseudo-random value from 0.0 to 1.0                       |
++-------------------+--------------------------------------------------------------------+
+| ``FSPATH(X)``     | expect X to be an attribute whose value is stored in a             |
+|                   | :class:`BFSStorage` and return its path on the file system         |
++-------------------+--------------------------------------------------------------------+
+| ``FTIRANK(X)``    | expect X to be an entity used in a has_text relation, and return a |
+|                   | number corresponding to the rank order of each resulting entity    |
++-------------------+--------------------------------------------------------------------+
+| ``CAST(Type, X)`` | expect X to be an attribute and return it casted into the given    |
+|                   | final type                                                         |
++-------------------+--------------------------------------------------------------------+
+
+
+.. _RQLExamples:
+
+Examples
+~~~~~~~~
+
+- *Search for the object of identifier 53*
+
+  .. sourcecode:: sql
+
+        Any X WHERE X eid 53
+
+- *Search material such as comics, owned by syt and available*
+
+  .. sourcecode:: sql
+
+        Any X WHERE X is Document,
+                    X occurence_of F, F class C, C name 'Comics',
+                    X owned_by U, U login 'syt',
+                    X available TRUE
+
+- *Looking for people working for eurocopter interested in training*
+
+  .. sourcecode:: sql
+
+        Any P WHERE P is Person, P work_for S, S name 'Eurocopter',
+                    P interested_by T, T name 'training'
+
+- *Search note less than 10 days old written by jphc or ocy*
+
+  .. sourcecode:: sql
+
+        Any N WHERE N is Note, N written_on D, D day> (today -10),
+                    N written_by P, P name 'jphc' or P name 'ocy'
+
+- *Looking for people interested in training or living in Paris*
+
+  .. sourcecode:: sql
+
+        Any P WHERE P is Person, EXISTS(P interested_by T, T name 'training') OR
+                    (P city 'Paris')
+
+- *The surname and firstname of all people*
+
+  .. sourcecode:: sql
+
+        Any N, P WHERE X is Person, X name N, X firstname P
+
+  Note that the selection of several entities generally force
+  the use of "Any" because the type specification applies otherwise
+  to all the selected variables. We could write here
+
+  .. sourcecode:: sql
+
+        String N, P WHERE X is Person, X name N, X first_name P
+
+
+  Note: You can not specify several types with * ... where X is FirstType or X is SecondType*.
+  To specify several types explicitly, you have to do
+
+
+  .. sourcecode:: sql
+
+        Any X WHERE X is IN (FirstType, SecondType)
+
+
+.. _RQLInsertQuery:
+
+Insertion query
+~~~~~~~~~~~~~~~
+
+    `INSERT` <entity type> V1 (, <entity type> V2) \ * `:` <assignments>
+    [ `WHERE` <restriction>]
+
+:assignments:
+   list of relations to assign in the form `V1 relationship V2 | <static value>`
+
+The restriction can define variables used in assignments.
+
+Caution, if a restriction is specified, the insertion is done for
+*each line result returned by the restriction*.
+
+- *Insert a new person named 'foo'*
+
+  .. sourcecode:: sql
+
+        INSERT Person X: X name 'foo'
+
+- *Insert a new person named 'foo', another called 'nice' and a 'friend' relation
+  between them*
+
+  .. sourcecode:: sql
+
+        INSERT Person X, Person Y: X name 'foo', Y name 'nice', X friend Y
+
+- *Insert a new person named 'foo' and a 'friend' relation with an existing
+  person called 'nice'*
+
+  .. sourcecode:: sql
+
+        INSERT Person X: X name 'foo', X friend  Y WHERE Y name 'nice'
+
+.. _RQLSetQuery:
+
+Update and relation creation queries
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    `SET` <assignements>
+    [ `WHERE` <restriction>]
+
+Caution, if a restriction is specified, the update is done *for
+each result line returned by the restriction*.
+
+- *Renaming of the person named 'foo' to 'bar' with the first name changed*
+
+  .. sourcecode:: sql
+
+        SET X name 'bar', X firstname 'original' WHERE X is Person, X name 'foo'
+
+- *Insert a relation of type 'know' between objects linked by
+  the relation of type 'friend'*
+
+  .. sourcecode:: sql
+
+        SET X know Y  WHERE X friend Y
+
+
+.. _RQLDeleteQuery:
+
+Deletion query
+~~~~~~~~~~~~~~
+
+    `DELETE` (<entity type> V) | (V1 relation v2 ),...
+    [ `WHERE` <restriction>]
+
+Caution, if a restriction is specified, the deletion is made *for
+each line result returned by the restriction*.
+
+- *Deletion of the person named 'foo'*
+
+  .. sourcecode:: sql
+
+        DELETE Person X WHERE X name 'foo'
+
+- *Removal of all relations of type 'friend' from the person named 'foo'*
+
+  .. sourcecode:: sql
+
+        DELETE X friend Y WHERE X is Person, X name 'foo'
+
+
+.. _Yapps: http://theory.stanford.edu/~amitp/yapps/
+.. _Left outer join: http://en.wikipedia.org/wiki/Join_(SQL)#Left_outer_join
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/cubes/available-cubes.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,66 @@
+.. _AvailableCubes:
+
+Available cubes
+---------------
+
+An instance is made of several basic cubes. In the set of available
+basic cubes we can find for example:
+
+Base entity types
+~~~~~~~~~~~~~~~~~
+* addressbook_: PhoneNumber and PostalAddress
+* card_: Card, generic documenting card
+* event_: Event (define events, display them in calendars)
+* file_: File (to allow users to upload and store binary or text files)
+* link_: Link (to collect links to web resources)
+* mailinglist_: MailingList (to reference a mailing-list and the URLs
+  for its archives and its admin interface)
+* person_: Person (easily mixed with addressbook)
+* task_: Task (something to be done between start and stop date)
+* zone_: Zone (to define places within larger places, for example a
+  city in a state in a country)
+
+
+Classification
+~~~~~~~~~~~~~~
+* folder_: Folder (to organize things by grouping them in folders)
+* keyword_: Keyword (to define classification schemes)
+* tag_: Tag (to tag anything)
+
+Other features
+~~~~~~~~~~~~~~
+* basket_: Basket (like a shopping cart)
+* blog_: a blogging system using Blog and BlogEntry entity types
+* comment_: system to attach comment threads to entities)
+* email_: archiving management for emails (`Email`, `Emailpart`,
+  `Emailthread`), trigger action in cubicweb through email
+
+
+
+
+
+.. _addressbook: http://www.cubicweb.org/project/cubicweb-addressbook
+.. _basket: http://www.cubicweb.org/project/cubicweb-basket
+.. _card: http://www.cubicweb.org/project/cubicweb-card
+.. _blog: http://www.cubicweb.org/project/cubicweb-blog
+.. _comment: http://www.cubicweb.org/project/cubicweb-comment
+.. _email: http://www.cubicweb.org/project/cubicweb-email
+.. _event: http://www.cubicweb.org/project/cubicweb-event
+.. _file: http://www.cubicweb.org/project/cubicweb-file
+.. _folder: http://www.cubicweb.org/project/cubicweb-folder
+.. _keyword: http://www.cubicweb.org/project/cubicweb-keyword
+.. _link: http://www.cubicweb.org/project/cubicweb-link
+.. _mailinglist: http://www.cubicweb.org/project/cubicweb-mailinglist
+.. _person: http://www.cubicweb.org/project/cubicweb-person
+.. _tag: http://www.cubicweb.org/project/cubicweb-tag
+.. _task: http://www.cubicweb.org/project/cubicweb-task
+.. _zone: http://www.cubicweb.org/project/cubicweb-zone
+
+To declare the use of a cube, once installed, add the name of the cube
+and its dependency relation in the `__depends_cubes__` dictionary
+defined in the file `__pkginfo__.py` of your own component.
+
+.. note::
+  The listed cubes above are available as debian-packages on `CubicWeb's forge`_.
+
+.. _`CubicWeb's forge`: http://www.cubicweb.org/project?vtitle=All%20cubicweb%20projects
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/cubes/cc-newcube.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,58 @@
+Creating a new cube from scratch
+--------------------------------
+
+Let's start by creating the cube environment in which we will develop ::
+
+  cd ~/cubes
+  # use cubicweb-ctl to generate a template for the cube
+  # will ask some questions, most with nice default
+  cubicweb-ctl newcube mycube
+  # makes the cube source code managed by mercurial
+  cd mycube
+  hg init
+  hg add .
+  hg ci
+
+If all went well, you should see the cube you just created in the list
+returned by ``cubicweb-ctl list`` in the  *Available cubes* section.
+If not, please refer to :ref:`ConfigurationEnv`.
+
+To reuse an existing cube, add it to the list named
+``__depends_cubes__`` which is defined in :file:`__pkginfo__.py`.
+This variable is used for the instance packaging (dependencies handled
+by system utility tools such as APT) and to find used cubes when the
+database for the instance is created (import_erschema('MyCube') will
+not properly work otherwise).
+
+On a Unix system, the available cubes are usually stored in the
+directory :file:`/usr/share/cubicweb/cubes`. If you are using the
+cubicweb mercurial repository (:ref:`SourceInstallation`), the cubes
+are searched in the directory
+:file:`/path/to/cubicweb_toplevel/cubes`. In this configuration
+cubicweb itself ought to be located at
+:file:`/path/to/cubicweb_toplevel/cubicweb`.
+
+.. note::
+
+    Please note that if you do not wish to use default directory for your cubes
+    library, you should set the :envvar:`CW_CUBES_PATH` environment variable to
+    add extra directories where cubes will be search, and you'll then have to use
+    the option `--directory` to specify where you would like to place the source
+    code of your cube:
+
+    ``cubicweb-ctl newcube --directory=/path/to/cubes/library mycube``
+
+
+.. XXX resurrect once live-server is back
+.. Usage of :command:`cubicweb-ctl liveserver`
+.. -------------------------------------------
+
+.. To quickly test a new cube, you can also use the `liveserver` command for cubicweb-ctl
+.. which allows to create an instance in memory (using an SQLite database by
+.. default) and make it accessible through a web server ::
+
+..   cubicweb-ctl live-server mycube
+
+.. or by using an existing database (SQLite or Postgres)::
+
+..   cubicweb-ctl live-server -s myfile_sources mycube
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/cubes/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,11 @@
+Cubes
+=====
+
+This chapter describes how to define your own cubes and reuse already available cubes.
+
+.. toctree::
+   :maxdepth: 1
+
+   layout.rst
+   cc-newcube.rst
+   available-cubes.rst
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/cubes/layout.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,153 @@
+
+.. _foundationsCube:
+
+.. _cubelayout:
+
+Standard structure for a cube
+-----------------------------
+
+A cube is structured as follows:
+
+::
+
+  mycube/
+  |
+  |-- data/
+  |   |-- cubes.mycube.css
+  |   |-- cubes.mycube.js
+  |   `-- external_resources
+  |
+  |-- debian/
+  |   |-- changelog
+  |   |-- compat
+  |   |-- control
+  |   |-- copyright
+  |   |-- cubicweb-mycube.prerm
+  |   `-- rules
+  |
+  |-- entities.py
+  |
+  |-- i18n/
+  |   |-- en.po
+  |   |-- es.po
+  |   `-- fr.po
+  |
+  |-- __init__.py
+  |
+  |-- MANIFEST.in
+  |
+  |-- migration/
+  |   |-- postcreate.py
+  |   `-- precreate.py
+  |
+  |-- __pkginfo__.py
+  |
+  |-- schema.py
+  |
+  |-- setup.py
+  |
+  |-- site_cubicweb.py
+  |
+  |-- hooks.py
+  |
+  |-- test/
+  |   |-- data/
+  |   |   `-- bootstrap_cubes
+  |   |-- pytestconf.py
+  |   |-- realdb_test_mycube.py
+  |   `-- test_mycube.py
+  |
+  `-- views.py
+
+
+We can use subpackages instead of python modules for ``views.py``, ``entities.py``,
+``schema.py`` or ``hooks.py``. For example, we could have:
+
+::
+
+  mycube/
+  |
+  |-- entities.py
+  |-- hooks.py
+  `-- views/
+      |-- __init__.py
+      |-- forms.py
+      |-- primary.py
+      `-- widgets.py
+
+
+where :
+
+* ``schema`` contains the schema definition (server side only)
+* ``entities`` contains the entity definitions (server side and web interface)
+* ``hooks`` contains hooks and/or views notifications (server side only)
+* ``views`` contains the web interface components (web interface only)
+* ``test`` contains tests related to the cube (not installed)
+* ``i18n`` contains message catalogs for supported languages (server side and
+  web interface)
+* ``data`` contains data files for static content (images, css,
+  javascript code)...(web interface only)
+* ``migration`` contains initialization files for new instances (``postcreate.py``)
+  and a file containing dependencies of the component depending on the version
+  (``depends.map``)
+* ``debian`` contains all the files managing debian packaging (you will find
+  the usual files ``control``, ``rules``, ``changelog``... not installed)
+* file ``__pkginfo__.py`` provides component meta-data, especially the distribution
+  and the current version (server side and web interface) or sub-cubes used by
+  the cube.
+
+
+At least you should have the file ``__pkginfo__.py``.
+
+
+The :file:`__init__.py` and :file:`site_cubicweb.py` files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. XXX WRITEME
+
+The :file:`__pkginfo__.py` file
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It contains metadata describing your cube, mostly useful for packaging.
+
+Two important attributes of this module are __depends__ and __recommends__
+dictionaries that indicates what should be installed (and each version if
+necessary) for the cube to work.
+
+Dependency on other cubes are expected to be of the form 'cubicweb-<cubename>'.
+
+When an instance is created, dependencies are automatically installed, while
+recommends are not.
+
+Recommends may be seen as a kind of 'weak dependency'. Eg, the most important
+effect of recommending a cube is that, if cube A recommends cube B, the cube B
+will be loaded before the cube A (same thing happend when A depends on B).
+
+Having this behaviour is sometime desired: on schema creation, you may rely on
+something defined in the other's schema; on database creation, on something
+created by the other's postcreate, and so on.
+
+
+:file:`migration/precreate.py` and :file:`migration/postcreate.py`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. XXX detail steps of instance creation
+
+
+External resources such as image, javascript and css files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. XXX naming convention external_resources file
+
+
+Out-of the box testing
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. XXX MANIFEST.in, __pkginfo__.include_dirs, debian
+
+
+Packaging and distribution
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. XXX MANIFEST.in, __pkginfo__.include_dirs, debian
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/dataimport.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,138 @@
+.. -*- coding: utf-8 -*-
+
+.. _dataimport:
+
+Dataimport
+==========
+
+*CubicWeb* is designed to manipulate huge of amount of data, and provides utilities to do so.
+
+The main entry point is :mod:`cubicweb.dataimport.importer` which defines an
+:class:`ExtEntitiesImporter` class responsible for importing data from an external source in the
+form :class:`ExtEntity` objects. An :class:`ExtEntity` is a transitional representation of an
+entity to be imported in the CubicWeb instance; building this representation is usually
+domain-specific -- e.g. dependent of the kind of data source (RDF, CSV, etc.) -- and is thus the
+responsibility of the end-user.
+
+Along with the importer, a *store* must be selected, which is responsible for insertion of data into
+the database. There exists different kind of stores_, allowing to insert data within different
+levels of the *CubicWeb* API and with different speed/security tradeoffs. Those keeping all the
+*CubicWeb* hooks and security will be slower but the possible errors in insertion (bad data types,
+integrity error, ...) will be handled.
+
+
+Example
+-------
+
+Consider the following schema snippet.
+
+.. code-block:: python
+
+    class Person(EntityType):
+        name = String(required=True)
+
+    class knows(RelationDefinition):
+        subject = 'Person'
+        object = 'Person'
+
+along with some data in a ``people.csv`` file::
+
+    # uri,name,knows
+    http://www.example.org/alice,Alice,
+    http://www.example.org/bob,Bob,http://www.example.org/alice
+
+The following code (using a shell context) defines a function `extentities_from_csv` to read
+`Person` external entities coming from a CSV file and calls the :class:`ExtEntitiesImporter` to
+insert corresponding entities and relations into the CubicWeb instance.
+
+.. code-block:: python
+
+    from cubicweb.dataimport import ucsvreader, RQLObjectStore
+    from cubicweb.dataimport.importer import ExtEntity, ExtEntitiesImporter
+
+    def extentities_from_csv(fpath):
+        """Yield Person ExtEntities read from `fpath` CSV file."""
+        with open(fpath) as f:
+            for uri, name, knows in ucsvreader(f, skipfirst=True, skip_empty=False):
+                yield ExtEntity('Personne', uri,
+                                {'nom': set([name]), 'connait': set([knows])})
+
+    extenties = extentities_from_csv('people.csv')
+    store = RQLObjectStore(cnx)
+    importer = ExtEntitiesImporter(schema, store)
+    importer.import_entities(extenties)
+    commit()
+    rset = cnx.execute('String N WHERE X nom N, X connait Y, Y nom "Alice"')
+    assert rset[0][0] == u'Bob', rset
+
+Importer API
+------------
+
+.. automodule:: cubicweb.dataimport.importer
+
+
+Stores
+~~~~~~
+
+Stores are responsible to insert properly formatted entities and relations into the database. They
+have the following API::
+
+    >>> user_eid = store.prepare_insert_entity('CWUser', login=u'johndoe')
+    >>> group_eid = store.prepare_insert_entity('CWUser', name=u'unknown')
+    >>> store.relate(user_eid, 'in_group', group_eid)
+    >>> store.flush()
+    >>> store.commit()
+    >>> store.finish()
+
+Some stores **require a flush** to copy data in the database, so if you want to have store
+independent code you should explicitly call it. (There may be multiple flushes during the
+process, or only one at the end if there is no memory issue). This is different from the
+commit which validates the database transaction. At last, the `finish()` method should be called in
+case the store requires additional work once everything is done.
+
+* ``prepare_insert_entity(<entity type>, **kwargs) -> eid``: given an entity
+  type, attributes and inlined relations, return the eid of the entity to be
+  inserted, *with no guarantee that anything has been inserted in database*.
+
+* ``prepare_update_entity(<entity type>, eid, **kwargs) -> None``: given an
+  entity type and eid, promise for update given attributes and inlined
+  relations *with no guarantee that anything has been inserted in database*.
+
+* ``prepare_insert_relation(eid_from, rtype, eid_to) -> None``: indicate that a
+  relation ``rtype`` should be added between entities with eids ``eid_from``
+  and ``eid_to``. Similar to ``prepare_insert_entity()``, *there is no
+  guarantee that the relation has been inserted in database*.
+
+* ``flush() -> None``: flush any temporary data to database. May be called
+  several times during an import.
+
+* ``commit() -> None``: commit the database transaction.
+
+* ``finish() -> None``: additional stuff to do after import is terminated.
+
+ObjectStore
+-----------
+
+This store keeps objects in memory for *faster* validation. It may be useful in development
+mode. However, as it will not enforce the constraints of the schema nor insert anything in the
+database, so it may miss some problems.
+
+
+RQLObjectStore
+--------------
+
+This store works with an actual RQL repository, and it may be used in production mode.
+
+
+NoHookRQLObjectStore
+--------------------
+
+This store works similarly to the *RQLObjectStore* but bypasses some *CubicWeb* hooks to be faster.
+
+
+SQLGenObjectStore
+-----------------
+
+This store relies on *COPY FROM*/execute many sql commands to directly push data using SQL commands
+rather than using the whole *CubicWeb* API. For now, **it only works with PostgresSQL** as it requires
+the *COPY FROM* command.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/datamodel/baseschema.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,42 @@
+.. _pre_defined_entity_types:
+
+Pre-defined entities in the library
+-----------------------------------
+
+The library defines a set of entity schemas that are required by the system
+or commonly used in *CubicWeb* instances.
+
+
+Entity types used to store the schema
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* _`CWEType`, entity type
+* _`CWRType`, relation type
+* _`CWRelation`, relation definition
+* _`CWAttribute`, attribute relation definition
+* _`CWConstraint`,  `CWConstraintType`, `RQLExpression`
+
+Entity types used to manage users and permissions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* _`CWUser`, system users
+* _`CWGroup`, users groups
+
+Entity types used to manage workflows
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* :ref:`Workflow <Workflow>`, workflow entity, linked to some entity types which may use this workflow
+* _`State`, workflow state
+* _`Transition`, workflow transition
+* _`TrInfo`, record of a transition trafic for an entity
+
+Other entity types
+~~~~~~~~~~~~~~~~~~
+* _`CWCache`, cache entities used to improve performances
+* _`CWProperty`, used to configure the instance
+
+* _`EmailAddress`, email address, used by the system to send notifications
+  to the users and also used by others optionnals schemas
+
+* _`Bookmark`, an entity type used to allow a user to customize his links within
+  the instance
+
+* _`ExternalUri`, used for semantic web site to indicate that an entity is the
+  same as another from an external site
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/datamodel/define-workflows.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,160 @@
+.. -*- coding: utf-8 -*-
+
+.. _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.
+
+We will define a simple workflow for a blog, with only the following two states:
+`submitted` and `published`. You may want to take a look at :ref:`TutosBase` if
+you want to quickly setup an instance running a blog.
+
+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
+its state should be `submitted`. To be visible to all, it has to
+be in the state `published`. To move it from `submitted` to `published`,
+we need a transition that we can call `approve_blogentry`.
+
+A BlogEntry state should not be modifiable by every user.
+So we have to define a group of users, `moderators`, and
+this group will have appropriate permissions to publish a BlogEntry.
+
+There are two ways to create a workflow: from the user interface, or
+by defining it in ``migration/postcreate.py``. This script is executed
+each time a new ``cubicweb-ctl db-init`` is done.  We strongly
+recommend to create the workflow in ``migration/postcreate.py`` and we
+will now show you how. Read `Two bits of warning`_ to understand why.
+
+The state of an entity is managed by the `in_state` attribute which
+can be added to your entity schema by inheriting from
+`cubicweb.schema.WorkflowableEntityType`.
+
+
+About our example of BlogEntry, we must have:
+
+.. sourcecode:: python
+
+  from cubicweb.schema import WorkflowableEntityType
+
+  class BlogEntry(WorkflowableEntityType):
+      ...
+
+
+Creating states, transitions and group permissions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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` 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
+``Transition`` which are standard *CubicWeb* entity types.
+
+To define a workflow for BlogDemo, please add the following lines
+to ``migration/postcreate.py``:
+
+.. sourcecode:: python
+
+  _ = unicode
+
+  moderators = add_entity('CWGroup', name=u"moderators")
+
+This adds the `moderators` user group.
+
+.. sourcecode:: python
+
+  wf = add_workflow(u'blog publication workflow', 'BlogEntry')
+
+At first, instanciate a new workflow object with a gentle description
+and the concerned entity types (this one can be a tuple for multiple
+value).
+
+.. sourcecode:: python
+
+  submitted = wf.add_state(_('submitted'), initial=True)
+  published = wf.add_state(_('published'))
+
+This will create two entities of type ``State``, one with name
+'submitted', and the other with name 'published'.
+
+``add_state`` expects as first argument the name of the state you want
+to create and an optional argument to say if it is supposed to be the
+initial state of the entity type.
+
+.. sourcecode:: python
+
+  wf.add_transition(_('approve_blogentry'), (submitted,), published, ('moderators', 'managers'),)
+
+This will create an entity of type ``Transition`` with name
+`approve_blogentry` which will be linked to the ``State`` entities
+created before.
+
+``add_transition`` expects
+
+  * as the first argument: the name of the transition
+  * then the list of states on which the transition can be triggered,
+  * the target state of the transition,
+  * and the permissions
+    (e.g. a list of user groups who can apply the transition; the user
+    has to belong to at least one of the listed group to perform the action).
+
+.. sourcecode:: python
+
+  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.
+
+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
+only perform the action if the two conditions are satisfied.
+
+If we use an RQL condition on a transition, we can use the following variables:
+
+* `X`, the entity on which we may pass the transition
+* `U`, the user executing that may pass the transition
+
+
+.. image:: ../../images/03-transitions-view_en.png
+
+You can notice that in the action box of a BlogEntry, the state is now
+listed as well as the possible transitions for the current state
+defined by the workflow.
+
+The transitions will only be displayed for users having the right permissions.
+In our example, the transition `approve_blogentry` will only be displayed
+for the users belonging to the group `moderators` or `managers`.
+
+
+Two bits of warning
+~~~~~~~~~~~~~~~~~~~
+
+We could perfectly use the administration interface to do these
+operations. It is a convenient thing to do at times (when doing
+development, to quick-check things). But it is not recommended beyond
+that because it is a bit complicated to do it right and it will be
+only local to your instance (or, said a bit differently, such a
+workflow only exists in an instance database). Furthermore, you cannot
+write unit tests against deployed instances, and experience shows it
+is mandatory to have tests for any mildly complicated workflow
+setup.
+
+Indeed, if you create the states and transitions through the user
+interface, next time you initialize the database you will have to
+re-create all the workflow entities. The user interface should only be
+a reference for you to view the states and transitions, but is not the
+appropriate interface to define your application workflow.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/datamodel/definition.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,912 @@
+.. -*- coding: utf-8 -*-
+
+.. _datamodel_definition:
+
+Yams *schema*
+-------------
+
+The **schema** is the core piece of a *CubicWeb* instance as it
+defines and handles the data model. It is based on entity types that
+are either already defined in `Yams`_ and the *CubicWeb* standard
+library; or more specific types defined in cubes. The schema for a
+cube is defined in a `schema` python module or package.
+
+.. _`Yams`: http://www.logilab.org/project/yams
+
+.. _datamodel_overview:
+
+Overview
+~~~~~~~~
+
+The core idea of the yams schema is not far from the classical
+`Entity-relationship`_ model. But while an E/R model (or `logical
+model`) traditionally has to be manually translated to a lower-level
+data description language (such as the SQL `create table`
+sublanguage), also often described as the `physical model`, no such
+step is required with |yams| and |cubicweb|.
+
+.. _`Entity-relationship`: http://en.wikipedia.org/wiki/Entity-relationship_model
+
+This is because in addition to high-level, logical |yams| models, one
+uses the |rql| data manipulation language to query, insert, update and
+delete data. |rql| abstracts as much of the underlying SQL database as
+a |yams| schema abstracts from the physical layout. The vagaries of
+SQL are avoided.
+
+As a bonus point, such abstraction make it quite comfortable to build
+or use different backends to which |rql| queries apply.
+
+So, as in the E/R formalism, the building blocks are ``entities``
+(:ref:`EntityType`), ``relationships`` (:ref:`RelationType`,
+:ref:`RelationDefinition`) and ``attributes`` (handled like relation
+with |yams|).
+
+Let us detail a little the divergences between E/R and |yams|:
+
+* all relationship are binary which means that to represent a
+  non-binary relationship, one has to use an entity,
+* relationships do not support attributes (yet, see:
+  http://www.cubicweb.org/ticket/341318), hence the need to reify it
+  as an entity if need arises,
+* all entities have an `eid` attribute (an integer) that is its
+  primary key (but it is possible to declare uniqueness on other
+  attributes)
+
+Also |yams| supports the notions of:
+
+* 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)
+
+Finally |yams| has a few concepts of its own:
+
+* relationships being oriented and binary, we call the left hand
+  entity type the `subject` and the right hand entity type the
+  `object`
+
+.. note::
+
+   The |yams| schema is available at run time through the .schema
+   attribute of the `vregistry`.  It's an instance of
+   :class:`cubicweb.schema.Schema`, which extends
+   :class:`yams.schema.Schema`.
+
+.. _EntityType:
+
+Entity type
+~~~~~~~~~~~
+
+An entity type is an instance of :class:`yams.schema.EntitySchema`. Each entity type has
+a set of attributes and relations, and some permissions which define who can add, read,
+update or delete entities of this type.
+
+The following built-in types are available: ``String``,
+``Int``, ``BigInt``, ``Float``, ``Decimal``, ``Boolean``,
+``Date``, ``Datetime``, ``Time``, ``Interval``, ``Byte`` and
+``Password``. They can only be used as attributes of an other entity
+type.
+
+There is also a `RichString` kindof type:
+
+ .. autoclass:: yams.buildobjs.RichString
+
+The ``__unique_together__`` class attribute is a list of tuples of names of
+attributes or inlined relations.  For each tuple, CubicWeb ensures the unicity
+of the combination.  For example:
+
+.. sourcecode:: python
+
+  class State(EntityType):
+      __unique_together__ = [('name', 'state_of')]
+
+      name = String(required=True)
+      state_of = SubjectRelation('Workflow', cardinality='1*',
+                                 composite='object', inlined=True)
+
+
+You can find more base entity types in
+:ref:`pre_defined_entity_types`.
+
+.. XXX yams inheritance
+
+.. _RelationType:
+
+Relation type
+~~~~~~~~~~~~~
+
+A relation type is an instance of
+:class:`yams.schema.RelationSchema`. A relation type is simply a
+semantic definition of a kind of relationship that may occur in an
+application.
+
+It may be referenced by zero, one or more relation definitions.
+
+It is important to choose a good name, at least to avoid conflicts
+with some semantically different relation defined in other cubes
+(since there's only a shared name space for these names).
+
+A relation type holds the following properties (which are hence shared
+between all relation definitions of that type):
+
+* `inlined`: boolean handling the physical optimization for archiving
+  the relation in the subject entity table, instead of creating a specific
+  table for the relation. This applies to relations where cardinality
+  of subject->relation->object is 0..1 (`?`) or 1..1 (`1`) for *all* its relation
+  definitions.
+
+* `symmetric`: boolean indicating that the relation is symmetrical, which
+  means that `X relation Y` implies `Y relation X`.
+
+.. _RelationDefinition:
+
+Relation definition
+~~~~~~~~~~~~~~~~~~~
+
+A relation definition is an instance of
+:class:`yams.schema.RelationDefinition`. It is a complete triplet
+"<subject entity type> <relation type> <object entity type>".
+
+When creating a new instance of that class, the corresponding
+:class:`RelationType` instance is created on the fly if necessary.
+
+Properties
+``````````
+
+The available properties for relation definitions are enumerated
+here. There are several kind of properties, as some relation
+definitions are actually attribute definitions, and other are not.
+
+Some properties may be completely optional, other may have a default
+value.
+
+Common properties for attributes and relations:
+
+* `description`: a unicode string describing an attribute or a
+  relation. By default this string will be used in the editing form of
+  the entity, which means that it is supposed to help the end-user and
+  should be flagged by the function `_` to be properly
+  internationalized.
+
+* `constraints`: a list of conditions/constraints that the relation has to
+  satisfy (c.f. `Constraints`_)
+
+* `cardinality`: a two character string specifying the cardinality of
+  the relation. The first character defines the cardinality of the
+  relation on the subject, and the second on the object. When a
+  relation can have multiple subjects or objects, the cardinality
+  applies to all, not on a one-to-one basis (so it must be
+  consistent...). Default value is '**'. The possible values are
+  inspired from regular expression syntax:
+
+    * `1`: 1..1
+    * `?`: 0..1
+    * `+`: 1..n
+    * `*`: 0..n
+
+Attributes properties:
+
+* `unique`: boolean indicating if the value of the attribute has to be
+  unique or not within all entities of the same type (false by
+  default)
+
+* `indexed`: boolean indicating if an index needs to be created for
+  this attribute in the database (false by default). This is useful
+  only if you know that you will have to run numerous searches on the
+  value of this attribute.
+
+* `default`: default value of the attribute. In case of date types, the values
+  which could be used correspond to the RQL keywords `TODAY` and `NOW`.
+
+* `metadata`: Is also accepted as an argument of the attribute contructor. It is
+  not really an attribute property. see `Metadata`_ for details.
+
+Properties for `String` attributes:
+
+* `fulltextindexed`: boolean indicating if the attribute is part of
+  the full text index (false by default) (*applicable on the type
+  `Byte` as well*)
+
+* `internationalizable`: boolean indicating if the value of the
+  attribute is internationalizable (false by default)
+
+Relation properties:
+
+* `composite`: string indicating that the subject (composite ==
+  'subject') is composed of the objects of the relations. For the
+  opposite case (when the object is composed of the subjects of the
+  relation), we just set 'object' as value. The composition implies
+  that when the relation is deleted (so when the composite is deleted,
+  at least), the composed are also deleted.
+
+* `fulltext_container`: string indicating if the value if the full
+  text indexation of the entity on one end of the relation should be
+  used to find the entity on the other end. The possible values are
+  'subject' or 'object'. For instance the use_email relation has that
+  property set to 'subject', since when performing a full text search
+  people want to find the entity using an email address, and not the
+  entity representing the email address.
+
+Constraints
+```````````
+
+By default, the available constraint types are:
+
+General Constraints
+......................
+
+* `SizeConstraint`: allows to specify a minimum and/or maximum size on
+  string (generic case of `maxsize`)
+
+* `BoundaryConstraint`: allows to specify a minimum and/or maximum value
+  on numeric types and date
+
+.. sourcecode:: python
+
+   from yams.constraints import BoundaryConstraint, TODAY, NOW, Attribute
+
+   class DatedEntity(EntityType):
+      start = Date(constraints=[BoundaryConstraint('>=', TODAY())])
+      end = Date(constraints=[BoundaryConstraint('>=', Attribute('start'))])
+
+   class Before(EntityType);
+      last_time = DateTime(constraints=[BoundaryConstraint('<=', NOW())])
+
+* `IntervalBoundConstraint`: allows to specify an interval with
+  included values
+
+.. sourcecode:: python
+
+     class Node(EntityType):
+         latitude = Float(constraints=[IntervalBoundConstraint(-90, +90)])
+
+* `UniqueConstraint`: identical to "unique=True"
+
+* `StaticVocabularyConstraint`: identical to "vocabulary=(...)"
+
+Constraints can be dependent on a fixed value (90, Date(2015,3,23)) or a variable.
+In this second case, yams can handle :
+
+* `Attribute`: compare to the value of another attribute.
+* `TODAY`: compare to the current Date.
+* `NOW`: compare to the current Datetime.
+
+RQL Based Constraints
+......................
+
+RQL based constraints may take three arguments. The first one is the ``WHERE``
+clause of a RQL query used by the constraint. The second argument ``mainvars``
+is the ``Any`` clause of the query. By default this include `S` reserved for the
+subject of the relation and `O` for the object. Additional variables could be
+specified using ``mainvars``. The argument expects a single string with all
+variable's name separated by spaces. The last one, ``msg``, is the error message
+displayed when the constraint fails. As RQLVocabularyConstraint never fails the
+third argument is not available.
+
+* `RQLConstraint`: allows to specify a RQL query that has to be satisfied
+  by the subject and/or the object of relation. In this query the variables
+  `S` and `O` are reserved for the relation subject and object entities.
+
+* `RQLVocabularyConstraint`: similar to the previous type of constraint except
+  that it does not express a "strong" constraint, which means it is only used to
+  restrict the values listed in the drop-down menu of editing form, but it does
+  not prevent another entity to be selected.
+
+* `RQLUniqueConstraint`: allows to the specify a RQL query that ensure that an
+  attribute is unique in a specific context. The Query must **never** return more
+  than a single result to be satisfied. In this query the variables `S` is
+  reserved for the relation subject entity. The other variables should be
+  specified with the second constructor argument (mainvars). This constraint type
+  should be used when __unique_together__ doesn't fit.
+
+.. XXX note about how to add new constraint
+
+.. _securitymodel:
+
+The security model
+~~~~~~~~~~~~~~~~~~
+
+The security model of `CubicWeb` is based on `Access Control List`.
+The main principles are:
+
+* users and groups of users
+* a user belongs to at least one group of user
+* permissions (`read`, `update`, `create`, `delete`)
+* permissions are assigned to groups (and not to users)
+
+For *CubicWeb* in particular:
+
+* we associate rights at the entities/relations schema level
+
+* the default groups are: `managers`, `users` and `guests`
+
+* users belong to the `users` group
+
+* there is a virtual group called `owners` to which we can associate only
+  `delete` and `update` permissions
+
+  * we can not add users to the `owners` group, they are implicitly added to it
+    according to the context of the objects they own
+
+  * the permissions of this group are only checked on `update`/`delete` actions
+    if all the other groups the user belongs to do not provide those permissions
+
+Setting permissions is done with the class attribute `__permissions__`
+of entity types and relation definitions. The value of this attribute
+is a dictionary where the keys are the access types (action), and the
+values are the authorized groups or rql expressions.
+
+For an entity type, the possible actions are `read`, `add`, `update` and
+`delete`.
+
+For a relation, the possible actions are `read`, `add`, and `delete`.
+
+For an attribute, the possible actions are `read`, `add` and `update`,
+and they are a refinement of an entity type permission.
+
+.. note::
+
+   By default, the permissions of an entity type attributes are
+   equivalent to the permissions of the entity type itself.
+
+   It is possible to provide custom attribute permissions which are
+   stronger than, or are more lenient than the entity type
+   permissions.
+
+   In a situation where all attributes were given custom permissions,
+   the entity type permissions would not be checked, except for the
+   `delete` action.
+
+For each access type, a tuple indicates the name of the authorized groups and/or
+one or multiple RQL expressions to satisfy to grant access. The access is
+provided if the user is in one of the listed groups or if one of the RQL condition
+is satisfied.
+
+Default permissions
+```````````````````
+
+The default permissions for ``EntityType`` are:
+
+.. sourcecode:: python
+
+   __permissions__ = {
+        'read': ('managers', 'users', 'guests',),
+        'update': ('managers', 'owners',),
+        'delete': ('managers', 'owners'),
+        'add': ('managers', 'users',)
+        }
+
+The default permissions for relations are:
+
+.. sourcecode:: python
+
+   __permissions__ = {'read': ('managers', 'users', 'guests',),
+                    'delete': ('managers', 'users'),
+                    'add': ('managers', 'users',)}
+
+The default permissions for attributes are:
+
+.. sourcecode:: python
+
+   __permissions__ = {'read': ('managers', 'users', 'guests',),
+                      'add': ('managers', ERQLExpression('U has_add_permission X'),
+                      'update': ('managers', ERQLExpression('U has_update_permission X')),}
+
+.. note::
+
+   The default permissions for attributes are not syntactically
+   equivalent to the default permissions of the entity types, but the
+   rql expressions work by delegating to the entity type permissions.
+
+
+The standard user groups
+````````````````````````
+
+* `guests`
+
+* `users`
+
+* `managers`
+
+* `owners`: virtual group corresponding to the entity's owner.
+  This can only be used for the actions `update` and `delete` of an entity
+  type.
+
+It is also possible to use specific groups if they are defined in the precreate
+script of the cube (``migration/precreate.py``). Defining groups in postcreate
+script or later makes them unavailable for security purposes (in this case, an
+`sync_schema_props_perms` command has to be issued in a CubicWeb shell).
+
+
+Use of RQL expression for write permissions
+```````````````````````````````````````````
+
+It is possible to define RQL expression to provide update permission (`add`,
+`delete` and `update`) on entity type / relation definitions. An rql expression
+is a piece of query (corresponds to the WHERE statement of an RQL query), and the
+expression will be considered as satisfied if it returns some results. They can
+not be used in `read` permission.
+
+To use RQL expression in entity type permission:
+
+* you have to use the class :class:`~cubicweb.schema.ERQLExpression`
+
+* in this expression, the variables `X` and `U` are pre-defined references
+  respectively on the current entity (on which the action is verified) and on the
+  user who send the request
+
+For RQL expressions on a relation type, the principles are the same except for
+the following:
+
+* you have to use the class :class:`~cubicweb.schema.RRQLExpression` instead of
+  :class:`~cubicweb.schema.ERQLExpression`
+
+* in the expression, the variables `S`, `O` and `U` are pre-defined references to
+  respectively the subject and the object of the current relation (on which the
+  action is being verified) and the user who executed the query
+
+To define security for attributes of an entity (non-final relation), you have to
+use the class :class:`~cubicweb.schema.ERQLExpression` in which `X` represents
+the entity the attribute belongs to.
+
+It is possible to use in those expression a special relation
+`has_<ACTION>_permission` where the subject is the user (eg 'U') and the object
+is any variable representing an entity (usually 'X' in
+:class:`~cubicweb.schema.ERQLExpression`, 'S' or 'O' in
+:class:`~cubicweb.schema.RRQLExpression`), meaning that the user needs to have
+permission to execute the action <ACTION> on the entities represented by this
+variable. It's recommanded to use this feature whenever possible since it
+simplify greatly complex security definition and upgrade.
+
+
+.. sourcecode:: python
+
+  class my_relation(RelationDefinition):
+    __permissions__ = {'read': ('managers', 'users'),
+                       'add': ('managers', RRQLExpression('U has_update_permission S')),
+                       'delete': ('managers', RRQLExpression('U has_update_permission S'))
+		       }
+
+In the above example, user will be allowed to add/delete `my_relation` if he has
+the `update` permission on the subject of the relation.
+
+.. note::
+
+  Potentially, the `use of an RQL expression to add an entity or a relation` can
+  cause problems for the user interface, because if the expression uses the
+  entity or the relation to create, we are not able to verify the permissions
+  before we actually added the entity (please note that this is not a problem for
+  the RQL server at all, because the permissions checks are done after the
+  creation). In such case, the permission check methods
+  (CubicWebEntitySchema.check_perm and has_perm) can indicate that the user is
+  not allowed to create this entity while it would obtain the permission.  To
+  compensate this problem, it is usually necessary in such case to use an action
+  that reflects the schema permissions but which check properly the permissions
+  so that it would show up only if possible.
+
+
+Use of RQL expression for reading rights
+````````````````````````````````````````
+
+The principles are the same but with the following restrictions:
+
+* you can not use rql expression for the `read` permission of relations and
+  attributes,
+
+* you can not use special `has_<ACTION>_permission` relation in the rql
+  expression.
+
+
+Important notes about write permissions checking
+````````````````````````````````````````````````
+
+Write permissions (e.g. 'add', 'update', 'delete') are checked in core hooks.
+
+When a permission is checked slightly vary according to if it's an entity or
+relation, and if the relation is an attribute relation or not). It's important to
+understand that since according to when a permission is checked, values returned
+by rql expressions may changes, hence the permission being granted or not.
+
+Here are the current rules:
+
+1. permission to add/update entity and its attributes are checked on
+   commit
+
+2. permission to delete an entity is checked in 'before_delete_entity' hook
+
+3. permission to add a relation is checked either:
+
+   - in 'before_add_relation' hook if the relation type is in the
+     `BEFORE_ADD_RELATIONS` set
+
+   - else at commit time if the relation type is in the `ON_COMMIT_ADD_RELATIONS`
+     set
+
+   - else in 'after_add_relation' hook (the default)
+
+4. permission to delete a relation is checked in 'before_delete_relation' hook
+
+Last but not least, remember queries issued from hooks and operation are by
+default 'unsafe', eg there are no read or write security checks.
+
+See :mod:`cubicweb.hooks.security` for more details.
+
+
+.. _yams_example:
+
+
+Derived attributes and relations
+--------------------------------
+
+.. note:: **TODO** Check organisation of the whole chapter of the documentation
+
+Cubicweb offers the possibility to *query* data using so called
+*computed* relations and attributes. Those are *seen* by RQL requests
+as normal attributes and relations but are actually derived from other
+attributes and relations. In a first section we'll informally review
+two typical use cases. Then we see how to use computed attributes and
+relations in your schema. Last we will consider various significant
+aspects of their implementation and the impact on their usage.
+
+Motivating use cases
+~~~~~~~~~~~~~~~~~~~~
+
+Computed (or reified) relations
+```````````````````````````````
+
+It often arises that one must represent a ternary relation, or a
+family of relations. For example, in the context of an exhibition
+catalog you might want to link all *contributors* to the *work* they
+contributed to, but this contribution can be as *illustrator*,
+*author*, *performer*, ...
+
+The classical way to describe this kind of information within an
+entity-relationship schema is to *reify* the relation, that is turn
+the relation into a entity. In our example the schema will have a
+*Contribution* entity type used to represent the family of the
+contribution relations.
+
+
+.. sourcecode:: python
+
+    class ArtWork(EntityType):
+        name = String()
+        ...
+
+    class Person(EntityType):
+        name = String()
+        ...
+
+    class Contribution(EntityType):
+        contributor = SubjectRelation('Person', cardinality='1*', inlined=True)
+        manifestation = SubjectRelation('ArtWork')
+        role = SubjectRelation('Role')
+
+    class Role(EntityType):
+        name = String()
+
+But then, in order to query the illustrator(s) ``I`` of a work ``W``,
+one has to write::
+
+    Any I, W WHERE C is Contribution, C contributor I, C manifestation W,
+                   C role R, R name 'illustrator'
+
+whereas we would like to be able to simply write::
+
+    Any I, W WHERE I illustrator_of W
+
+This is precisely what the computed relations allow.
+
+
+Computed (or synthesized) attribute
+```````````````````````````````````
+
+Assuming a trivial schema for describing employees in companies, one
+can be interested in the total of salaries payed by a company for
+all its employees. One has to write::
+
+    Any C, SUM(SA) GROUPBY S WHERE E works_for C, E salary SA
+
+whereas it would be most convenient to simply write::
+
+    Any C, TS WHERE C total_salary TS
+
+And this is again what computed attributes provide.
+
+
+Using computed attributes and relations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Computed (or reified) relations
+```````````````````````````````
+
+In the above case we would define the *computed relation*
+``illustrator_of`` in the schema by:
+
+.. sourcecode:: python
+
+    class illustrator_of(ComputedRelation):
+        rule  = ('C is Contribution, C contributor S, C manifestation O,'
+                 'C role R, R name "illustrator"')
+
+You will note that:
+
+* the ``S`` and ``O`` RQL variables implicitly identify the subject and
+  object of the defined computed relation, akin to what happens in
+  RRQLExpression
+* the possible subject and object entity types are inferred from the rule;
+* computed relation definitions always have empty *add* and *delete* permissions
+* *read* permissions can be defined, permissions from the relations used in the
+  rewrite rule **are not considered** ;
+* nothing else may be defined on the `ComputedRelation` subclass beside
+  description, permissions and rule (e.g. no cardinality, composite, etc.,).
+  `BadSchemaDefinition` is raised on attempt to specify other attributes;
+* computed relations can not be used in 'SET' and 'DELETE' rql queries
+  (`BadQuery` exception raised).
+
+
+NB: The fact that the *add* and *delete* permissions are *empty* even
+for managers is expected to make the automatic UI not attempt to edit
+them.
+
+Computed (or synthesized) attributes
+````````````````````````````````````
+
+In the above case we would define the *computed attribute*
+``total_salary`` on the ``Company`` entity type in the schema by:
+
+.. sourcecode:: python
+
+    class Company(EntityType):
+        name = String()
+        total_salary = Int(formula='Any SUM(SA) GROUPBY E WHERE P works_for X, E salary SA')
+
+* the ``X`` RQL variable implicitly identifies the entity holding the
+  computed attribute, akin to what happens in ERQLExpression;
+* the type inferred from the formula is checked against the declared type, and
+  `BadSchemaDefinition` is raised if they don't match;
+* the computed attributes always have empty *update* permissions
+* `BadSchemaDefinition` is raised on attempt to set 'update' permissions;
+* 'read' permissions can be defined, permissions regarding the formula
+  **are not considered**;
+* other attribute's property (inlined, ...) can be defined as for normal attributes;
+* Similarly to computed relation, computed attribute can't be used in 'SET' and
+  'DELETE' rql queries (`BadQuery` exception raised).
+
+
+API and implementation
+~~~~~~~~~~~~~~~~~~~~~~
+
+Representation in the data backend
+``````````````````````````````````
+
+Computed relations have no direct representation at the SQL table
+level.  Instead, each time a query is issued the query is rewritten to
+replace the computed relation by its equivalent definition and the
+resulting rewritten query is performed in the usual way.
+
+On the contrary, computed attributes are represented as a column in the
+table for their host entity type, just like normal attributes. Their
+value is kept up-to-date with respect to their defintion by a system
+of hooks (also called triggers in most RDBMS) which recomputes them
+when the relations and attributes they depend on are modified.
+
+Yams API
+````````
+
+When accessing the schema through the *yams API* (not when defining a
+schema in a ``schema.py`` file) the computed attributes and relations
+are represented as follows:
+
+relations
+    The ``yams.RelationSchema`` class has a new ``rule`` attribute
+    holding the rule as a string. If this attribute is set all others
+    must not be set.
+attributes
+    A new property ``formula`` is added on class
+    ``yams.RelationDefinitionSchema`` alomng with a new keyword
+    argument ``formula`` on the initializer.
+
+Migration
+`````````
+
+The migrations are to be handled as summarized in the array below.
+
++------------+---------------------------------------------------+---------------------------------------+
+|            | Computed rtype                                    | Computed attribute                    |
++============+===================================================+=======================================+
+| add        | * add_relation_type                               | * add_attribute                       |
+|            | * add_relation_definition should trigger an error | * add_relation_definition             |
++------------+---------------------------------------------------+---------------------------------------+
+| modify     | * sync_schema_prop_perms:                         | * sync_schema_prop_perms:             |
+|            |   checks the rule is                              |                                       |
+| (rule or   |   synchronized with the database                  |   - empty the cache,                  |
+| formula)   |                                                   |   - check formula,                    |
+|            |                                                   |   - make sure all the values get      |
+|            |                                                   |     updated                           |
++------------+---------------------------------------------------+---------------------------------------+
+| del        | * drop_relation_type                              | * drop_attribute                      |
+|            | * drop_relation_definition should trigger an error| * drop_relation_definition            |
++------------+---------------------------------------------------+---------------------------------------+
+
+
+Defining your schema using yams
+-------------------------------
+
+Entity type definition
+~~~~~~~~~~~~~~~~~~~~~~
+
+An entity type is defined by a Python class which inherits from
+:class:`yams.buildobjs.EntityType`.  The class definition contains the
+description of attributes and relations for the defined entity type.
+The class name corresponds to the entity type name. It is expected to
+be defined in the module ``mycube.schema``.
+
+:Note on schema definition:
+
+ The code in ``mycube.schema`` is not meant to be executed. The class
+ EntityType mentioned above is different from the EntitySchema class
+ described in the previous chapter. EntityType is a helper class to
+ make Entity definition easier. Yams will process EntityType classes
+ and create EntitySchema instances from these class definitions. Similar
+ manipulation happen for relations.
+
+When defining a schema using python files, you may use the following shortcuts:
+
+- `required`: boolean indicating if the attribute is required, ed subject cardinality is '1'
+
+- `vocabulary`: specify static possible values of an attribute
+
+- `maxsize`: integer providing the maximum size of a string (no limit by default)
+
+For example:
+
+.. sourcecode:: python
+
+  class Person(EntityType):
+    """A person with the properties and the relations necessary for my
+    application"""
+
+    last_name = String(required=True, fulltextindexed=True)
+    first_name = String(required=True, fulltextindexed=True)
+    title = String(vocabulary=('Mr', 'Mrs', 'Miss'))
+    date_of_birth = Date()
+    works_for = SubjectRelation('Company', cardinality='?*')
+
+
+The entity described above defines three attributes of type String,
+last_name, first_name and title, an attribute of type Date for the date of
+birth and a relation that connects a `Person` to another entity of type
+`Company` through the semantic `works_for`.
+
+
+
+:Naming convention:
+
+ Entity class names must start with an uppercase letter. The common
+ usage is to use ``CamelCase`` names.
+
+ Attribute and relation names must start with a lowercase letter. The
+ common usage is to use ``underscore_separated_words``. Attribute and
+ relation names starting with a single underscore are permitted, to
+ denote a somewhat "protected" or "private" attribute.
+
+ In any case, identifiers starting with "CW" or "cw" are reserved for
+ internal use by the framework.
+
+ .. _Metadata:
+
+ Some attribute using the name of another attribute as prefix are considered
+ metadata.  For example, if an EntityType have both a ``data`` and
+ ``data_format`` attribute, ``data_format`` is view as the ``format`` metadata
+ of ``data``. Later the :meth:`cw_attr_metadata` method will allow you to fetch
+ metadata related to an attribute. There are only three valid metadata names:
+ ``format``, ``encoding`` and ``name``.
+
+
+The name of the Python attribute corresponds to the name of the attribute
+or the relation in *CubicWeb* application.
+
+An attribute is defined in the schema as follows::
+
+    attr_name = AttrType(*properties, metadata={})
+
+where
+
+* `AttrType`: is one of the type listed in EntityType_,
+
+* `properties`: is a list of the attribute needs to satisfy (see `Properties`_
+  for more details),
+
+* `metadata`: is a dictionary of meta attributes related to ``attr_name``.
+  Dictionary keys are the name of the meta attribute. Dictionary values
+  attributes objects (like the content of ``AttrType``). For each entry of the
+  metadata dictionary a ``<attr_name>_<key> = <value>`` attribute is
+  automaticaly added to the EntityType.  see `Metadata`_ section for details
+  about valid key.
+
+
+ ---
+
+While building your schema
+
+* it is possible to use the attribute `meta` to flag an entity type as a `meta`
+  (e.g. used to describe/categorize other entities)
+
+.. XXX the paragraph below needs clarification and / or moving out in
+.. another place
+
+*Note*: if you end up with an `if` in the definition of your entity, this probably
+means that you need two separate entities that implement the `ITree` interface and
+get the result from `.children()` which ever entity is concerned.
+
+.. Inheritance
+.. ```````````
+.. XXX feed me
+
+
+Definition of relations
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. XXX add note about defining relation type / definition
+
+A relation is defined by a Python class heriting `RelationType`. The name
+of the class corresponds to the name of the type. The class then contains
+a description of the properties of this type of relation, and could as well
+contain a string for the subject and a string for the object. This allows to create
+new definition of associated relations, (so that the class can have the
+definition properties from the relation) for example ::
+
+  class locked_by(RelationType):
+    """relation on all entities indicating that they are locked"""
+    inlined = True
+    cardinality = '?*'
+    subject = '*'
+    object = 'CWUser'
+
+If provided, the `subject` and `object` attributes denote the subject
+and object of the various relation definitions related to the relation
+type. Allowed values for these attributes are:
+
+* a string corresponding to an entity type
+* a tuple of string corresponding to multiple entity types
+* the '*' special string, meaning all types of entities
+
+When a relation is not inlined and not symmetrical, and it does not require
+specific permissions, it can be defined using a `SubjectRelation`
+attribute in the EntityType class. The first argument of `SubjectRelation` gives
+the entity type for the object of the relation.
+
+:Naming convention:
+
+ Although this way of defining relations uses a Python class, the
+ naming convention defined earlier prevails over the PEP8 conventions
+ used in the framework: relation type class names use
+ ``underscore_separated_words``.
+
+:Historical note:
+
+   It has been historically possible to use `ObjectRelation` which
+   defines a relation in the opposite direction. This feature is
+   deprecated and therefore should not be used in newly written code.
+
+:Future deprecation note:
+
+  In an even more remote future, it is quite possible that the
+  SubjectRelation shortcut will become deprecated, in favor of the
+  RelationType declaration which offers some advantages in the context
+  of reusable cubes.
+
+
+
+
+Handling schema changes
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Also, it should be clear that to properly handle data migration, an
+instance's schema is stored in the database, so the python schema file
+used to defined it is only read when the instance is created or
+upgraded.
+
+.. XXX complete me
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/datamodel/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,12 @@
+Data model
+==========
+
+This chapter describes how you define a schema and how to make it evolves as the time goes.
+
+.. toctree::
+   :maxdepth: 1
+
+   definition
+   metadata
+   baseschema
+   define-workflows
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/datamodel/metadata.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,37 @@
+
+Metadata
+--------
+
+.. index::
+   schema: meta-data;
+   schema: eid; creation_date; modification_data; cwuri
+   schema: created_by; owned_by; is; is_instance;
+
+Each entity type in |cubicweb| has at least the following meta-data attributes and relations:
+
+`eid`
+  entity's identifier which is unique in an instance. We usually call this identifier `eid` for historical reason.
+
+`creation_date`
+  Date and time of the creation of the entity.
+
+`modification_date`
+  Date and time of the latest modification of an entity.
+
+`cwuri`
+  Reference URL of the entity, which is not expected to change.
+
+`created_by`
+  Relation to the :ref:`users <CWUser>` who has created the entity
+
+`owned_by`
+  Relation to :ref:`users <CWUser>` whom the entity belongs; usually the creator but not
+  necessary, and it could have multiple owners notably for permission control
+
+`is`
+  Relation to the :ref:`entity type <CWEType>` of which type the entity is.
+
+`is_instance`
+  Relation to the :ref:`entity types <CWEType>` of which type the
+  entity is an instance of.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/devcore/dbapi.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,133 @@
+.. _dbapi:
+
+Python/RQL API
+~~~~~~~~~~~~~~
+
+The Python API developped to interface with RQL is inspired from the standard db-api,
+with a Connection object having the methods cursor, rollback and commit essentially.
+The most important method is the `execute` method of a cursor.
+
+.. sourcecode:: python
+
+   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
+
+The `Connection` object owns the methods `commit` and `rollback`. You
+*should never need to use them* during the development of the web
+interface based on the *CubicWeb* framework as it determines the end
+of the transaction depending on the query execution success. They are
+however useful in other contexts such as tests or custom controllers.
+
+.. note::
+
+  If a query generates an error related to security (:exc:`Unauthorized`) or to
+  integrity (:exc:`ValidationError`), the transaction can still continue but you
+  won't be able to commit it, a rollback will be necessary to start a new
+  transaction.
+
+  Also, a rollback is automatically done if an error occurs during commit.
+
+.. note::
+
+   A :exc:`ValidationError` has a `entity` attribute. In CubicWeb,
+   this atttribute is set to the entity's eid (not a reference to the
+   entity itself).
+
+Executing RQL queries from a view or a hook
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When you're within code of the web interface, the db-api like connexion is
+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
+you're directly inside the data-server), so you'll have to use the execute method
+of the session object.
+
+
+Proper usage of `.execute`
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Let's say you want to get T which is in configuration C, this translates to:
+
+.. sourcecode:: python
+
+   self._cw.execute('Any T WHERE T in_conf C, C eid %s' % entity.eid)
+
+But it must be written in a syntax that will benefit from the use
+of a cache on the RQL server side:
+
+.. sourcecode:: python
+
+   self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid})
+
+The syntax tree is built once for the "generic" RQL and can be re-used
+with a number of different eids. There rql IN operator is an exception
+to this rule.
+
+.. sourcecode:: python
+
+   self._cw.execute('Any T WHERE T in_conf C, C name IN (%s)'
+                    % ','.join(['foo', 'bar']))
+
+Alternativelly, some of the common data related to an entity can be
+obtained from the `entity.related()` method (which is used under the
+hood by the orm when you use attribute access notation on an entity to
+get a relation. The initial request would then be translated to:
+
+.. sourcecode:: python
+
+   entity.related('in_conf', 'object')
+
+Additionnaly this benefits from the fetch_attrs policy (see
+:ref:`FetchAttrs`) eventually defined on the class element, which says
+which attributes must be also loaded when the entity is loaded through
+the orm.
+
+
+.. _resultset:
+
+The `ResultSet` API
+~~~~~~~~~~~~~~~~~~~
+
+ResultSet instances are a very commonly manipulated object. They have
+a rich API as seen below, but we would like to highlight a bunch of
+methods that are quite useful in day-to-day practice:
+
+* `__str__()` (applied by `print`) gives a very useful overview of both
+  the underlying RQL expression and the data inside; unavoidable for
+  debugging purposes
+
+* `printable_rql()` produces back a well formed RQL expression as a
+  string; it is very useful to build views
+
+* `entities()` returns a generator on all entities of the result set
+
+* `get_entity(row, col)` gets the entity at row, col coordinates; one
+  of the most used result set method
+
+.. autoclass:: cubicweb.rset.ResultSet
+   :members:
+
+
+The `Cursor` and `Connection` API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The whole cursor API is developped below.
+
+.. note::
+
+  In practice you'll usually use the `.execute` method on the _cw object of
+  appobjects. Usage of other methods is quite rare.
+
+.. autoclass:: cubicweb.dbapi.Cursor
+   :members:
+
+.. autoclass:: cubicweb.dbapi.Connection
+   :members:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/devcore/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,8 @@
+Core APIs
+=========
+
+.. toctree::
+   :maxdepth: 1
+
+   reqbase.rst
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/devcore/reqbase.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,40 @@
+Request and ResultSet methods
+-----------------------------
+
+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 :).
+
+`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
+
+`And more...`:
+
+* `tal_render(template, variables)`, renders a precompiled page template with
+  variables in the given dictionary as context
+
+
+Result set methods
+~~~~~~~~~~~~~~~~~~
+
+* `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
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/entityclasses/adapters.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,167 @@
+.. _adapters:
+
+Interfaces and Adapters
+-----------------------
+
+Interfaces are the same thing as object-oriented programming `interfaces`_.
+Adapter refers to a well-known `adapter`_ design pattern that helps separating
+concerns in object oriented applications.
+
+.. _`interfaces`: http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
+.. _`adapter`: http://en.wikipedia.org/wiki/Adapter_pattern
+
+In |cubicweb| adapters provide logical functionalities to entity types.
+
+Definition of an adapter is quite trivial. An excerpt from cubicweb
+itself (found in :mod:`cubicweb.entities.adapters`):
+
+.. sourcecode:: python
+
+
+    class ITreeAdapter(EntityAdapter):
+        """This adapter has to be overriden to be configured using the
+        tree_relation, child_role and parent_role class attributes to
+        benefit from this default implementation
+        """
+        __regid__ = 'ITree'
+
+        child_role = 'subject'
+        parent_role = 'object'
+
+        def children_rql(self):
+            """returns RQL to get children """
+            return self.entity.cw_related_rql(self.tree_relation, self.parent_role)
+
+The adapter object has ``self.entity`` attribute which represents the
+entity being adapted.
+
+.. Note::
+
+   Adapters came with the notion of service identified by the registry identifier
+   of an adapters, hence dropping the need for explicit interface and the
+   :class:`cubicweb.predicates.implements` selector. You should instead use
+   :class:`cubicweb.predicates.is_instance` when you want to select on an entity
+   type, or :class:`cubicweb.predicates.adaptable` when you want to select on a
+   service.
+
+
+Specializing and binding an adapter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. sourcecode:: python
+
+  from cubicweb.entities.adapters import ITreeAdapter
+
+  class MyEntityITreeAdapter(ITreeAdapter):
+      __select__ = is_instance('MyEntity')
+      tree_relation = 'filed_under'
+
+The ITreeAdapter here provides a default implementation. The
+tree_relation class attribute is actually used by this implementation
+to help implement correct behaviour.
+
+Here we provide a specific implementation which will be bound for
+``MyEntity`` entity type (the `adaptee`).
+
+
+.. _interfaces_to_adapters:
+
+Converting code from Interfaces/Mixins to Adapters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here we go with a small example. Before:
+
+.. sourcecode:: python
+
+    from cubicweb.predicates import implements
+    from cubicweb.interfaces import ITree
+    from cubicweb.mixins import ITreeMixIn
+
+    class MyEntity(ITreeMixIn, AnyEntity):
+        __implements__ = AnyEntity.__implements__ + (ITree,)
+
+
+    class ITreeView(EntityView):
+        __select__ = implements('ITree')
+        def cell_call(self, row, col):
+            entity = self.cw_rset.get_entity(row, col)
+            children = entity.children()
+
+After:
+
+.. sourcecode:: python
+
+    from cubicweb.predicates import adaptable, is_instance
+    from cubicweb.entities.adapters import ITreeAdapter
+
+    class MyEntityITreeAdapter(ITreeAdapter):
+        __select__ = is_instance('MyEntity')
+
+    class ITreeView(EntityView):
+        __select__ = adaptable('ITree')
+        def cell_call(self, row, col):
+            entity = self.cw_rset.get_entity(row, col)
+            itree = entity.cw_adapt_to('ITree')
+            children = itree.children()
+
+As we can see, the interface/mixin duality disappears and the entity
+class itself is completely freed from these concerns. When you want
+to use the ITree interface of an entity, call its `cw_adapt_to` method
+to get an adapter for this interface, then access to members of the
+interface on the adapter
+
+Let's look at an example where we defined everything ourselves. We
+start from:
+
+.. sourcecode:: python
+
+    class IFoo(Interface):
+        def bar(self, *args):
+            raise NotImplementedError
+
+    class MyEntity(AnyEntity):
+        __regid__ = 'MyEntity'
+        __implements__ = AnyEntity.__implements__ + (IFoo,)
+
+        def bar(self, *args):
+            return sum(captain.age for captain in self.captains)
+
+    class FooView(EntityView):
+        __regid__ = 'mycube.fooview'
+        __select__ = implements('IFoo')
+
+        def cell_call(self, row, col):
+            entity = self.cw_rset.get_entity(row, col)
+            self.w('bar: %s' % entity.bar())
+
+Converting to:
+
+.. sourcecode:: python
+
+   class IFooAdapter(EntityAdapter):
+       __regid__ = 'IFoo'
+       __select__ = is_instance('MyEntity')
+
+       def bar(self, *args):
+           return sum(captain.age for captain in self.entity.captains)
+
+   class FooView(EntityView):
+        __regid__ = 'mycube.fooview'
+        __select__ = adaptable('IFoo')
+
+        def cell_call(self, row, col):
+            entity = self.cw_rset.get_entity(row, col)
+            self.w('bar: %s' % entity.cw_adapt_to('IFoo').bar())
+
+.. note::
+
+   When migrating an entity method to an adapter, the code can be moved as is
+   except for the `self` of the entity class, which in the adapter must become `self.entity`.
+
+Adapters defined in the library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. automodule:: cubicweb.entities.adapters
+   :members:
+
+More are defined in web/views.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/entityclasses/application-logic.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,177 @@
+How to use entities objects and adapters
+----------------------------------------
+
+The previous chapters detailed the classes and methods available to
+the developer at the so-called `ORM`_ level. However they say little
+about the common patterns of usage of these objects.
+
+.. _`ORM`: http://en.wikipedia.org/wiki/Object-relational_mapping
+
+Entities objects (and their adapters) are used in the repository and
+web sides of CubicWeb. On the repository side of things, one should
+manipulate them in Hooks and Operations.
+
+Hooks and Operations provide support for the implementation of rules
+such as computed attributes, coherency invariants, etc (they play the
+same role as database triggers, but in a way that is independent of
+the actual data sources).
+
+So a lot of an application's business rules will be written in Hooks
+(or Operations).
+
+On the web side, views also typically operate using entity
+objects. Obvious entity methods for use in views are the Dublin Core
+methods like ``dc_title``. For separation of concerns reasons, one
+should ensure no ui logic pervades the entities level, and also no
+business logic should creep into the views.
+
+In the duration of a transaction, entities objects can be instantiated
+many times, in views and hooks, even for the same database entity. For
+instance, in a classic CubicWeb deployment setup, the repository and
+the web front-end are separated process communicating over the
+wire. There is no way state can be shared between these processes
+(there is a specific API for that). Hence, it is not possible to use
+entity objects as messengers between these components of an
+application. It means that an attribute set as in ``obj.x = 42``,
+whether or not x is actually an entity schema attribute, has a short
+life span, limited to the hook, operation or view within which the
+object was built.
+
+Setting an attribute or relation value can be done in the context of a
+Hook/Operation, using the ``obj.cw_set(x=42)`` notation or a plain
+RQL ``SET`` expression.
+
+In views, it would be preferable to encapsulate the necessary logic in
+a method of an adapter for the concerned entity class(es). But of
+course, this advice is also reasonable for Hooks/Operations, though
+the separation of concerns here is less stringent than in the case of
+views.
+
+This leads to the practical role of objects adapters: it's where an
+important part of the application logic lies (the other part being
+located in the Hook/Operations).
+
+Anatomy of an entity class
+--------------------------
+
+We can look now at a real life example coming from the `tracker`_
+cube. Let us begin to study the ``entities/project.py`` content.
+
+.. sourcecode:: python
+
+    from cubicweb.entities.adapters import ITreeAdapter
+
+    class ProjectAdapter(ITreeAdapter):
+        __select__ = is_instance('Project')
+        tree_relation = 'subproject_of'
+
+    class Project(AnyEntity):
+        __regid__ = 'Project'
+        fetch_attrs, cw_fetch_order = fetch_config(('name', 'description',
+                                                    'description_format', 'summary'))
+
+        TICKET_DEFAULT_STATE_RESTR = 'S name IN ("created","identified","released","scheduled")'
+
+        def dc_title(self):
+            return self.name
+
+The fact that the `Project` entity type implements an ``ITree``
+interface is materialized by the ``ProjectAdapter`` class (inheriting
+the pre-defined ``ITreeAdapter`` whose ``__regid__`` is of course
+``ITree``), which will be selected on `Project` entity types because
+of its selector. On this adapter, we redefine the ``tree_relation``
+attribute of the ``ITreeAdapter`` class.
+
+This is typically used in views concerned with the representation of
+tree-like structures (CubicWeb provides several such views).
+
+It is important that the views themselves try not to implement this
+logic, not only because such views would be hardly applyable to other
+tree-like relations, but also because it is perfectly fine and useful
+to use such an interface in Hooks.
+
+In fact, Tree nature is a property of the data model that cannot be
+fully and portably expressed at the level of database entities (think
+about the transitive closure of the child relation). This is a further
+argument to implement it at entity class level.
+
+``fetch_attrs`` configures which attributes should be pre-fetched when using ORM
+methods retrieving entity of this type. In a same manner, the ``cw_fetch_order`` is
+a class method allowing to control sort order. More on this in :ref:`FetchAttrs`.
+
+We can observe the big ``TICKET_DEFAULT_STATE_RESTR`` is a pure
+application domain piece of data. There is, of course, no limitation
+to the amount of class attributes of this kind.
+
+The ``dc_title`` method provides a (unicode string) value likely to be
+consumed by views, but note that here we do not care about output
+encodings. We care about providing data in the most universal format
+possible, because the data could be used by a web view (which would be
+responsible of ensuring XHTML compliance), or a console or file
+oriented output (which would have the necessary context about the
+needed byte stream encoding).
+
+.. note::
+
+  The Dublin Core `dc_xxx` methods are not moved to an adapter as they
+  are extremely prevalent in CubicWeb and assorted cubes and should be
+  available for all entity types.
+
+Let us now dig into more substantial pieces of code, continuing the
+Project class.
+
+.. sourcecode:: python
+
+    def latest_version(self, states=('published',), reverse=None):
+        """returns the latest version(s) for the project in one of the given
+        states.
+
+        when no states specified, returns the latest published version.
+        """
+        order = 'DESC'
+        if reverse is not None:
+            warn('reverse argument is deprecated',
+                 DeprecationWarning, stacklevel=1)
+            if reverse:
+                order = 'ASC'
+        rset = self.versions_in_state(states, order, True)
+        if rset:
+            return rset.get_entity(0, 0)
+        return None
+
+    def versions_in_state(self, states, order='ASC', limit=False):
+        """returns version(s) for the project in one of the given states, sorted
+        by version number.
+
+        If limit is true, limit result to one version.
+        If reverse, versions are returned from the smallest to the greatest.
+        """
+        if limit:
+            order += ' LIMIT 1'
+        rql = 'Any V,N ORDERBY version_sort_value(N) %s ' \
+              'WHERE V num N, V in_state S, S name IN (%s), ' \
+              'V version_of P, P eid %%(p)s' % (order, ','.join(repr(s) for s in states))
+        return self._cw.execute(rql, {'p': self.eid})
+
+.. _`tracker`: http://www.cubicweb.org/project/cubicweb-tracker/
+
+These few lines exhibit the important properties we want to outline:
+
+* entity code is concerned with the application domain
+
+* it is NOT concerned with database consistency (this is the realm of
+  Hooks/Operations); in other words, it assumes a consistent world
+
+* it is NOT (directly) concerned with end-user interfaces
+
+* however it can be used in both contexts
+
+* it does not create or manipulate the internal object's state
+
+* it plays freely with RQL expression as needed
+
+* it is not concerned with internationalization
+
+* it does not raise exceptions
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/entityclasses/data-as-objects.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,142 @@
+Access to persistent data
+--------------------------
+
+Python-level access to persistent data is provided by the
+:class:`Entity <cubicweb.entity>` class.
+
+.. XXX this part is not clear. refactor it.
+
+An entity class is bound to a schema entity type. Descriptors are added when
+classes are registered in order to initialize the class according to its schema:
+
+* the attributes defined in the schema appear as attributes of these classes
+
+* the relations defined in the schema appear as attributes of these classes,
+  but are lists of instances
+
+`Formatting and output generation`:
+
+* :meth:`view(__vid, __registry='views', **kwargs)`, applies the given view to the entity
+  (and returns a unicode string)
+
+* :meth:`absolute_url(*args, **kwargs)`, returns an absolute URL including the base-url
+
+* :meth:`rest_path()`, returns a relative REST URL to get the entity
+
+* :meth:`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`:
+
+* :meth:`as_rset()`, converts the entity into an equivalent result set simulating the
+  request `Any X WHERE X eid _eid_`
+
+* :meth:`complete(skip_bytes=True)`, executes a request that recovers at
+  once all the missing attributes of an entity
+
+* :meth:`get_value(name)`, returns the value associated to the attribute name given
+  in parameter
+
+* :meth:`related(rtype, role='subject', limit=None, entities=False)`,
+  returns a list of entities related to the current entity by the
+  relation given in parameter
+
+* :meth:`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
+
+* :meth:`cw_set(**kwargs)`, updates entity's attributes and/or relation with the
+  corresponding values given named parameters. 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).
+
+* :meth:`copy_relations(ceid)`, copies the relations of the entities having the eid
+  given in the parameters on the current entity
+
+* :meth:`cw_delete()` allows to delete the entity
+
+
+The :class:`AnyEntity` class
+----------------------------
+
+To provide a specific behavior for each entity, we can define a class
+inheriting from `cubicweb.entities.AnyEntity`. In general, we define this class
+in `mycube.entities` module (or in a submodule if we want to split code among
+multiple files) so that it will be available on both server and client side.
+
+The class `AnyEntity` is a sub-class of Entity that add methods to it,
+and helps specializing (by further subclassing) the handling of a
+given entity type.
+
+Most methods defined for `AnyEntity`, in addition to `Entity`, add
+support for the `Dublin Core`_ metadata.
+
+.. _`Dublin Core`: http://dublincore.org/
+
+`Standard meta-data (Dublin Core)`:
+
+* :meth:`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)
+
+* :meth:`dc_long_title()`, same as dc_title but can return a more
+  detailed title
+
+* :meth:`dc_description(format='text/plain')`, returns a unicode string
+  corresponding to the meta-data `Description` (looks for a
+  description attribute by default)
+
+* :meth:`dc_authors()`, returns a unicode string corresponding to the meta-data
+  `Authors` (owners by default)
+
+* :meth:`dc_creator()`, returns a unicode string corresponding to the
+  creator of the entity
+
+* :meth:`dc_date(date_format=None)`, returns a unicode string corresponding to
+  the meta-data `Date` (update date by default)
+
+* :meth:`dc_type(form='')`, returns a string to display the entity type by
+  specifying the preferred form (`plural` for a plural form)
+
+* :meth:`dc_language()`, returns the language used by the entity
+
+Inheritance
+-----------
+
+When describing a data model, entities can inherit from other entities as is
+common in object-oriented programming.
+
+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, which is an
+experimental undocumented feature.
+
+
+Application logic
+-----------------
+
+While a lot of custom behaviour and application logic can be
+implemented using entity classes, the programmer must be aware that
+adding new attributes and method on an entity class adds may shadow
+schema-level attribute or relation definitions.
+
+To keep entities clean (mostly data structures plus a few universal
+methods such as listed above), one should use `adapters` (see
+:ref:`adapters`).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/entityclasses/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,13 @@
+Data as objects
+===============
+
+In this chapter, we will introduce the objects that are used to handle
+the logic associated to the data stored in the database.
+
+.. toctree::
+   :maxdepth: 1
+
+   data-as-objects
+   load-sort
+   adapters
+   application-logic
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/entityclasses/load-sort.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,40 @@
+
+.. _FetchAttrs:
+
+Loaded attributes and default sorting management
+````````````````````````````````````````````````
+
+* The class attribute `fetch_attrs` allows to define in an entity class a list of
+  names of attributes that should be automatically loaded when entities of this
+  type are fetched from the database using ORM methods retrieving entity of this
+  type (such as :meth:`related` and :meth:`unrelated`). You can also put relation
+  names in there, but we are limited to *subject relations of cardinality `?` or
+  `1`*.
+
+* The :meth:`cw_fetch_order` and :meth:`cw_fetch_unrelated_order` class methods
+  are respectively responsible to control how entities will be sorted when:
+
+  - retrieving all entities of a given type, or entities related to another
+
+  - retrieving a list of entities for use in drop-down lists enabling relations
+    creation in the editing view of an entity
+
+By default entities will be listed on their modification date descending,
+i.e. you'll get entities recently modified first. While this is usually a good
+default in drop-down list, you'll probably want to change `cw_fetch_order`.
+
+This may easily be done using the :func:`~cubicweb.entities.fetch_config`
+function, which simplifies the definition of attributes to load and sorting by
+returning a list of attributes to pre-load (considering automatically the
+attributes of `AnyEntity`) and a sorting function as described below:
+
+.. autofunction:: cubicweb.entities.fetch_config
+
+In you want something else (such as sorting on the result of a registered
+procedure), here is the prototype of those methods:
+
+
+.. automethod:: cubicweb.entity.Entity.cw_fetch_order
+
+.. automethod:: cubicweb.entity.Entity.cw_fetch_unrelated_order
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/fti.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,159 @@
+.. _fti:
+
+Full Text Indexing in CubicWeb
+------------------------------
+
+When an attribute is tagged as *fulltext-indexable* in the datamodel,
+CubicWeb will automatically trigger hooks to update the internal
+fulltext index (i.e the ``appears`` SQL table) each time this attribute
+is modified.
+
+CubicWeb also provides a ``db-rebuild-fti`` command to rebuild the whole
+fulltext on demand:
+
+.. sourcecode:: bash
+
+   cubicweb@esope~$ cubicweb db-rebuild-fti my_tracker_instance
+
+You can also rebuild the fulltext index for a given set of entity types:
+
+.. sourcecode:: bash
+
+   cubicweb@esope~$ cubicweb db-rebuild-fti my_tracker_instance Ticket Version
+
+In the above example, only fulltext index of entity types ``Ticket`` and ``Version``
+will be rebuilt.
+
+
+Standard FTI process
+~~~~~~~~~~~~~~~~~~~~
+
+Considering an entity type ``ET``, the default *fti* process is to :
+
+1. fetch all entities of type ``ET``
+
+2. for each entity, adapt it to ``IFTIndexable`` (see
+   :class:`~cubicweb.entities.adapters.IFTIndexableAdapter`)
+
+3. call
+   :meth:`~cubicweb.entities.adapters.IFTIndexableAdapter.get_words` on
+   the adapter which is supposed to return a dictionary *weight* ->
+   *list of words* as expected by
+   :meth:`~logilab.database.fti.FTIndexerMixIn.index_object`. The
+   tokenization of each attribute value is done by
+   :meth:`~logilab.database.fti.tokenize`.
+
+
+See :class:`~cubicweb.entities.adapters.IFTIndexableAdapter` for more documentation.
+
+
+Yams and ``fulltext_container``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is possible in the datamodel to indicate that fulltext-indexed
+attributes defined for an entity type will be used to index not the
+entity itself but a related entity. This is especially useful for
+composite entities. Let's take a look at (a simplified version of)
+the base schema defined in CubicWeb (see :mod:`cubicweb.schemas.base`):
+
+.. sourcecode:: python
+
+  class CWUser(WorkflowableEntityType):
+      login     = String(required=True, unique=True, maxsize=64)
+      upassword = Password(required=True)
+
+  class EmailAddress(EntityType):
+      address = String(required=True,  fulltextindexed=True,
+                       indexed=True, unique=True, maxsize=128)
+
+
+  class use_email_relation(RelationDefinition):
+      name = 'use_email'
+      subject = 'CWUser'
+      object = 'EmailAddress'
+      cardinality = '*?'
+      composite = 'subject'
+
+
+The schema above states that there is a relation between ``CWUser`` and ``EmailAddress``
+and that the ``address`` field of ``EmailAddress`` is fulltext indexed. Therefore,
+in your application, if you use fulltext search to look for an email address, CubicWeb
+will return the ``EmailAddress`` itself. But the objects we'd like to index
+are more likely to be the associated ``CWUser`` than the ``EmailAddress`` itself.
+
+The simplest way to achieve that is to tag the ``use_email`` relation in
+the datamodel:
+
+.. sourcecode:: python
+
+  class use_email(RelationType):
+      fulltext_container = 'subject'
+
+
+Customizing how entities are fetched during ``db-rebuild-fti``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``db-rebuild-fti`` will call the
+:meth:`~cubicweb.entities.AnyEntity.cw_fti_index_rql_queries` class
+method on your entity type.
+
+.. automethod:: cubicweb.entities.AnyEntity.cw_fti_index_rql_queries
+
+Now, suppose you've got a _huge_ table to index, you probably don't want to
+get all entities at once. So here's a simple customized example that will
+process block of 10000 entities:
+
+.. sourcecode:: python
+
+
+    class MyEntityClass(AnyEntity):
+        __regid__ = 'MyEntityClass'
+
+    @classmethod
+    def cw_fti_index_rql_queries(cls, req):
+        # get the default RQL method and insert LIMIT / OFFSET instructions
+        base_rql = super(SearchIndex, cls).cw_fti_index_rql_queries(req)[0]
+        selected, restrictions = base_rql.split(' WHERE ')
+        rql_template = '%s ORDERBY X LIMIT %%(limit)s OFFSET %%(offset)s WHERE %s' % (
+            selected, restrictions)
+        # count how many entities you'll have to index
+        count = req.execute('Any COUNT(X) WHERE X is MyEntityClass')[0][0]
+        # iterate by blocks of 10000 entities
+        chunksize = 10000
+        for offset in xrange(0, count, chunksize):
+            print 'SENDING', rql_template % {'limit': chunksize, 'offset': offset}
+            yield rql_template % {'limit': chunksize, 'offset': offset}
+
+Since you have access to ``req``, you can more or less fetch whatever you want.
+
+
+Customizing :meth:`~cubicweb.entities.adapters.IFTIndexableAdapter.get_words`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can also customize the FTI process by providing your own ``get_words()``
+implementation:
+
+.. sourcecode:: python
+
+    from cubicweb.entities.adapters import IFTIndexableAdapter
+
+    class SearchIndexAdapter(IFTIndexableAdapter):
+        __regid__ = 'IFTIndexable'
+        __select__ = is_instance('MyEntityClass')
+
+        def fti_containers(self, _done=None):
+            """this should yield any entity that must be considered to
+            fulltext-index self.entity
+
+            CubicWeb's default implementation will look for yams'
+            ``fulltex_container`` property.
+            """
+            yield self.entity
+            yield self.entity.some_related_entity
+
+
+        def get_words(self):
+            # implement any logic here
+            # see http://www.postgresql.org/docs/9.1/static/textsearch-controls.html
+            # for the actual signification of 'C'
+            return {'C': ['any', 'word', 'I', 'want']}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,25 @@
+.. _Part2:
+
+----------------------
+Repository development
+----------------------
+
+This part is about developing applications with the *CubicWeb*
+framework. It is not concerned with the web system, which is a
+separate layer and has its own whole chapter.
+
+.. toctree::
+   :maxdepth: 2
+   :numbered:
+
+   cubes/index
+   vreg.rst
+   datamodel/index
+   entityclasses/index
+   devcore/index
+   repo/index
+   testing.rst
+   migration.rst
+   profiling.rst
+   fti.rst
+   dataimport
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/migration.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,250 @@
+.. -*- coding: utf-8 -*-
+
+.. _migration:
+
+Migration
+=========
+
+One of the main design goals of *CubicWeb* was to support iterative and agile
+development. For this purpose, multiple actions are provided to facilitate the
+improvement of an instance, and in particular to handle the changes to be
+applied to the data model, without loosing existing data.
+
+The current version of a cube (and of cubicweb itself) is provided in the file
+`__pkginfo__.py` as a tuple of 3 integers.
+
+Migration scripts management
+----------------------------
+
+Migration scripts has to be located in the directory `migration` of your
+cube and named accordingly:
+
+::
+
+  <version n° X.Y.Z>[_<description>]_<mode>.py
+
+in which :
+
+* X.Y.Z is the model version number to which the script enables to migrate.
+
+* *mode* (between the last "_" and the extension ".py") is used for
+  distributed installation. It indicates to which part
+  of the application (RQL server, web server) the script applies.
+  Its value could be :
+
+  * `common`, applies to the RQL server as well as the web server and updates
+    files on the hard drive (configuration files migration for example).
+
+  * `web`, applies only to the web server and updates files on the hard drive.
+
+  * `repository`, applies only to the RQL server and updates files on the
+    hard drive.
+
+  * `Any`, applies only to the RQL server and updates data in the database
+    (schema and data migration for example).
+
+Again in the directory `migration`, the file `depends.map` allows to indicate
+that for the migration to a particular model version, you always have to first
+migrate to a particular *CubicWeb* version. This file can contain comments (lines
+starting with `#`) and a dependency is listed as follows: ::
+
+  <model version n° X.Y.Z> : <cubicweb version n° X.Y.Z>
+
+For example: ::
+
+  0.12.0: 2.26.0
+  0.13.0: 2.27.0
+  # 0.14 works with 2.27 <= cubicweb <= 2.28 at least
+  0.15.0: 2.28.0
+
+Base context
+------------
+
+The following identifiers are pre-defined in migration scripts:
+
+* `config`, instance configuration
+
+* `interactive_mode`, boolean indicating that the script is executed in
+  an interactive mode or not
+
+* `versions_map`, dictionary of migrated versions  (key are cubes
+  names, including 'cubicweb', values are (from version, to version)
+
+* `confirm(question)`, function asking the user and returning true
+  if the user answers yes, false otherwise (always returns true in
+  non-interactive mode)
+
+* `_()` is equivalent to `unicode` allowing to flag the strings to
+  internationalize in the migration scripts.
+
+In the `repository` scripts, the following identifiers are also defined:
+
+* `commit(ask_confirm=True)`, request confirming and executing a "commit"
+
+* `schema`, instance schema (readen from the database)
+
+* `fsschema`, installed schema on the file system (e.g. schema of
+  the updated model and cubicweb)
+
+* `repo`, repository object
+
+* `session`, repository session object
+
+
+New cube dependencies
+---------------------
+
+If your code depends on some new cubes, you have to add them in a migration
+script by using:
+
+* `add_cube(cube, update_database=True)`, add a cube.
+* `add_cubes(cubes, update_database=True)`, add a list of cubes.
+
+The `update_database` parameter is telling if the database schema
+should be updated or if only the relevant persistent property should be
+inserted (for the case where a new cube has been extracted from an
+existing one, so the new cube schema is actually already in there).
+
+If some of the added cubes are already used by an instance, they'll simply be
+silently skipped.
+
+
+Schema migration
+----------------
+The following functions for schema migration are available in `repository`
+scripts:
+
+* `add_attribute(etype, attrname, attrtype=None, commit=True)`, adds a new
+  attribute to an existing entity type. If the attribute type is not specified,
+  then it is extracted from the updated schema.
+
+* `drop_attribute(etype, attrname, commit=True)`, removes an attribute from an
+  existing entity type.
+
+* `rename_attribute(etype, oldname, newname, commit=True)`, renames an attribute
+
+* `add_entity_type(etype, auto=True, commit=True)`, adds a new entity type.
+  If `auto` is True, all the relations using this entity type and having a known
+  entity type on the other hand will automatically be added.
+
+* `drop_entity_type(etype, commit=True)`, removes an entity type and all the
+  relations using it.
+
+* `rename_entity_type(oldname, newname, commit=True)`, renames an entity type
+
+* `add_relation_type(rtype, addrdef=True, commit=True)`, adds a new relation
+  type. If `addrdef` is True, all the relations definitions of this type will
+  be added.
+
+* `drop_relation_type(rtype, commit=True)`, removes a relation type and all the
+  definitions of this type.
+
+* `rename_relation_type(oldname, newname, commit=True)`, renames a relation type.
+
+* `add_relation_definition(subjtype, rtype, objtype, commit=True)`, adds a new
+  relation definition.
+
+* `drop_relation_definition(subjtype, rtype, objtype, commit=True)`, removes
+  a relation definition.
+
+* `sync_schema_props_perms(ertype=None, syncperms=True, syncprops=True, syncrdefs=True, commit=True)`,
+  synchronizes properties and/or permissions on:
+  - the whole schema if ertype is None
+  - an entity or relation type schema if ertype is a string
+  - a relation definition  if ertype is a 3-uple (subject, relation, object)
+
+* `change_relation_props(subjtype, rtype, objtype, commit=True, **kwargs)`, changes
+  properties of a relation definition by using the named parameters of the properties
+  to change.
+
+* `set_widget(etype, rtype, widget, commit=True)`, changes the widget used for the
+  relation <rtype> of entity type <etype>.
+
+* `set_size_constraint(etype, rtype, size, commit=True)`, changes the size constraints
+  for the relation <rtype> of entity type <etype>.
+
+Data migration
+--------------
+The following functions for data migration are available in `repository` scripts:
+
+* `rql(rql, kwargs=None, cachekey=None, ask_confirm=True)`, executes an arbitrary RQL
+  query, either to interrogate or update. A result set object is returned.
+
+* `add_entity(etype, *args, **kwargs)`, adds a new entity of the given type.
+  The attribute and relation values are specified as named positional
+  arguments.
+
+Workflow creation
+-----------------
+
+The following functions for workflow creation are available in `repository`
+scripts:
+
+* `add_workflow(label, workflowof, initial=False, commit=False, **kwargs)`, adds a new workflow
+  for a given type(s)
+
+You can find more details about workflows in the chapter :ref:`Workflow` .
+
+Configuration migration
+-----------------------
+
+The following functions for configuration migration are available in all
+scripts:
+
+* `option_renamed(oldname, newname)`, indicates that an option has been renamed
+
+* `option_group_change(option, oldgroup, newgroup)`, indicates that an option does not
+  belong anymore to the same group.
+
+* `option_added(oldname, newname)`, indicates that an option has been added.
+
+* `option_removed(oldname, newname)`, indicates that an option has been deleted.
+
+The `config` variable is an object which can be used to access the
+configuration values, for reading and updating, with a dictionary-like
+syntax. 
+
+Example 1: migration script changing the variable 'sender-addr' in
+all-in-one.conf. The script also checks that in that the instance is
+configured with a known value for that variable, and only updates the
+value in that case.
+
+.. sourcecode:: python
+
+ wrong_addr = 'cubicweb@loiglab.fr' # known wrong address
+ fixed_addr = 'cubicweb@logilab.fr'
+ configured_addr = config.get('sender-addr')
+ # check that the address has not been hand fixed by a sysadmin
+ if configured_addr == wrong_addr: 
+     config['sender-addr'] = fixed-addr
+     config.save()
+
+Example 2: checking the value of the database backend driver, which
+can be useful in case you need to issue backend-dependent raw SQL
+queries in a migration script.
+
+.. sourcecode:: python
+
+ dbdriver  = config.sources()['system']['db-driver']
+ if dbdriver == "sqlserver2005":
+     # this is now correctly handled by CW :-)
+     sql('ALTER TABLE cw_Xxxx ALTER COLUMN cw_name varchar(64) NOT NULL;')
+     commit()
+ else: # postgresql
+     sync_schema_props_perms(ertype=('Xxxx', 'name', 'String'),
+     syncperms=False)
+
+
+Others migration functions
+--------------------------
+Those functions are only used for low level operations that could not be
+accomplished otherwise or to repair damaged databases during interactive
+session. They are available in `repository` scripts:
+
+* `sql(sql, args=None, ask_confirm=True)`, executes an arbitrary SQL query on the system source
+* `add_entity_type_table(etype, commit=True)`
+* `add_relation_type_table(rtype, commit=True)`
+* `uninline_relation(rtype, commit=True)`
+
+
+[FIXME] Add explanation on how to use cubicweb-ctl shell
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/profiling.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,57 @@
+.. _PROFILING:
+
+Profiling and performance
+=========================
+
+If you feel that one of your pages takes more time than it should to be
+generated, chances are that you're making too many RQL queries.  Obviously,
+there are other reasons but experience tends to show this is the first thing to
+track down. Luckily, CubicWeb provides a configuration option to log RQL
+queries. In your ``all-in-one.conf`` file, set the **query-log-file** option::
+
+    # web application query log file
+    query-log-file=/home/user/myapp-rql.log
+
+Then restart your application, reload your page and stop your application.
+The file ``myapp-rql.log`` now contains the list of RQL queries that were
+executed during your test. It's a simple text file containing lines such as::
+
+    Any A WHERE X eid %(x)s, X lastname A {'x': 448} -- (0.002 sec, 0.010 CPU sec)
+    Any A WHERE X eid %(x)s, X firstname A {'x': 447} -- (0.002 sec, 0.000 CPU sec)
+
+The structure of each line is::
+
+    <RQL QUERY> <QUERY ARGS IF ANY> -- <TIME SPENT>
+
+CubicWeb also provides the **exlog** command to examine and summarize data found
+in such a file:
+
+.. sourcecode:: sh
+
+    $ cubicweb-ctl exlog /home/user/myapp-rql.log
+    0.07 50 Any A WHERE X eid %(x)s, X firstname A {}
+    0.05 50 Any A WHERE X eid %(x)s, X lastname A {}
+    0.01 1 Any X,AA ORDERBY AA DESC WHERE E eid %(x)s, E employees X, X modification_date AA {}
+    0.01 1 Any X WHERE X eid %(x)s, X owned_by U, U eid %(u)s {, }
+    0.01 1 Any B,T,P ORDERBY lower(T) WHERE B is Bookmark,B title T, B path P, B bookmarked_by U, U eid %(x)s {}
+    0.01 1 Any A,B,C,D WHERE A eid %(x)s,A name B,A creation_date C,A modification_date D {}
+
+This command sorts and uniquifies queries so that it's easy to see where
+is the hot spot that needs optimization.
+
+Do not neglect to set the **fetch_attrs** attribute you can define in your
+entity classes because it can greatly reduce the number of queries executed (see
+:ref:`FetchAttrs`).
+
+You should also know about the **profile** option in the ``all-in-on.conf``. If
+set, this option will make your application run in an `hotshot`_ session and
+store the results in the specified file.
+
+.. _hotshot: http://docs.python.org/library/hotshot.html#module-hotshot
+
+Last but no least, if you're using the PostgreSQL database backend, VACUUMing
+your database can significantly improve the performance of the queries (by
+updating the statistics used by the query optimizer). Nowadays, this is done
+automatically from time to time, but if you've just imported a large amount of
+data in your db, you will want to vacuum it (with the analyse option on). Read
+the documentation of your database for more information.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/repo/hooks.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,279 @@
+.. -*- coding: utf-8 -*-
+.. _hooks:
+
+Hooks and Operations
+====================
+
+.. autodocstring:: cubicweb.server.hook
+
+
+Example using dataflow hooks
+----------------------------
+
+We will use a very simple example to show hooks usage. Let us start with the
+following schema.
+
+.. sourcecode:: python
+
+   class Person(EntityType):
+       age = Int(required=True)
+
+We would like to add a range constraint over a person's age. Let's write an hook
+(supposing yams can not handle this nativly, which is wrong). It shall be placed
+into `mycube/hooks.py`. If this file were to grow too much, we can easily have a
+`mycube/hooks/... package` containing hooks in various modules.
+
+.. sourcecode:: python
+
+   from cubicweb import ValidationError
+   from cubicweb.predicates import is_instance
+   from cubicweb.server.hook import Hook
+
+   class PersonAgeRange(Hook):
+        __regid__ = 'person_age_range'
+        __select__ = Hook.__select__ & is_instance('Person')
+        events = ('before_add_entity', 'before_update_entity')
+
+        def __call__(self):
+	    if 'age' in self.entity.cw_edited:
+                if 0 <= self.entity.age <= 120:
+                   return
+		msg = self._cw._('age must be between 0 and 120')
+		raise ValidationError(self.entity.eid, {'age': msg})
+
+In our example the base `__select__` is augmented with an `is_instance` selector
+matching the desired entity type.
+
+The `events` tuple is used specify that our hook should be called before the
+entity is added or updated.
+
+Then in the hook's `__call__` method, we:
+
+* check if the 'age' attribute is edited
+* if so, check the value is in the range
+* if not, raise a validation error properly
+
+Now Let's augment our schema with new `Company` entity type with some relation to
+`Person` (in 'mycube/schema.py').
+
+.. sourcecode:: python
+
+   class Company(EntityType):
+        name = String(required=True)
+        boss = SubjectRelation('Person', cardinality='1*')
+        subsidiary_of = SubjectRelation('Company', cardinality='*?')
+
+
+We would like to constrain the company's bosses to have a minimum (legal)
+age. Let's write an hook for this, which will be fired when the `boss` relation
+is established (still supposing we could not specify that kind of thing in the
+schema).
+
+.. sourcecode:: python
+
+   class CompanyBossLegalAge(Hook):
+        __regid__ = 'company_boss_legal_age'
+        __select__ = Hook.__select__ & match_rtype('boss')
+        events = ('before_add_relation',)
+
+        def __call__(self):
+            boss = self._cw.entity_from_eid(self.eidto)
+            if boss.age < 18:
+                msg = self._cw._('the minimum age for a boss is 18')
+                raise ValidationError(self.eidfrom, {'boss': msg})
+
+.. Note::
+
+    We use the :class:`~cubicweb.server.hook.match_rtype` selector to select the
+    proper relation type.
+
+    The essential difference with respect to an entity hook is that there is no
+    self.entity, but `self.eidfrom` and `self.eidto` hook attributes which
+    represent the subject and object **eid** of the relation.
+
+Suppose we want to check that there is no cycle by the `subsidiary_of`
+relation. This is best achieved in an operation since all relations are likely to
+be set at commit time.
+
+.. sourcecode:: python
+
+    from cubicweb.server.hook import Hook, DataOperationMixIn, Operation, match_rtype
+
+    def check_cycle(self, session, eid, rtype, role='subject'):
+        parents = set([eid])
+        parent = session.entity_from_eid(eid)
+        while parent.related(rtype, role):
+            parent = parent.related(rtype, role)[0]
+            if parent.eid in parents:
+                msg = session._('detected %s cycle' % rtype)
+                raise ValidationError(eid, {rtype: msg})
+            parents.add(parent.eid)
+
+
+    class CheckSubsidiaryCycleOp(Operation):
+
+        def precommit_event(self):
+            check_cycle(self.session, self.eidto, 'subsidiary_of')
+
+
+    class CheckSubsidiaryCycleHook(Hook):
+        __regid__ = 'check_no_subsidiary_cycle'
+        __select__ = Hook.__select__ & match_rtype('subsidiary_of')
+        events = ('after_add_relation',)
+
+        def __call__(self):
+            CheckSubsidiaryCycleOp(self._cw, eidto=self.eidto)
+
+
+Like in hooks, :exc:`~cubicweb.ValidationError` can be raised in operations. Other
+exceptions are usually programming errors.
+
+In the above example, our hook will instantiate an operation each time the hook
+is called, i.e. each time the `subsidiary_of` relation is set. There is an
+alternative method to schedule an operation from a hook, using the
+:func:`get_instance` class method.
+
+.. sourcecode:: python
+
+   from cubicweb.server.hook import set_operation
+
+   class CheckSubsidiaryCycleHook(Hook):
+       __regid__ = 'check_no_subsidiary_cycle'
+       events = ('after_add_relation',)
+       __select__ = Hook.__select__ & match_rtype('subsidiary_of')
+
+       def __call__(self):
+           CheckSubsidiaryCycleOp.get_instance(self._cw).add_data(self.eidto)
+
+   class CheckSubsidiaryCycleOp(DataOperationMixIn, Operation):
+
+       def precommit_event(self):
+           for eid in self.get_data():
+               check_cycle(self.session, eid, self.rtype)
+
+
+Here, we call :func:`set_operation` so that we will simply accumulate eids of
+entities to check at the end in a single `CheckSubsidiaryCycleOp`
+operation. Value are stored in a set associated to the
+'subsidiary_cycle_detection' transaction data key. The set initialization and
+operation creation are handled nicely by :func:`set_operation`.
+
+A more realistic example can be found in the advanced tutorial chapter
+:ref:`adv_tuto_security_propagation`.
+
+
+Inter-instance communication
+----------------------------
+
+If your application consists of several instances, you may need some means to
+communicate between them.  Cubicweb provides a publish/subscribe mechanism
+using ØMQ_.  In order to use it, use
+:meth:`~cubicweb.server.cwzmq.ZMQComm.add_subscription` on the
+`repo.app_instances_bus` object.  The `callback` will get the message (as a
+list).  A message can be sent by calling
+:meth:`~cubicweb.server.cwzmq.ZMQComm.publish` on `repo.app_instances_bus`.
+The first element of the message is the topic which is used for filtering and
+dispatching messages.
+
+.. _ØMQ: http://www.zeromq.org/
+
+.. sourcecode:: python
+
+  class FooHook(hook.Hook):
+      events = ('server_startup',)
+      __regid__ = 'foo_startup'
+
+      def __call__(self):
+          def callback(msg):
+              self.info('received message: %s', ' '.join(msg))
+          self.repo.app_instances_bus.add_subscription('hello', callback)
+
+.. sourcecode:: python
+
+  def do_foo(self):
+      actually_do_foo()
+      self._cw.repo.app_instances_bus.publish(['hello', 'world'])
+
+The `zmq-address-pub` configuration variable contains the address used
+by the instance for sending messages, e.g. `tcp://*:1234`.  The
+`zmq-address-sub` variable contains a comma-separated list of addresses
+to listen on, e.g. `tcp://localhost:1234, tcp://192.168.1.1:2345`.
+
+
+Hooks writing tips
+------------------
+
+Reminder
+~~~~~~~~
+
+You should never use the `entity.foo = 42` notation to update an entity. It will
+not do what you expect (updating the database). Instead, use the
+:meth:`~cubicweb.entity.Entity.cw_set` method or direct access to entity's
+:attr:`cw_edited` attribute if you're writing a hook for 'before_add_entity' or
+'before_update_entity' event.
+
+
+How to choose between a before and an after event ?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`before_*` hooks give you access to the old attribute (or relation)
+values. You can also intercept and update edited values in the case of
+entity modification before they reach the database.
+
+Else the question is: should I need to do things before or after the actual
+modification ? If the answer is "it doesn't matter", use an 'after' event.
+
+
+Validation Errors
+~~~~~~~~~~~~~~~~~
+
+When a hook which is responsible to maintain the consistency of the
+data model detects an error, it must use a specific exception named
+:exc:`~cubicweb.ValidationError`. Raising anything but a (subclass of)
+:exc:`~cubicweb.ValidationError` is a programming error. Raising it
+entails aborting the current transaction.
+
+This exception is used to convey enough information up to the user
+interface. Hence its constructor is different from the default Exception
+constructor. It accepts, positionally:
+
+* an entity eid (**not the entity itself**),
+
+* a dict whose keys represent attribute (or relation) names and values
+  an end-user facing message (hence properly translated) relating the
+  problem.
+
+.. sourcecode:: python
+
+  raise ValidationError(earth.eid, {'sea_level': self._cw._('too high'),
+                                    'temperature': self._cw._('too hot')})
+
+
+Checking for object created/deleted in the current transaction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In hooks, you can use the
+:meth:`~cubicweb.server.session.Session.added_in_transaction` or
+:meth:`~cubicweb.server.session.Session.deleted_in_transaction` of the session
+object to check if an eid has been created or deleted during the hook's
+transaction.
+
+This is useful to enable or disable some stuff if some entity is being added or
+deleted.
+
+.. sourcecode:: python
+
+   if self._cw.deleted_in_transaction(self.eidto):
+      return
+
+
+Peculiarities of inlined relations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Relations which are defined in the schema as `inlined` (see :ref:`RelationType`
+for details) are inserted in the database at the same time as entity attributes.
+
+This may have some side effect, for instance when creating an entity
+and setting an inlined relation in the same rql query, then at
+`before_add_relation` time, the relation will already exist in the
+database (it is otherwise not the case).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/repo/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,13 @@
+.. -*- coding: utf-8 -*-
+
+Repository customization
+++++++++++++++++++++++++
+.. toctree::
+   :maxdepth: 1
+
+   sessions
+   hooks
+   notifications
+   tasks
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/repo/notifications.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,29 @@
+.. -*- coding: utf-8 -*-
+
+Notifications management
+========================
+
+CubicWeb provides a machinery to ease notifications handling. To use it for a
+notification:
+
+* write a view inheriting from
+  :class:`~cubicweb.sobjects.notification.NotificationView`.  The usual view api
+  is used to generated the email (plain text) content, and additional
+  :meth:`~cubicweb.sobjects.notification.NotificationView.subject` and
+  :meth:`~cubicweb.sobjects.notification.NotificationView.recipients` methods
+  are used to build the email's subject and
+  recipients. :class:`NotificationView` provides default implementation for both
+  methods.
+
+* write a hook for event that should trigger this notification, select the view
+  (without rendering it), and give it to
+  :func:`cubicweb.hooks.notification.notify_on_commit` so that the notification
+  will be sent if the transaction succeed.
+
+
+.. XXX explain recipient finder and provide example
+
+API details
+~~~~~~~~~~~
+.. autoclass:: cubicweb.sobjects.notification.NotificationView
+.. autofunction:: cubicweb.hooks.notification.notify_on_commit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/repo/sessions.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,318 @@
+.. -*- coding: utf-8 -*-
+
+Sessions
+========
+
+Sessions are objects linked to an authenticated user.  The `Session.new_cnx`
+method returns a new Connection linked to that session.
+
+Connections
+===========
+
+Connections provide the `.execute` method to query the data sources, along with
+`.commit` and `.rollback` methods for transaction management.
+
+Kinds of connections
+--------------------
+
+There are two kinds of connections.
+
+* `normal connections` are the most common: they are related to users and
+  carry security checks coming with user credentials
+
+* `internal connections` have all the powers; they are also used in only a
+  few situations where you don't already have an adequate session at
+  hand, like: user authentication, data synchronisation in
+  multi-source contexts
+
+Normal connections are typically named `_cw` in most appobjects or
+sometimes just `session`.
+
+Internal connections are available from the `Repository` object and are
+to be used like this:
+
+.. sourcecode:: python
+
+   with self.repo.internal_cnx() as cnx:
+       do_stuff_with(cnx)
+       cnx.commit()
+
+Connections should always be used as context managers, to avoid leaks.
+
+
+Python/RQL API
+~~~~~~~~~~~~~~
+
+The Python API developped to interface with RQL is inspired from the standard db-api,
+but since `execute` returns its results directly, there is no `cursor` concept.
+
+.. sourcecode:: python
+
+   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
+
+The `Connection` object owns the methods `commit` and `rollback`. You
+*should never need to use them* during the development of the web
+interface based on the *CubicWeb* framework as it determines the end
+of the transaction depending on the query execution success. They are
+however useful in other contexts such as tests or custom controllers.
+
+.. note::
+
+  If a query generates an error related to security (:exc:`Unauthorized`) or to
+  integrity (:exc:`ValidationError`), the transaction can still continue but you
+  won't be able to commit it, a rollback will be necessary to start a new
+  transaction.
+
+  Also, a rollback is automatically done if an error occurs during commit.
+
+.. note::
+
+   A :exc:`ValidationError` has a `entity` attribute. In CubicWeb,
+   this atttribute is set to the entity's eid (not a reference to the
+   entity itself).
+
+Executing RQL queries from a view or a hook
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When you're within code of the web interface, the Connection is 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 request object (since
+you're directly inside the data-server), so you'll have to use the execute method
+of the Connection object.
+
+Proper usage of `.execute`
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Let's say you want to get T which is in configuration C, this translates to:
+
+.. sourcecode:: python
+
+   self._cw.execute('Any T WHERE T in_conf C, C eid %s' % entity.eid)
+
+But it must be written in a syntax that will benefit from the use
+of a cache on the RQL server side:
+
+.. sourcecode:: python
+
+   self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid})
+
+The syntax tree is built once for the "generic" RQL and can be re-used
+with a number of different eids.  The rql IN operator is an exception
+to this rule.
+
+.. sourcecode:: python
+
+   self._cw.execute('Any T WHERE T in_conf C, C name IN (%s)'
+                    % ','.join(['foo', 'bar']))
+
+Alternatively, some of the common data related to an entity can be
+obtained from the `entity.related()` method (which is used under the
+hood by the ORM when you use attribute access notation on an entity to
+get a relation. The initial request would then be translated to:
+
+.. sourcecode:: python
+
+   entity.related('in_conf', 'object')
+
+Additionally this benefits from the fetch_attrs policy (see :ref:`FetchAttrs`)
+optionally defined on the class element, which says which attributes must be
+also loaded when the entity is loaded through the ORM.
+
+.. _resultset:
+
+The `ResultSet` API
+~~~~~~~~~~~~~~~~~~~
+
+ResultSet instances are a very commonly manipulated object. They have
+a rich API as seen below, but we would like to highlight a bunch of
+methods that are quite useful in day-to-day practice:
+
+* `__str__()` (applied by `print`) gives a very useful overview of both
+  the underlying RQL expression and the data inside; unavoidable for
+  debugging purposes
+
+* `printable_rql()` returns a well formed RQL expression as a
+  string; it is very useful to build views
+
+* `entities()` returns a generator on all entities of the result set
+
+* `get_entity(row, col)` gets the entity at row, col coordinates; one
+  of the most used result set methods
+
+.. autoclass:: cubicweb.rset.ResultSet
+   :members:
+
+
+Authentication and management of sessions
+-----------------------------------------
+
+The authentication process is a ballet involving a few dancers:
+
+* through its `get_session` method the top-level application object (the
+  `CubicWebPublisher`) will open a session whenever a web request
+  comes in; it asks the `session manager` to open a session (giving
+  the web request object as context) using `open_session`
+
+  * the session manager asks its authentication manager (which is a
+    `component`) to authenticate the request (using `authenticate`)
+
+    * the authentication manager asks, in order, to its authentication
+      information retrievers, a login and an opaque object containing
+      other credentials elements (calling `authentication_information`),
+      giving the request object each time
+
+      * the default retriever (named `LoginPasswordRetriever`)
+        will in turn defer login and password fetching to the request
+        object (which, depending on the authentication mode (`cookie`
+        or `http`), will do the appropriate things and return a login
+        and a password)
+
+    * the authentication manager, on success, asks the `Repository`
+      object to connect with the found credentials (using `connect`)
+
+      * the repository object asks authentication to all of its
+        sources which support the `CWUser` entity with the given
+        credentials; when successful it can build the cwuser entity,
+        from which a regular `Session` object is made; it returns the
+        session id
+
+        * the source in turn will delegate work to an authentifier
+          class that defines the ultimate `authenticate` method (for
+          instance the native source will query the database against
+          the provided credentials)
+
+    * the authentication manager, on success, will call back _all_
+      retrievers with `authenticated` and return its authentication
+      data (on failure, it will try the anonymous login or, if the
+      configuration forbids it, raise an `AuthenticationError`)
+
+Writing authentication plugins
+------------------------------
+
+Sometimes CubicWeb's out-of-the-box authentication schemes (cookie and
+http) are not sufficient. Nowadays there is a plethora of such schemes
+and the framework cannot provide them all, but as the sequence above
+shows, it is extensible.
+
+Two levels have to be considered when writing an authentication
+plugin: the web client and the repository.
+
+We invented a scenario where it makes sense to have a new plugin in
+each side: some middleware will do pre-authentication and under the
+right circumstances add a new HTTP `x-foo-user` header to the query
+before it reaches the CubicWeb instance. For a concrete example of
+this, see the `trustedauth`_ cube.
+
+.. _`trustedauth`: http://www.cubicweb.org/project/cubicweb-trustedauth
+
+Repository authentication plugins
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On the repository side, it is possible to register a source
+authentifier using the following kind of code:
+
+.. sourcecode:: python
+
+ from cubicweb.server.sources import native
+
+ class FooAuthentifier(native.LoginPasswordAuthentifier):
+     """ a source authentifier plugin
+     if 'foo' in authentication information, no need to check
+     password
+     """
+     auth_rql = 'Any X WHERE X is CWUser, X login %(login)s'
+
+     def authenticate(self, session, login, **kwargs):
+         """return CWUser eid for the given login
+         if this account is defined in this source,
+         else raise `AuthenticationError`
+         """
+         session.debug('authentication by %s', self.__class__.__name__)
+         if 'foo' not in kwargs:
+             return super(FooAuthentifier, self).authenticate(session, login, **kwargs)
+         try:
+             rset = session.execute(self.auth_rql, {'login': login})
+             return rset[0][0]
+         except Exception, exc:
+             session.debug('authentication failure (%s)', exc)
+         raise AuthenticationError('foo user is unknown to us')
+
+Since repository authentifiers are not appobjects, we have to register
+them through a `server_startup` hook.
+
+.. sourcecode:: python
+
+ class ServerStartupHook(hook.Hook):
+     """ register the foo authenticator """
+     __regid__ = 'fooauthenticatorregisterer'
+     events = ('server_startup',)
+
+     def __call__(self):
+         self.debug('registering foo authentifier')
+         self.repo.system_source.add_authentifier(FooAuthentifier())
+
+Web authentication plugins
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. sourcecode:: python
+
+ class XFooUserRetriever(authentication.LoginPasswordRetriever):
+     """ authenticate by the x-foo-user http header
+     or just do normal login/password authentication
+     """
+     __regid__ = 'x-foo-user'
+     order = 0
+
+     def authentication_information(self, req):
+         """retrieve authentication information from the given request, raise
+         NoAuthInfo if expected information is not found
+         """
+         self.debug('web authenticator building auth info')
+         try:
+            login = req.get_header('x-foo-user')
+            if login:
+                return login, {'foo': True}
+            else:
+                return super(XFooUserRetriever, self).authentication_information(self, req)
+         except Exception, exc:
+            self.debug('web authenticator failed (%s)', exc)
+         raise authentication.NoAuthInfo()
+
+     def authenticated(self, retriever, req, cnx, login, authinfo):
+         """callback when return authentication information have opened a
+         repository connection successfully. Take care req has no session
+         attached yet, hence req.execute isn't available.
+
+         Here we set a flag on the request to indicate that the user is
+         foo-authenticated. Can be used by a selector
+         """
+         self.debug('web authenticator running post authentication callback')
+         cnx.foo_user = authinfo.get('foo')
+
+In the `authenticated` method we add (in an admitedly slightly hackish
+way) an attribute to the connection object. This, in turn, can be used
+to build a selector dispatching on the fact that the user was
+preauthenticated or not.
+
+.. sourcecode:: python
+
+ @objectify_selector
+ def foo_authenticated(cls, req, rset=None, **kwargs):
+     if hasattr(req.cnx, 'foo_user') and req.foo_user:
+         return 1
+     return 0
+
+Full Session and Connection API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. autoclass:: cubicweb.server.session.Session
+.. autoclass:: cubicweb.server.session.Connection
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/repo/tasks.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,9 @@
+.. -*- coding: utf-8 -*-
+
+Tasks
+=========
+
+[WRITE ME]
+
+* repository tasks
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/testing.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,559 @@
+.. -*- coding: utf-8 -*-
+
+Tests
+=====
+
+Unit tests
+----------
+
+The *CubicWeb* framework provides the
+:class:`cubicweb.devtools.testlib.CubicWebTC` test base class .
+
+Tests shall be put into the mycube/test directory. Additional test
+data shall go into mycube/test/data.
+
+It is much advised to write tests concerning entities methods,
+actions, hooks and operations, security. The
+:class:`~cubicweb.devtools.testlib.CubicWebTC` base class has
+convenience methods to help test all of this.
+
+In the realm of views, automatic tests check that views are valid
+XHTML. See :ref:`automatic_views_tests` for details.
+
+Most unit tests need a live database to work against. This is achieved
+by CubicWeb using automatically sqlite (bundled with Python, see
+http://docs.python.org/library/sqlite3.html) as a backend.
+
+The database is stored in the mycube/test/tmpdb,
+mycube/test/tmpdb-template files. If it does not (yet) exist, it will
+be built automatically when the test suite starts.
+
+.. warning::
+
+  Whenever the schema changes (new entities, attributes, relations)
+  one must delete these two files. Changes concerned only with entity
+  or relation type properties (constraints, cardinalities,
+  permissions) and generally dealt with using the
+  `sync_schema_props_perms()` function of the migration environment do
+  not need a database regeneration step.
+
+.. _hook_test:
+
+Unit test by example
+````````````````````
+
+We start with an example extracted from the keyword cube (available
+from http://www.cubicweb.org/project/cubicweb-keyword).
+
+.. sourcecode:: python
+
+    from cubicweb.devtools.testlib import CubicWebTC
+    from cubicweb import ValidationError
+
+    class ClassificationHooksTC(CubicWebTC):
+
+        def setup_database(self):
+            with self.admin_access.repo_cnx() as cnx:
+                group_etype = cnx.find('CWEType', name='CWGroup').one()
+                c1 = cnx.create_entity('Classification', name=u'classif1',
+                                       classifies=group_etype)
+                user_etype = cnx.find('CWEType', name='CWUser').one()
+                c2 = cnx.create_entity('Classification', name=u'classif2',
+                                       classifies=user_etype)
+                self.kw1eid = cnx.create_entity('Keyword', name=u'kwgroup', included_in=c1).eid
+                cnx.commit()
+
+        def test_cannot_create_cycles(self):
+            with self.admin_access.repo_cnx() as cnx:
+                kw1 = cnx.entity_from_eid(self.kw1eid)
+                # direct obvious cycle
+                with self.assertRaises(ValidationError):
+                    kw1.cw_set(subkeyword_of=kw1)
+                cnx.rollback()
+                # testing indirect cycles
+                kw3 = cnx.execute('INSERT Keyword SK: SK name "kwgroup2", SK included_in C, '
+                                  'SK subkeyword_of K WHERE C name "classif1", K eid %(k)s'
+                                  {'k': kw1}).get_entity(0,0)
+                kw3.cw_set(reverse_subkeyword_of=kw1)
+                self.assertRaises(ValidationError, cnx.commit)
+
+The test class defines a :meth:`setup_database` method which populates the
+database with initial data. Each test of the class runs with this
+pre-populated database.
+
+The test case itself checks that an Operation does its job of
+preventing cycles amongst Keyword entities.
+
+The `create_entity` method of connection (or request) objects allows
+to create an entity. You can link this entity to other entities, by
+specifying as argument, the relation name, and the entity to link, as
+value. In the above example, the `Classification` entity is linked to
+a `CWEtype` via the relation `classifies`. Conversely, if you are
+creating a `CWEtype` entity, you can link it to a `Classification`
+entity, by adding `reverse_classifies` as argument.
+
+.. note::
+
+   the :meth:`commit` method is not called automatically. You have to
+   call it explicitly if needed (notably to test operations). It is a
+   good practice to regenerate entities with :meth:`entity_from_eid`
+   after a commit to avoid request cache effects.
+
+You can see an example of security tests in the
+:ref:`adv_tuto_security`.
+
+It is possible to have these tests run continuously using `apycot`_.
+
+.. _apycot: http://www.cubicweb.org/project/apycot
+
+.. _securitytest:
+
+Managing connections or users
++++++++++++++++++++++++++++++
+
+Since unit tests are done with the SQLITE backend and this does not
+support multiple connections at a time, you must be careful when
+simulating security, changing users.
+
+By default, tests run with a user with admin privileges. Connections
+using these credentials are accessible through the `admin_access` object
+of the test classes.
+
+The `repo_cnx()` method returns a connection object that can be used as a
+context manager:
+
+.. sourcecode:: python
+
+   # admin_access is a pre-cooked session wrapping object
+   # it is built with:
+   # self.admin_access = self.new_access('admin')
+   with self.admin_access.repo_cnx() as cnx:
+       cnx.execute(...)
+       self.create_user(cnx, login='user1')
+       cnx.commit()
+
+   user1access = self.new_access('user1')
+   with user1access.web_request() as req:
+       req.execute(...)
+       req.cnx.commit()
+
+On exit of the context manager, a rollback is issued, which releases
+the connection. Don't forget to issue the `cnx.commit()` calls!
+
+.. warning::
+
+   Do not use references kept to the entities created with a
+   connection from another one!
+
+Email notifications tests
+`````````````````````````
+
+When running tests, potentially generated e-mails are not really sent
+but are found in the list `MAILBOX` of module
+:mod:`cubicweb.devtools.testlib`.
+
+You can test your notifications by analyzing the contents of this list, which
+contains objects with two attributes:
+
+* `recipients`, the list of recipients
+* `msg`, email.Message object
+
+Let us look at a simple example from the ``blog`` cube.
+
+.. sourcecode:: python
+
+    from cubicweb.devtools.testlib import CubicWebTC, MAILBOX
+
+    class BlogTestsCubicWebTC(CubicWebTC):
+        """test blog specific behaviours"""
+
+        def test_notifications(self):
+            with self.admin_access.web_request() as req:
+                cubicweb_blog = req.create_entity('Blog', title=u'cubicweb',
+                                    description=u'cubicweb is beautiful')
+                blog_entry_1 = req.create_entity('BlogEntry', title=u'hop',
+                                                 content=u'cubicweb hop')
+                blog_entry_1.cw_set(entry_of=cubicweb_blog)
+                blog_entry_2 = req.create_entity('BlogEntry', title=u'yes',
+                                                 content=u'cubicweb yes')
+                blog_entry_2.cw_set(entry_of=cubicweb_blog)
+                self.assertEqual(len(MAILBOX), 0)
+                req.cnx.commit()
+                self.assertEqual(len(MAILBOX), 2)
+                mail = MAILBOX[0]
+                self.assertEqual(mail.subject, '[data] hop')
+                mail = MAILBOX[1]
+                self.assertEqual(mail.subject, '[data] yes')
+
+Visible actions tests
+`````````````````````
+
+It is easy to write unit tests to test actions which are visible to
+a user or to a category of users. Let's take an example in the
+`conference cube`_.
+
+.. _`conference cube`: http://www.cubicweb.org/project/cubicweb-conference
+.. sourcecode:: python
+
+    class ConferenceActionsTC(CubicWebTC):
+
+        def setup_database(self):
+            with self.admin_access.repo_cnx() as cnx:
+                self.confeid = cnx.create_entity('Conference',
+                                                 title=u'my conf',
+                                                 url_id=u'conf',
+                                                 start_on=date(2010, 1, 27),
+                                                 end_on = date(2010, 1, 29),
+                                                 call_open=True,
+                                                 reverse_is_chair_at=chair,
+                                                 reverse_is_reviewer_at=reviewer).eid
+
+        def test_admin(self):
+            with self.admin_access.web_request() as req:
+                rset = req.find('Conference').one()
+                self.assertListEqual(self.pactions(req, rset),
+                                      [('workflow', workflow.WorkflowActions),
+                                       ('edit', confactions.ModifyAction),
+                                       ('managepermission', actions.ManagePermissionsAction),
+                                       ('addrelated', actions.AddRelatedActions),
+                                       ('delete', actions.DeleteAction),
+                                       ('generate_badge_action', badges.GenerateBadgeAction),
+                                       ('addtalkinconf', confactions.AddTalkInConferenceAction)
+                                       ])
+                self.assertListEqual(self.action_submenu(req, rset, 'addrelated'),
+                                      [(u'add Track in_conf Conference object',
+                                        u'http://testing.fr/cubicweb/add/Track'
+                                        u'?__linkto=in_conf%%3A%(conf)s%%3Asubject&'
+                                        u'__redirectpath=conference%%2Fconf&'
+                                        u'__redirectvid=' % {'conf': self.confeid}),
+                                       ])
+
+You just have to execute a rql query corresponding to the view you want to test,
+and to compare the result of
+:meth:`~cubicweb.devtools.testlib.CubicWebTC.pactions` with the list of actions
+that must be visible in the interface. This is a list of tuples. The first
+element is the action's `__regid__`, the second the action's class.
+
+To test actions in a submenu, you just have to test the result of
+:meth:`~cubicweb.devtools.testlib.CubicWebTC.action_submenu` method. The last
+parameter of the method is the action's category. The result is a list of
+tuples. The first element is the action's title, and the second element the
+action's url.
+
+
+.. _automatic_views_tests:
+
+Automatic views testing
+-----------------------
+
+This is done automatically with the :class:`cubicweb.devtools.testlib.AutomaticWebTest`
+class. At cube creation time, the mycube/test/test_mycube.py file
+contains such a test. The code here has to be uncommented to be
+usable, without further modification.
+
+The ``auto_populate`` method uses a smart algorithm to create
+pseudo-random data in the database, thus enabling the views to be
+invoked and tested.
+
+Depending on the schema, hooks and operations constraints, it is not
+always possible for the automatic auto_populate to proceed.
+
+It is possible of course to completely redefine auto_populate. A
+lighter solution is to give hints (fill some class attributes) about
+what entities and relations have to be skipped by the auto_populate
+mechanism. These are:
+
+* `no_auto_populate`, may contain a list of entity types to skip
+* `ignored_relations`, may contain a list of relation types to skip
+* `application_rql`, may contain a list of rql expressions that
+  auto_populate cannot guess by itself; these must yield resultsets
+  against which views may be selected.
+
+.. warning::
+
+  Take care to not let the imported `AutomaticWebTest` in your test module
+  namespace, else both your subclass *and* this parent class will be run.
+
+Cache heavy database setup
+-------------------------------
+
+Some test suites require a complex setup of the database that takes
+seconds (or even minutes) to complete. Doing the whole setup for each
+individual test makes the whole run very slow. The ``CubicWebTC``
+class offer a simple way to prepare a specific database once for
+multiple tests. The `test_db_id` class attribute of your
+``CubicWebTC`` subclass must be set to a unique identifier and the
+:meth:`pre_setup_database` class method must build the cached content. As
+the :meth:`pre_setup_database` method is not garanteed to be called
+every time a test method is run, you must not set any class attribute
+to be used during test *there*. Databases for each `test_db_id` are
+automatically created if not already in cache. Clearing the cache is
+up to the user. Cache files are found in the :file:`data/database`
+subdirectory of your test directory.
+
+.. warning::
+
+  Take care to always have the same :meth:`pre_setup_database`
+  function for all classes with a given `test_db_id` otherwise your
+  tests will have unpredictable results depending on the first
+  encountered one.
+
+
+Testing on a real-life database
+-------------------------------
+
+The ``CubicWebTC`` class uses the `cubicweb.devtools.ApptestConfiguration`
+configuration class to setup its testing environment (database driver,
+user password, application home, and so on). The `cubicweb.devtools`
+module also provides a `RealDatabaseConfiguration`
+class that will read a regular cubicweb sources file to fetch all
+this information but will also prevent the database to be initalized
+and reset between tests.
+
+For a test class to use a specific configuration, you have to set
+the `_config` class attribute on the class as in:
+
+.. sourcecode:: python
+
+    from cubicweb.devtools import RealDatabaseConfiguration
+    from cubicweb.devtools.testlib import CubicWebTC
+
+    class BlogRealDatabaseTC(CubicWebTC):
+        _config = RealDatabaseConfiguration('blog',
+                                            sourcefile='/path/to/realdb_sources')
+
+        def test_blog_rss(self):
+            with self.admin_access.web_request() as req:
+            rset = req.execute('Any B ORDERBY D DESC WHERE B is BlogEntry, '
+                               'B created_by U, U login "logilab", B creation_date D')
+            self.view('rss', rset, req=req)
+
+
+Testing with other cubes
+------------------------
+
+Sometimes a small component cannot be tested all by itself, so one
+needs to specify other cubes to be used as part of the the unit test
+suite. This is handled by the ``bootstrap_cubes`` file located under
+``mycube/test/data``. One example from the `preview` cube::
+
+ card, file, preview
+
+The format is:
+
+* possibly several empy lines or lines starting with ``#`` (comment lines)
+* one line containing a comma-separated list of cube names.
+
+It is also possible to add a ``schema.py`` file in
+``mycube/test/data``, which will be used by the testing framework,
+therefore making new entity types and relations available to the
+tests. 
+
+Literate programming
+--------------------
+
+CubicWeb provides some literate programming capabilities. The :ref:`cubicweb-ctl`
+`shell` command accepts different file formats. If your file ends with `.txt`
+or `.rst`, the file will be parsed by :mod:`doctest.testfile` with CubicWeb's
+:ref:`migration` API enabled in it.
+
+Create a `scenario.txt` file in the `test/` directory and fill with some content.
+Refer to the :mod:`doctest.testfile` `documentation`_.
+
+.. _documentation: http://docs.python.org/library/doctest.html
+
+Then, you can run it directly by::
+
+    $ cubicweb-ctl shell <cube_instance> test/scenario.txt
+
+When your scenario file is ready, put it in a new test case to be able to run
+it automatically.
+
+.. sourcecode:: python
+
+      from os.path import dirname, join
+      from logilab.common.testlib import unittest_main
+      from cubicweb.devtools.testlib import CubicWebTC
+
+      class AcceptanceTC(CubicWebTC):
+
+              def test_scenario(self):
+                      self.assertDocTestFile(join(dirname(__file__), 'scenario.txt'))
+
+      if __name__ == '__main__':
+              unittest_main()
+
+Skipping a scenario
+```````````````````
+
+If you want to set up initial conditions that you can't put in your unit test
+case, you have to use a :exc:`KeyboardInterrupt` exception only because of the
+way :mod:`doctest` module will catch all the exceptions internally.
+
+    >>> if condition_not_met:
+    ...     raise KeyboardInterrupt('please, check your fixture.')
+
+Passing paramaters
+``````````````````
+Using extra arguments to parametrize your scenario is possible by prepending them
+by double dashes.
+
+Please refer to the `cubicweb-ctl shell --help` usage.
+
+.. important::
+    Your scenario file must be utf-8 encoded.
+
+Test APIS
+---------
+
+Using Pytest
+````````````
+
+The `pytest` utility (shipping with `logilab-common`_, which is a
+mandatory dependency of CubicWeb) extends the Python unittest
+functionality and is the preferred way to run the CubicWeb test
+suites. Bare unittests also work the usual way.
+
+.. _logilab-common: http://www.logilab.org/project/logilab-common
+
+To use it, you may:
+
+* just launch `pytest` in your cube to execute all tests (it will
+  discover them automatically)
+* launch `pytest unittest_foo.py` to execute one test file
+* launch `pytest unittest_foo.py bar` to execute all test methods and
+  all test cases whose name contains `bar`
+
+Additionally, the `-x` option tells pytest to exit at the first error
+or failure. The `-i` option tells pytest to drop into pdb whenever an
+exception occurs in a test.
+
+When the `-x` option has been used and the run stopped on a test, it
+is possible, after having fixed the test, to relaunch pytest with the
+`-R` option to tell it to start testing again from where it previously
+failed.
+
+Using the `TestCase` base class
+```````````````````````````````
+
+The base class of CubicWebTC is logilab.common.testlib.TestCase, which
+provides a lot of convenient assertion methods.
+
+.. autoclass:: logilab.common.testlib.TestCase
+   :members:
+
+CubicWebTC API
+``````````````
+.. autoclass:: cubicweb.devtools.testlib.CubicWebTC
+   :members:
+
+
+What you need to know about request and session
+-----------------------------------------------
+
+.. image:: ../images/request_session.png
+
+First, remember to think that some code run on a client side, some
+other on the repository side. More precisely:
+
+* client side: web interface, raw repoapi connection (cubicweb-ctl shell for
+  instance);
+
+* repository side: RQL query execution, that may trigger hooks and operation.
+
+The client interacts with the repository through a repoapi connection.
+
+
+.. note::
+
+   These distinctions are going to disappear in cubicweb 3.21 (if not
+   before).
+
+A repoapi connection is tied to a session in the repository. The connection and
+request objects are inaccessible from repository code / the session object is
+inaccessible from client code (theoretically at least).
+
+The web interface provides a request class.  That `request` object provides
+access to all cubicweb resources, eg:
+
+* the registry (which itself provides access to the schema and the
+  configuration);
+
+* an underlying repoapi connection (when using req.execute, you actually call the
+  repoapi);
+
+* other specific resources depending on the client type (url generation according
+  to base url, form parameters, etc.).
+
+
+A `session` provides an api similar to a request regarding RQL execution and
+access to global resources (registry and all), but also has the following
+responsibilities:
+
+* handle transaction data, that will live during the time of a single
+  transaction. This includes the database connections that will be used to
+  execute RQL queries.
+
+* handle persistent data that may be used across different (web) requests
+
+* security and hooks control (not possible through a request)
+
+
+The `_cw` attribute
+```````````````````
+The `_cw` attribute available on every application object provides access to all
+cubicweb resources, i.e.:
+
+- For code running on the client side (eg web interface view), `_cw` is a request
+  instance.
+
+- For code running on the repository side (hooks and operation), `_cw` is a
+  Connection or Session instance.
+
+
+Beware some views may be called with a session (e.g. notifications) or with a
+request.
+
+
+Request, session and transaction
+````````````````````````````````
+
+In the web interface, an HTTP request is handled by a single request, which will
+be thrown away once the response is sent.
+
+The web publisher handles the transaction:
+
+* commit / rollback is done automatically
+
+* you should not commit / rollback explicitly, except if you really
+  need it
+
+Let's detail the process:
+
+1. an incoming RQL query comes from a client to the web stack
+
+2. the web stack opens an authenticated database connection for the
+   request, which is associated to a user session
+
+3. the query is executed (through the repository connection)
+
+4. this query may trigger hooks. Hooks and operations may execute some rql queries
+   through `cnx.execute`.
+
+5. the repository gets the result of the query in 1. If it was a RQL read query,
+   the database connection is released. If it was a write query, the connection
+   is then tied to the session until the transaction is commited or rolled back.
+
+6. results are sent back to the client
+
+This implies several things:
+
+* when using a request, or code executed in hooks, this database
+  connection handling is totally transparent
+
+* however, take care when writing tests: you are usually faking /
+  testing both the server and the client side, so you have to decide
+  when to use RepoAccess.client_cnx or RepoAccess.repo_cnx. Ask
+  yourself "where will the code I want to test be running, client or
+  repository side?". The response is usually: use a repo (since the
+  "client connection" concept is going away in a couple of releases).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devrepo/vreg.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,119 @@
+The Registry, selectors and application objects
+===============================================
+
+This chapter deals with some of the  core concepts of the |cubicweb| framework
+which make it different from other frameworks (and maybe not easy to
+grasp at a first glance). To be able to do advanced development with
+|cubicweb| you need a good understanding of what is explained below.
+
+This chapter goes deep into details. You don't have to remember them
+all but keep it in mind so you can go back there later.
+
+An overview of AppObjects, the VRegistry and Selectors is given in the
+:ref:`VRegistryIntro` chapter.
+
+.. autodocstring:: cubicweb.cwvreg
+.. autodocstring:: cubicweb.predicates
+.. automodule:: cubicweb.appobject
+
+Base predicates
+---------------
+
+Predicates are scoring functions that are called by the registry to tell whenever
+an appobject can be selected in a given context. Predicates may be chained
+together using operators to build a selector. A selector is the glue that tie
+views to the data model or whatever input context. Using them appropriately is an
+essential part of the construction of well behaved cubes.
+
+Of course you may have to write your own set of predicates as your needs grows
+and you get familiar with the framework (see :ref:`CustomPredicates`).
+
+Here is a description of generic predicates provided by CubicWeb that should suit
+most of your needs.
+
+Bare predicates
+~~~~~~~~~~~~~~~
+Those predicates are somewhat dumb, which doesn't mean they're not (very) useful.
+
+.. autoclass:: cubicweb.appobject.yes
+.. autoclass:: cubicweb.predicates.match_kwargs
+.. autoclass:: cubicweb.predicates.appobject_selectable
+.. autoclass:: cubicweb.predicates.adaptable
+.. autoclass:: cubicweb.predicates.configuration_values
+
+
+Result set predicates
+~~~~~~~~~~~~~~~~~~~~~
+Those predicates are looking for a result set in the context ('rset' argument or
+the input context) and match or not according to its shape. Some of these
+predicates have different behaviour if a particular cell of the result set is
+specified using 'row' and 'col' arguments of the input context or not.
+
+.. autoclass:: cubicweb.predicates.none_rset
+.. autoclass:: cubicweb.predicates.any_rset
+.. autoclass:: cubicweb.predicates.nonempty_rset
+.. autoclass:: cubicweb.predicates.empty_rset
+.. autoclass:: cubicweb.predicates.one_line_rset
+.. autoclass:: cubicweb.predicates.multi_lines_rset
+.. autoclass:: cubicweb.predicates.multi_columns_rset
+.. autoclass:: cubicweb.predicates.paginated_rset
+.. autoclass:: cubicweb.predicates.sorted_rset
+.. autoclass:: cubicweb.predicates.one_etype_rset
+.. autoclass:: cubicweb.predicates.multi_etypes_rset
+
+
+Entity predicates
+~~~~~~~~~~~~~~~~~
+Those predicates are looking for either an `entity` argument in the input context,
+or entity found in the result set ('rset' argument or the input context) and
+match or not according to entity's (instance or class) properties.
+
+.. autoclass:: cubicweb.predicates.non_final_entity
+.. autoclass:: cubicweb.predicates.is_instance
+.. autoclass:: cubicweb.predicates.score_entity
+.. autoclass:: cubicweb.predicates.rql_condition
+.. autoclass:: cubicweb.predicates.relation_possible
+.. autoclass:: cubicweb.predicates.partial_relation_possible
+.. autoclass:: cubicweb.predicates.has_related_entities
+.. autoclass:: cubicweb.predicates.partial_has_related_entities
+.. autoclass:: cubicweb.predicates.has_permission
+.. autoclass:: cubicweb.predicates.has_add_permission
+.. autoclass:: cubicweb.predicates.has_mimetype
+.. autoclass:: cubicweb.predicates.is_in_state
+.. autofunction:: cubicweb.predicates.on_fire_transition
+
+
+Logged user predicates
+~~~~~~~~~~~~~~~~~~~~~~
+Those predicates are looking for properties of the user issuing the request.
+
+.. autoclass:: cubicweb.predicates.match_user_groups
+
+
+Web request predicates
+~~~~~~~~~~~~~~~~~~~~~~
+Those predicates are looking for properties of *web* request, they can not be
+used on the data repository side.
+
+.. autoclass:: cubicweb.predicates.no_cnx
+.. autoclass:: cubicweb.predicates.anonymous_user
+.. autoclass:: cubicweb.predicates.authenticated_user
+.. autoclass:: cubicweb.predicates.match_form_params
+.. autoclass:: cubicweb.predicates.match_search_state
+.. autoclass:: cubicweb.predicates.match_context_prop
+.. autoclass:: cubicweb.predicates.match_context
+.. autoclass:: cubicweb.predicates.match_view
+.. autoclass:: cubicweb.predicates.primary_view
+.. autoclass:: cubicweb.predicates.contextual
+.. autoclass:: cubicweb.predicates.specified_etype_implements
+.. autoclass:: cubicweb.predicates.attribute_edited
+.. autoclass:: cubicweb.predicates.match_transition
+
+
+Other predicates
+~~~~~~~~~~~~~~~~
+.. autoclass:: cubicweb.predicates.match_exception
+.. autoclass:: cubicweb.predicates.debug_mode
+
+You'll also find some other (very) specific predicates hidden in other modules
+than :mod:`cubicweb.predicates`.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/ajax.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,12 @@
+.. _ajax:
+
+Ajax
+----
+
+CubicWeb provides a few helpers to facilitate *javascript <-> python* communications.
+
+You can, for instance, register some python functions that will become
+callable from javascript through ajax calls. All the ajax URLs are handled
+by the :class:`cubicweb.web.views.ajaxcontroller.AjaxController` controller.
+
+.. automodule:: cubicweb.web.views.ajaxcontroller
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/controllers.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,93 @@
+.. _controllers:
+
+Controllers
+-----------
+
+Overview
+++++++++
+
+Controllers are responsible for taking action upon user requests
+(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. They are all defined in
+(:mod:`cubicweb.web.views.basecontrollers`).
+
+`Browsing`:
+
+* the View controller is associated with most browsing actions within a
+  CubicWeb application: it always instantiates a
+  :ref:`the_main_template_layout` and lets the ResultSet/Views dispatch system
+  build up the whole content; it handles :exc:`ObjectNotFound` and
+  :exc:`NoSelectableObject` errors that may bubble up to its entry point, in an
+  end-user-friendly way (but other programming errors will slip through)
+
+* the JSonpController is a wrapper around the ``ViewController`` that
+  provides jsonp_ services. Padding can be specified with the
+  ``callback`` request parameter. Only *jsonexport* / *ejsonexport*
+  views can be used. If another ``vid`` is specified, it will be
+  ignored and replaced by *jsonexport*. Request is anonymized
+  to avoid returning sensitive data and reduce the risks of CSRF attacks;
+
+* the Login/Logout controllers make effective user login or logout
+  requests
+
+
+.. _jsonp: http://en.wikipedia.org/wiki/JSONP
+
+`Edition`:
+
+* the Edit controller (see :ref:`edit_controller`) handles CRUD
+  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`` 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`:
+
+* the ``SendMail controller`` (web/views/basecontrollers.py) is reponsible
+  for outgoing email notifications
+
+* the MailBugReport controller (web/views/basecontrollers.py) allows
+  to quickly have a `reportbug` feature in one's application
+
+* the :class:`cubicweb.web.views.ajaxcontroller.AjaxController`
+  (:mod:`cubicweb.web.views.ajaxcontroller`) provides
+  services for Ajax calls, typically using JSON as a serialization format
+  for input, and sometimes using either JSON or XML for output. See
+  :ref:`ajax` chapter for more information.
+
+
+Registration
+++++++++++++
+
+All controllers (should) live in the 'controllers' namespace within
+the global registry.
+
+Concrete controllers
+++++++++++++++++++++
+
+Most API details should be resolved by source code inspection, as the
+various controllers have differing goals. See for instance the
+:ref:`edit_controller` chapter.
+
+:mod:`cubicweb.web.controller` contains the top-level abstract
+Controller class and its unimplemented entry point
+`publish(rset=None)` method.
+
+A handful of helpers are also provided there:
+
+* process_rql builds a result set from an rql query typically issued
+  from the browser (and available through _cw.form['rql'])
+
+* validate_cache will force cache validation handling with respect to
+  the HTTP Cache directives (that were typically originally issued
+  from a previous server -> client response); concrete Controller
+  implementations dealing with HTTP (thus, for instance, not the
+  SendMail controller) may very well call this in their publication
+  process.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/css.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,30 @@
+.. -*- coding: utf-8 -*-
+
+CSS Stylesheet
+---------------
+Conventions
+~~~~~~~~~~~
+
+.. XXX external_resources variable
+..    naming convention
+..    request.add_css
+
+
+Extending / overriding existing styles
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We cannot modify the order in which the application is reading the CSS. In
+the case we want to create new CSS style, the best is to define it a in a new
+CSS located under ``myapp/data/`` and use those new styles while writing
+customized views and templates.
+
+If you want to modify an existing CSS styling property, you will have to use
+``!important`` declaration to override the existing property. The application
+apply a higher priority on the default CSS and you can not change that.
+Customized CSS will not be read first.
+
+
+CubicWeb stylesheets
+~~~~~~~~~~~~~~~~~~~~
+
+.. XXX explain diffenrent files and main classes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/edition/dissection.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,316 @@
+
+.. _form_dissection:
+
+Dissection of an entity form
+----------------------------
+
+This is done (again) with a vanilla instance of the `tracker`_
+cube. We will populate the database with a bunch of entities and see
+what kind of job the automatic entity form does.
+
+.. _`tracker`: http://www.cubicweb.org/project/cubicweb-tracker
+
+Populating the database
+~~~~~~~~~~~~~~~~~~~~~~~
+
+We should start by setting up a bit of context: a project with two
+unpublished versions, and a ticket linked to the project and the first
+version.
+
+.. sourcecode:: python
+
+ >>> p = rql('INSERT Project P: P name "cubicweb"')
+ >>> for num in ('0.1.0', '0.2.0'):
+ ...  rql('INSERT Version V: V num "%s", V version_of P WHERE P eid %%(p)s' % num, {'p': p[0][0]})
+ ...
+ <resultset 'INSERT Version V: V num "0.1.0", V version_of P WHERE P eid %(p)s' (1 rows): [765L] (('Version',))>
+ <resultset 'INSERT Version V: V num "0.2.0", V version_of P WHERE P eid %(p)s' (1 rows): [766L] (('Version',))>
+ >>> t = rql('INSERT Ticket T: T title "let us write more doc", T done_in V, '
+             'T concerns P WHERE V num "0.1.0"', P eid %(p)s', {'p': p[0][0]})
+ >>> commit()
+
+Now let's see what the edition form builds for us.
+
+.. sourcecode:: python
+
+ >>> cnx.use_web_compatible_requests('http://fakeurl.com')
+ >>> req = cnx.request()
+ >>> form = req.vreg['forms'].select('edition', req, rset=rql('Ticket T'))
+ >>> html = form.render()
+
+.. note::
+
+  In order to play interactively with web side application objects, we have to
+  cheat a bit to have request object that will looks like HTTP request object, by
+  calling :meth:`use_web_compatible_requests()` on the connection.
+
+This creates an automatic entity form. The ``.render()`` call yields
+an html (unicode) string. The html output is shown below (with
+internal fieldset omitted).
+
+Looking at the html output
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The form enveloppe
+''''''''''''''''''
+
+.. sourcecode:: html
+
+ <div class="iformTitle"><span>main informations</span></div>
+ <div class="formBody">
+  <form action="http://crater:9999/validateform" method="post" enctype="application/x-www-form-urlencoded"
+        id="entityForm" onsubmit="return freezeFormButtons(&#39;entityForm&#39;);"
+        class="entityForm" target="eformframe">
+    <div id="progress">validating...</div>
+    <fieldset>
+      <input name="__form_id" type="hidden" value="edition" />
+      <input name="__errorurl" type="hidden" value="http://perdu.com#entityForm" />
+      <input name="__domid" type="hidden" value="entityForm" />
+      <input name="__type:763" type="hidden" value="Ticket" />
+      <input name="eid" type="hidden" value="763" />
+      <input name="__maineid" type="hidden" value="763" />
+      <input name="_cw_edited_fields:763" type="hidden"
+             value="concerns-subject,done_in-subject,priority-subject,type-subject,title-subject,description-subject,__type,_cw_generic_field" />
+      ...
+    </fieldset>
+    <iframe width="0px" height="0px" name="eformframe" id="eformframe" src="javascript: void(0);"></iframe>
+   </form>
+ </div>
+
+The main fieldset encloses a set of hidden fields containing various
+metadata, that will be used by the `edit controller` to process it
+back correctly.
+
+The `freezeFormButtons(...)` javascript callback defined on the
+``onlick`` event of the form element prevents accidental multiple
+clicks in a row.
+
+The ``action`` of the form is mapped to the ``validateform`` controller
+(situated in :mod:`cubicweb.web.views.basecontrollers`).
+
+A full explanation of the validation loop is given in
+:ref:`validation_process`.
+
+.. _attributes_section:
+
+The attributes section
+''''''''''''''''''''''
+
+We can have a look at some of the inner nodes of the form. Some fields
+are omitted as they are redundant for our purposes.
+
+.. sourcecode:: html
+
+      <fieldset class="default">
+        <table class="attributeForm">
+          <tr class="title_subject_row">
+            <th class="labelCol"><label class="required" for="title-subject:763">title</label></th>
+            <td>
+              <input id="title-subject:763" maxlength="128" name="title-subject:763" size="45"
+                     tabindex="1" type="text" value="let us write more doc" />
+            </td>
+          </tr>
+          ... (description field omitted) ...
+          <tr class="priority_subject_row">
+            <th class="labelCol"><label class="required" for="priority-subject:763">priority</label></th>
+            <td>
+              <select id="priority-subject:763" name="priority-subject:763" size="1" tabindex="4">
+                <option value="important">important</option>
+                <option selected="selected" value="normal">normal</option>
+                <option value="minor">minor</option>
+              </select>
+              <div class="helper">importance</div>
+            </td>
+          </tr>
+          ... (type field omitted) ...
+          <tr class="concerns_subject_row">
+            <th class="labelCol"><label class="required" for="concerns-subject:763">concerns</label></th>
+            <td>
+              <select id="concerns-subject:763" name="concerns-subject:763" size="1" tabindex="6">
+                <option selected="selected" value="760">Foo</option>
+              </select>
+            </td>
+          </tr>
+          <tr class="done_in_subject_row">
+            <th class="labelCol"><label for="done_in-subject:763">done in</label></th>
+            <td>
+              <select id="done_in-subject:763" name="done_in-subject:763" size="1" tabindex="7">
+                <option value="__cubicweb_internal_field__"></option>
+                <option selected="selected" value="761">Foo 0.1.0</option>
+                <option value="762">Foo 0.2.0</option>
+              </select>
+              <div class="helper">version in which this ticket will be / has been  done</div>
+            </td>
+          </tr>
+        </table>
+      </fieldset>
+
+
+Note that the whole form layout has been computed by the form
+renderer. It is the renderer which produces the table
+structure. Otherwise, the fields html structure is emitted by their
+associated widget.
+
+While it is called the `attributes` section of the form, it actually
+contains attributes and *mandatory relations*. For each field, we
+observe:
+
+* a dedicated row with a specific class, such as ``title_subject_row``
+  (responsability of the form renderer)
+
+* an html widget (input, select, ...) with:
+
+  * an id built from the ``rtype-role:eid`` pattern
+
+  * a name built from the same pattern
+
+  * possible values or preselected options
+
+The relations section
+'''''''''''''''''''''
+
+.. sourcecode:: html
+
+      <fieldset class="This ticket :">
+        <legend>This ticket :</legend>
+        <table class="attributeForm">
+          <tr class="_cw_generic_field_None_row">
+            <td colspan="2">
+              <table id="relatedEntities">
+                <tr><th>&#160;</th><td>&#160;</td></tr>
+                <tr id="relationSelectorRow_763" class="separator">
+                  <th class="labelCol">
+                    <select id="relationSelector_763" tabindex="8"
+                            onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,763);">
+                      <option value="">select a relation</option>
+                      <option value="appeared_in_subject">appeared in</option>
+                      <option value="custom_workflow_subject">custom workflow</option>
+                      <option value="depends_on_object">dependency of</option>
+                      <option value="depends_on_subject">depends on</option>
+                      <option value="identical_to_subject">identical to</option>
+                      <option value="see_also_subject">see also</option>
+                    </select>
+                  </th>
+                  <td id="unrelatedDivs_763"></td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+        </table>
+      </fieldset>
+
+The optional relations are grouped into a drop-down combo
+box. Selection of an item triggers a javascript function which will:
+
+* show already related entities in the div of id `relatedentities`
+  using a two-colown layout, with an action to allow deletion of
+  individual relations (there are none in this example)
+
+* provide a relation selector in the div of id `relationSelector_EID`
+  to allow the user to set up relations and trigger dynamic action on
+  the last div
+
+* fill the div of id `unrelatedDivs_EID` with a dynamically computed
+  selection widget allowing direct selection of an unrelated (but
+  relatable) entity or a switch towards the `search mode` of
+  |cubicweb| which allows full browsing and selection of an entity
+  using a dedicated action situated in the left column boxes.
+
+
+The buttons zone
+''''''''''''''''
+
+Finally comes the buttons zone.
+
+.. sourcecode:: html
+
+      <table width="100%">
+        <tbody>
+          <tr>
+            <td align="center">
+              <button class="validateButton" tabindex="9" type="submit" value="validate">
+                <img alt="OK_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/ok.png" />
+                validate
+              </button>
+            </td>
+            <td style="align: right; width: 50%;">
+              <button class="validateButton"
+                      onclick="postForm(&#39;__action_apply&#39;, &#39;button_apply&#39;, &#39;entityForm&#39;)"
+                      tabindex="10" type="button" value="apply">
+                <img alt="APPLY_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/plus.png" />
+                apply
+              </button>
+              <button class="validateButton"
+                      onclick="postForm(&#39;__action_cancel&#39;, &#39;button_cancel&#39;, &#39;entityForm&#39;)"
+                      tabindex="11" type="button" value="cancel">
+                <img alt="CANCEL_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/cancel.png" />
+                cancel
+              </button>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+
+The most notable artifacts here are the ``postForm(...)`` calls
+defined on click events on these buttons. This function basically
+submits the form.
+
+.. _validation_process:
+
+The form validation process
+---------------------------
+
+Validation loop
+~~~~~~~~~~~~~~~
+
+On form submission, the form.action is invoked. Basically, the
+``validateform`` controller is called and its output lands in the
+specified ``target``, an invisible ``<iframe>`` at the end of the
+form.
+
+Hence, the main page is not replaced, only the iframe contents. The
+``validateform`` controller only outputs a tiny javascript fragment
+which is then immediately executed.
+
+.. sourcecode:: html
+
+ <iframe width="0px" height="0px" name="eformframe" id="eformframe" src="javascript: void(0);">
+   <script type="text/javascript">
+     window.parent.handleFormValidationResponse('entityForm', null, null,
+                                                [false, [2164, {"name-subject": "required field"}], null],
+                                                null);
+   </script>
+ </iframe>
+
+The ``window.parent`` part ensures the javascript function is called
+on the right context (that is: the form element). We will describe its
+parameters:
+
+* first comes the form id (`entityForm`)
+
+* then two optional callbacks for the success and failure case
+
+* an array containing:
+
+  * a boolean which indicates status (success or failure), and then, on error:
+
+    * an array structured as ``[eid, {'rtype-role': 'error msg'}, ...]``
+
+  * on success:
+
+    * a url (string) representing the next thing to jump to
+
+Given the array structure described above, it is quite simple to
+manipulate the DOM to show the errors at appropriate places.
+
+Explanation
+~~~~~~~~~~~
+
+This mecanism may seem a bit overcomplicated but we have to deal with
+two realities:
+
+* in the (strict) XHTML world, there are no iframes (hence the dynamic
+  inclusion, tolerated by Firefox)
+
+* no (or not all) browser(s) support file input field handling through
+  ajax.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/edition/editcontroller.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,113 @@
+.. _edit_controller:
+
+The `edit controller`
+---------------------
+
+It can be found in (:mod:`cubicweb.web.views.editcontroller`). This
+controller processes data received from an html form to create or
+update entities.
+
+Edition handling
+~~~~~~~~~~~~~~~~
+
+The parameters related to entities to edit are specified as follows
+(first seen in :ref:`attributes_section`)::
+
+  <rtype-role>:<entity eid>
+
+where entity eid could be a letter in case of an entity to create. We
+name those parameters as *qualified*.
+
+* Retrieval of entities to edit is done by using the forms parameters
+  `eid` and `__type`
+
+* For all the attributes and the relations of an entity to edit
+  (attributes and relations are handled a bit differently but these
+  details are not much relevant here) :
+
+   * using the ``rtype``, ``role`` and ``__type`` information, fetch
+     an appropriate field instance
+
+   * check if the field has been modified (if not, proceed to the next
+     relation)
+
+   * build an rql expression to update the entity
+
+At the end, all rql expressions are executed.
+
+* For each entity to edit:
+
+   * if a qualified parameter `__linkto` is specified, its value has
+     to be a string (or a list of strings) such as: ::
+
+        <relation type>:<eids>:<target>
+
+     where <target> is either `subject` or `object` and each eid could
+     be separated from the others by a `_`. Target specifies if the
+     *edited entity* is subject or object of the relation and each
+     relation specified will be inserted.
+
+    * if a qualified parameter `__clone_eid` is specified for an entity, the
+      relations of the specified entity passed as value of this parameter are
+      copied on the edited entity.
+
+    * if a qualified parameter `__delete` is specified, its value must be
+      a string or a list of string such as follows: ::
+
+          <subjects eids>:<relation type>:<objects eids>
+
+      where each eid subject or object can be seperated from the other
+      by `_`. Each specified relation will be deleted.
+
+
+* If no entity is edited but the form contains the parameters `__linkto`
+  and `eid`, this one is interpreted by using the value specified for `eid`
+  to designate the entity on which to add the relations.
+
+.. note::
+
+   * if the parameter `__action_delete` is found, all the entities specified
+     as to be edited will be deleted.
+
+   * if the parameter `__action_cancel` is found, no action is completed.
+
+   * if the parameter `__action_apply` is found, the editing is
+     applied normally but the redirection is done on the form (see
+     :ref:`RedirectionControl`).
+
+   * if no entity is found to be edited and if there is no parameter
+     `__action_delete`, `__action_cancel`, `__linkto`, `__delete` or
+     `__insert`, an error is raised.
+
+   * using the parameter `__message` in the form will allow to use its value
+     as a message to provide the user once the editing is completed.
+
+
+.. _RedirectionControl:
+
+Redirection control
+~~~~~~~~~~~~~~~~~~~
+Once editing is completed, there is still an issue left: where should we go
+now? If nothing is specified, the controller will do his job but it does not
+mean we will be happy with the result. We can control that by using the
+following parameters:
+
+* `__redirectpath`: path of the URL (relative to the root URL of the site,
+  no form parameters
+
+* `__redirectparams`: forms parameters to add to the path
+
+* `__redirectrql`: redirection RQL request
+
+* `__redirectvid`: redirection view identifier
+
+* `__errorurl`: initial form URL, used for redirecting in case a validation
+  error is raised during editing. If this one is not specified, an error page
+  is displayed instead of going back to the form (which is, if necessary,
+  responsible for displaying the errors)
+
+* `__form_id`: initial view form identifier, used if `__action_apply` is
+  found
+
+In general we use either `__redirectpath` and `__redirectparams` or
+`__redirectrql` and `__redirectvid`.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/edition/examples.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,232 @@
+Examples
+--------
+
+(Automatic) Entity form
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Looking at some cubes available on the `cubicweb forge`_ we find some
+with form manipulation. The following example comes from the the
+`conference`_ cube. It extends the change state form for the case
+where a ``Talk`` entity is getting into ``submitted`` state. The goal
+is to select reviewers for the submitted talk.
+
+.. _`cubicweb forge`: http://www.cubicweb.org/view?rql=Any+P+ORDERBY+N+WHERE+P+name+LIKE+%22cubicweb-%25%22%2C+P+is+Project%2C+P+name+N
+.. _`conference`: http://www.cubicweb.org/project/cubicweb-conference
+
+.. sourcecode:: python
+
+ from cubicweb.web import formfields as ff, formwidgets as fwdgs
+ class SendToReviewerStatusChangeView(ChangeStateFormView):
+     __select__ = (ChangeStateFormView.__select__ &
+                   is_instance('Talk') &
+                   rql_condition('X in_state S, S name "submitted"'))
+
+     def get_form(self, entity, transition, **kwargs):
+         form = super(SendToReviewerStatusChangeView, self).get_form(entity, transition, **kwargs)
+         relation = ff.RelationField(name='reviews', role='object',
+                                     eidparam=True,
+                                     label=_('select reviewers'),
+                                     widget=fwdgs.Select(multiple=True))
+         form.append_field(relation)
+         return form
+
+Simple extension of a form can be done from within the `FormView`
+wrapping the form. FormView instances have a handy ``get_form`` method
+that returns the form to be rendered. Here we add a ``RelationField``
+to the base state change form.
+
+One notable point is the ``eidparam`` argument: it tells both the
+field and the ``edit controller`` that the field is linked to a
+specific entity.
+
+It is hence entirely possible to add ad-hoc fields that will be
+processed by some specialized instance of the edit controller.
+
+
+Ad-hoc fields form
+~~~~~~~~~~~~~~~~~~
+
+We want to define a form doing something else than editing an entity. The idea is
+to propose a form to send an email to entities in a resultset which implements
+:class:`IEmailable`.  Let's take a simplified version of what you'll find in
+:mod:`cubicweb.web.views.massmailing`.
+
+Here is the source code:
+
+.. sourcecode:: python
+
+    def sender_value(form, field):
+	return '%s <%s>' % (form._cw.user.dc_title(), form._cw.user.get_email())
+
+    def recipient_choices(form, field):
+	return [(e.get_email(), e.eid)
+                 for e in form.cw_rset.entities()
+		 if e.get_email()]
+
+    def recipient_value(form, field):
+	return [e.eid for e in form.cw_rset.entities()
+                if e.get_email()]
+
+    class MassMailingForm(forms.FieldsForm):
+	__regid__ = 'massmailing'
+
+	needs_js = ('cubicweb.widgets.js',)
+	domid = 'sendmail'
+	action = 'sendmail'
+
+	sender = ff.StringField(widget=TextInput({'disabled': 'disabled'}),
+				label=_('From:'),
+				value=sender_value)
+
+	recipient = ff.StringField(widget=CheckBox(),
+	                           label=_('Recipients:'),
+				   choices=recipient_choices,
+				   value=recipients_value)
+
+	subject = ff.StringField(label=_('Subject:'), max_length=256)
+
+	mailbody = ff.StringField(widget=AjaxWidget(wdgtype='TemplateTextField',
+						    inputid='mailbody'))
+
+	form_buttons = [ImgButton('sendbutton', "javascript: $('#sendmail').submit()",
+				  _('send email'), 'SEND_EMAIL_ICON'),
+			ImgButton('cancelbutton', "javascript: history.back()",
+				  stdmsgs.BUTTON_CANCEL, 'CANCEL_EMAIL_ICON')]
+
+Let's detail what's going on up there. Our form will hold four fields:
+
+* a sender field, which is disabled and will simply contains the user's name and
+  email
+
+* a recipients field, which will be displayed as a list of users in the context
+  result set with checkboxes so user can still choose who will receive his mailing
+  by checking or not the checkboxes. By default all of them will be checked since
+  field's value return a list containing same eids as those returned by the
+  vocabulary function.
+
+* a subject field, limited to 256 characters (hence we know a
+  :class:`~cubicweb.web.formwidgets.TextInput` will be used, as explained in
+  :class:`~cubicweb.web.formfields.StringField`)
+
+* a mailbody field. This field use an ajax widget, defined in `cubicweb.widgets.js`,
+  and whose definition won't be shown here. Notice though that we tell this form
+  need this javascript file by using `needs_js`
+
+Last but not least, we add two buttons control: one to post the form using
+javascript (`$('#sendmail')` being the jQuery call to get the element with DOM id
+set to 'sendmail', which is our form DOM id as specified by its `domid`
+attribute), another to cancel the form which will go back to the previous page
+using another javascript call. Also we specify an image to use as button icon as a
+resource identifier (see :ref:`uiprops`) given as last argument to
+:class:`cubicweb.web.formwidgets.ImgButton`.
+
+To see this form, we still have to wrap it in a view. This is pretty simple:
+
+.. sourcecode:: python
+
+    class MassMailingFormView(form.FormViewMixIn, EntityView):
+	__regid__ = 'massmailing'
+	__select__ = is_instance(IEmailable) & authenticated_user()
+
+	def call(self):
+	    form = self._cw.vreg['forms'].select('massmailing', self._cw,
+	                                         rset=self.cw_rset)
+	    form.render(w=self.w)
+
+As you see, we simply define a view with proper selector so it only apply to a
+result set containing :class:`IEmailable` entities, and so that only users in the
+managers or users group can use it. Then in the `call()` method for this view we
+simply select the above form and call its `.render()` method with our output
+stream as argument.
+
+When this form is submitted, a controller with id 'sendmail' will be called (as
+specified using `action`). This controller will be responsible to actually send
+the mail to specified recipients.
+
+Here is what it looks like:
+
+.. sourcecode:: python
+
+   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))
+
+
+The entry point of a controller is the publish method. In that case we simply get
+back post values in request's `form` attribute, get user instances according
+to eids found in the 'recipient' form value, and send email after calling
+:func:`format_mail` to get a proper email message. If we can't send email or
+if we successfully sent email, we redirect to the index page with proper message
+to inform the user.
+
+Also notice that our controller has a selector that deny access to it
+to anonymous users (we don't want our instance to be used as a spam
+relay), but also checks if the expected parameters are specified in
+forms. That avoids later defensive programming (though it's not enough
+to handle all possible error cases).
+
+To conclude our example, suppose we wish a different form layout and that existent
+renderers are not satisfying (we would check that first of course :). We would then
+have to define our own renderer:
+
+.. sourcecode:: python
+
+    class MassMailingFormRenderer(formrenderers.FormRenderer):
+        __regid__ = 'massmailing'
+
+        def _render_fields(self, fields, w, form):
+            w(u'<table class="headersform">')
+            for field in fields:
+                if field.name == 'mailbody':
+                    w(u'</table>')
+                    w(u'<div id="toolbar">')
+                    w(u'<ul>')
+                    for button in form.form_buttons:
+                        w(u'<li>%s</li>' % button.render(form))
+                    w(u'</ul>')
+                    w(u'</div>')
+                    w(u'<div>')
+                    w(field.render(form, self))
+                    w(u'</div>')
+                else:
+                    w(u'<tr>')
+                    w(u'<td class="hlabel">%s</td>' %
+                      self.render_label(form, field))
+                    w(u'<td class="hvalue">')
+                    w(field.render(form, self))
+                    w(u'</td></tr>')
+
+        def render_buttons(self, w, form):
+            pass
+
+We simply override the `_render_fields` and `render_buttons` method of the base form renderer
+to arrange fields as we desire it: here we'll have first a two columns table with label and
+value of the sender, recipients and subject field (form order respected), then form controls,
+then a div containing the textarea for the email's content.
+
+To bind this renderer to our form, we should add to our form definition above:
+
+.. sourcecode:: python
+
+    form_renderer_id = 'massmailing'
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/edition/form.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,377 @@
+.. _webform:
+
+HTML form construction
+----------------------
+
+CubicWeb provides the somewhat usual form / field / widget / renderer abstraction
+to provide generic building blocks which will greatly help you in building forms
+properly integrated with CubicWeb (coherent display, error handling, etc...),
+while keeping things as flexible as possible.
+
+A ``form`` basically only holds a set of ``fields``, and has te be bound to a
+``renderer`` which is responsible to layout them. Each field is bound to a
+``widget`` that will be used to fill in value(s) for that field (at form
+generation time) and 'decode' (fetch and give a proper Python type to) values
+sent back by the browser.
+
+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
+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.
+
+Exploring the available forms
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A small excursion into a |cubicweb| shell is the quickest way to
+discover available forms (or application objects in general).
+
+.. sourcecode:: python
+
+ >>> from pprint import pprint
+ >>> pprint( session.vreg['forms'] )
+ {'base': [<class 'cubicweb.web.views.forms.FieldsForm'>,
+           <class 'cubicweb.web.views.forms.EntityFieldsForm'>],
+  'changestate': [<class 'cubicweb.web.views.workflow.ChangeStateForm'>,
+                  <class 'cubes.tracker.views.forms.VersionChangeStateForm'>],
+  'composite': [<class 'cubicweb.web.views.forms.CompositeForm'>,
+                <class 'cubicweb.web.views.forms.CompositeEntityForm'>],
+  'deleteconf': [<class 'cubicweb.web.views.editforms.DeleteConfForm'>],
+  'edition': [<class 'cubicweb.web.views.autoform.AutomaticEntityForm'>,
+              <class 'cubicweb.web.views.workflow.TransitionEditionForm'>,
+              <class 'cubicweb.web.views.workflow.StateEditionForm'>],
+  'logform': [<class 'cubicweb.web.views.basetemplates.LogForm'>],
+  'massmailing': [<class 'cubicweb.web.views.massmailing.MassMailingForm'>],
+  'muledit': [<class 'cubicweb.web.views.editforms.TableEditForm'>],
+  'sparql': [<class 'cubicweb.web.views.sparql.SparqlForm'>]}
+
+
+The two most important form families here (for all practical purposes) are `base`
+and `edition`. Most of the time one wants alterations of the
+:class:`AutomaticEntityForm` to generate custom forms to handle edition of an
+entity.
+
+The Automatic Entity Form
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. automodule:: cubicweb.web.views.autoform
+
+Anatomy of a choices function
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Let's have a look at the `ticket_done_in_choices` function given to
+the `choices` parameter of the relation tag that is applied to the
+('Ticket', 'done_in', '*') relation definition, as it is both typical
+and sophisticated enough. This is a code snippet from the `tracker`_
+cube.
+
+.. _`tracker`: http://www.cubicweb.org/project/cubicweb-tracker
+
+The ``Ticket`` entity type can be related to a ``Project`` and a
+``Version``, respectively through the ``concerns`` and ``done_in``
+relations. When a user is about to edit a ticket, we want to fill the
+combo box for the ``done_in`` relation with values pertinent with
+respect to the context. The important context here is:
+
+* creation or modification (we cannot fetch values the same way in
+  either case)
+
+* ``__linkto`` url parameter given in a creation context
+
+.. sourcecode:: python
+
+    from cubicweb.web import formfields
+
+    def ticket_done_in_choices(form, field):
+        entity = form.edited_entity
+        # first see if its specified by __linkto form parameters
+        linkedto = form.linked_to[('done_in', 'subject')]
+        if linkedto:
+            return linkedto
+        # it isn't, get initial values
+        vocab = field.relvoc_init(form)
+        veid = None
+        # try to fetch the (already or pending) related version and project
+        if not entity.has_eid():
+            peids = form.linked_to[('concerns', 'subject')]
+            peid = peids and peids[0]
+        else:
+            peid = entity.project.eid
+            veid = entity.done_in and entity.done_in[0].eid
+        if peid:
+            # we can complete the vocabulary with relevant values
+            rschema = form._cw.vreg.schema['done_in'].rdef('Ticket', 'Version')
+            rset = form._cw.execute(
+                'Any V, VN ORDERBY version_sort_value(VN) '
+                'WHERE V version_of P, P eid %(p)s, V num VN, '
+                'V in_state ST, NOT ST name "published"', {'p': peid}, 'p')
+            vocab += [(v.view('combobox'), v.eid) for v in rset.entities()
+                      if rschema.has_perm(form._cw, 'add', toeid=v.eid)
+                      and v.eid != veid]
+        return vocab
+
+The first thing we have to do is fetch potential values from the ``__linkto`` url
+parameter that is often found in entity creation contexts (the creation action
+provides such a parameter with a predetermined value; for instance in this case,
+ticket creation could occur in the context of a `Version` entity). The
+:class:`~cubicweb.web.formfields.RelationField` field class provides a
+:meth:`~cubicweb.web.formfields.RelationField.relvoc_linkedto` method that gets a
+list suitably filled with vocabulary values.
+
+.. sourcecode:: python
+
+        linkedto = field.relvoc_linkedto(form)
+        if linkedto:
+            return linkedto
+
+Then, if no ``__linkto`` argument was given, we must prepare the vocabulary with
+an initial empty value (because `done_in` is not mandatory, we must allow the
+user to not select a verson) and already linked values. This is done with the
+:meth:`~cubicweb.web.formfields.RelationField.relvoc_init` method.
+
+.. sourcecode:: python
+
+        vocab = field.relvoc_init(form)
+
+But then, we have to give more: if the ticket is related to a project,
+we should provide all the non published versions of this project
+(`Version` and `Project` can be related through the `version_of`
+relation). Conversely, if we do not know yet the project, it would not
+make sense to propose all existing versions as it could potentially
+lead to incoherences. Even if these will be caught by some
+RQLConstraint, it is wise not to tempt the user with error-inducing
+candidate values.
+
+The "ticket is related to a project" part must be decomposed as:
+
+* this is a new ticket which is created is the context of a project
+
+* this is an already existing ticket, linked to a project (through the
+  `concerns` relation)
+
+* there is no related project (quite unlikely given the cardinality of
+  the `concerns` relation, so it can only mean that we are creating a
+  new ticket, and a project is about to be selected but there is no
+  ``__linkto`` argument)
+
+.. note::
+
+   the last situation could happen in several ways, but of course in a
+   polished application, the paths to ticket creation should be
+   controlled so as to avoid a suboptimal end-user experience
+
+Hence, we try to fetch the related project.
+
+.. sourcecode:: python
+
+        veid = None
+        if not entity.has_eid():
+            peids = form.linked_to[('concerns', 'subject')]
+            peid = peids and peids[0]
+        else:
+            peid = entity.project.eid
+            veid = entity.done_in and entity.done_in[0].eid
+
+We distinguish between entity creation and entity modification using
+the ``Entity.has_eid()`` method, which returns `False` on creation. At
+creation time the only way to get a project is through the
+``__linkto`` parameter. Notice that we fetch the version in which the
+ticket is `done_in` if any, for later.
+
+.. note::
+
+  the implementation above assumes that if there is a ``__linkto``
+  parameter, it is only about a project. While it makes sense most of
+  the time, it is not an absolute. Depending on how an entity creation
+  action action url is built, several outcomes could be possible
+  there
+
+If the ticket is already linked to a project, fetching it is
+trivial. Then we add the relevant version to the initial vocabulary.
+
+.. sourcecode:: python
+
+        if peid:
+            rschema = form._cw.vreg.schema['done_in'].rdef('Ticket', 'Version')
+            rset = form._cw.execute(
+                'Any V, VN ORDERBY version_sort_value(VN) '
+                'WHERE V version_of P, P eid %(p)s, V num VN, '
+                'V in_state ST, NOT ST name "published"', {'p': peid})
+            vocab += [(v.view('combobox'), v.eid) for v in rset.entities()
+                      if rschema.has_perm(form._cw, 'add', toeid=v.eid)
+                      and v.eid != veid]
+
+.. warning::
+
+   we have to defend ourselves against lack of a project eid. Given
+   the cardinality of the `concerns` relation, there *must* be a
+   project, but this rule can only be enforced at validation time,
+   which will happen of course only after form subsmission
+
+Here, given a project eid, we complete the vocabulary with all
+unpublished versions defined in the project (sorted by number) for
+which the current user is allowed to establish the relation.
+
+
+Building self-posted form with custom fields/widgets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes you want a form that is not related to entity edition. For those,
+you'll have to handle form posting by yourself. Here is a complete example on how
+to achieve this (and more).
+
+Imagine you want a form that selects a month period. There are no proper
+field/widget to handle this in CubicWeb, so let's start by defining them:
+
+.. sourcecode:: python
+
+    # let's have the whole import list at the beginning, even those necessary for
+    # subsequent snippets
+    from logilab.common import date
+    from logilab.mtconverter import xml_escape
+    from cubicweb.view import View
+    from cubicweb.predicates import match_kwargs
+    from cubicweb.web import RequestError, ProcessFormError
+    from cubicweb.web import formfields as fields, formwidgets as wdgs
+    from cubicweb.web.views import forms, calendar
+
+    class MonthSelect(wdgs.Select):
+        """Custom widget to display month and year. Expect value to be given as a
+        date instance.
+        """
+
+        def format_value(self, form, field, value):
+            return u'%s/%s' % (value.year, value.month)
+
+        def process_field_data(self, form, field):
+            val = super(MonthSelect, self).process_field_data(form, field)
+            try:
+                year, month = val.split('/')
+                year = int(year)
+                month = int(month)
+                return date.date(year, month, 1)
+            except ValueError:
+                raise ProcessFormError(
+                    form._cw._('badly formated date string %s') % val)
+
+
+    class MonthPeriodField(fields.CompoundField):
+        """custom field composed of two subfields, 'begin_month' and 'end_month'.
+
+        It expects to be used on form that has 'mindate' and 'maxdate' in its
+        extra arguments, telling the range of month to display.
+        """
+
+        def __init__(self, *args, **kwargs):
+            kwargs.setdefault('widget', wdgs.IntervalWidget())
+            super(MonthPeriodField, self).__init__(
+                [fields.StringField(name='begin_month',
+                                    choices=self.get_range, sort=False,
+                                    value=self.get_mindate,
+                                    widget=MonthSelect()),
+                 fields.StringField(name='end_month',
+                                    choices=self.get_range, sort=False,
+                                    value=self.get_maxdate,
+                                    widget=MonthSelect())], *args, **kwargs)
+
+        @staticmethod
+        def get_range(form, field):
+            mindate = date.todate(form.cw_extra_kwargs['mindate'])
+            maxdate = date.todate(form.cw_extra_kwargs['maxdate'])
+            assert mindate <= maxdate
+            _ = form._cw._
+            months = []
+            while mindate <= maxdate:
+                label = '%s %s' % (_(calendar.MONTHNAMES[mindate.month - 1]),
+                                   mindate.year)
+                value = field.widget.format_value(form, field, mindate)
+                months.append( (label, value) )
+                mindate = date.next_month(mindate)
+            return months
+
+        @staticmethod
+        def get_mindate(form, field):
+            return form.cw_extra_kwargs['mindate']
+
+        @staticmethod
+        def get_maxdate(form, field):
+            return form.cw_extra_kwargs['maxdate']
+
+        def process_posted(self, form):
+            for field, value in super(MonthPeriodField, self).process_posted(form):
+                if field.name == 'end_month':
+                    value = date.last_day(value)
+                yield field, value
+
+
+Here we first define a widget that will be used to select the beginning and the
+end of the period, displaying months like '<month> YYYY' but using 'YYYY/mm' as
+actual value.
+
+We then define a field that will actually hold two fields, one for the beginning
+and another for the end of the period. Each subfield uses the widget we defined
+earlier, and the outer field itself uses the standard
+:class:`IntervalWidget`. The field adds some logic:
+
+* a vocabulary generation function `get_range`, used to populate each sub-field
+
+* two 'value' functions `get_mindate` and `get_maxdate`, used to tell to
+  subfields which value they should consider on form initialization
+
+* overriding of `process_posted`, called when the form is being posted, so that
+  the end of the period is properly set to the last day of the month.
+
+Now, we can define a very simple form:
+
+.. sourcecode:: python
+
+    class MonthPeriodSelectorForm(forms.FieldsForm):
+        __regid__ = 'myform'
+        __select__ = match_kwargs('mindate', 'maxdate')
+
+        form_buttons = [wdgs.SubmitButton()]
+        form_renderer_id = 'onerowtable'
+        period = MonthPeriodField()
+
+
+where we simply add our field, set a submit button and use a very simple renderer
+(try others!). Also we specify a selector that ensures form will have arguments
+necessary to our field.
+
+Now, we need a view that will wrap the form and handle post when it occurs,
+simply displaying posted values in the page:
+
+.. sourcecode:: python
+
+    class SelfPostingForm(View):
+        __regid__ = 'myformview'
+
+        def call(self):
+            mindate, maxdate = date.date(2010, 1, 1), date.date(2012, 1, 1)
+            form = self._cw.vreg['forms'].select(
+                'myform', self._cw, mindate=mindate, maxdate=maxdate, action='')
+            try:
+                posted = form.process_posted()
+                self.w(u'<p>posted values %s</p>' % xml_escape(repr(posted)))
+            except RequestError: # no specified period asked
+                pass
+            form.render(w=self.w, formvalues=self._cw.form)
+
+
+Notice usage of the :meth:`process_posted` method, that will return a dictionary
+of typed values (because they have been processed by the field). In our case, when
+the form is posted you should see a dictionary with 'begin_month' and 'end_month'
+as keys with the selected dates as value (as a python `date` object).
+
+
+APIs
+~~~~
+
+.. automodule:: cubicweb.web.formfields
+.. automodule:: cubicweb.web.formwidgets
+.. automodule:: cubicweb.web.views.forms
+.. automodule:: cubicweb.web.views.formrenderers
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/edition/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,15 @@
+Edition control
+===============
+
+This chapter covers the editing capabilities of |cubicweb|. It
+explains html Form construction, the Edit Controller and their
+interactions.
+
+
+.. toctree::
+   :maxdepth: 2
+
+   form
+   dissection
+   editcontroller
+   examples
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/facets.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,23 @@
+The facets system
+-----------------
+
+Facets allow to restrict searches according to some user friendly criterias.
+CubicWeb has a builtin `facet`_ system to define restrictions `filters`_ really
+as easily as possible.
+
+Here is an exemple of the facets rendering picked from our
+http://www.cubicweb.org web site:
+
+.. image:: ../images/facet_overview.png
+
+Facets will appear on each page presenting more than one entity that may be
+filtered according to some known criteria.
+
+Base classes for facets
+~~~~~~~~~~~~~~~~~~~~~~~
+.. automodule:: cubicweb.web.facet
+
+
+.. _facet: http://en.wikipedia.org/wiki/Faceted_browser
+.. _filters: http://www.cubicweb.org/blogentry/154152
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/httpcaching.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,21 @@
+HTTP cache management
+=====================
+
+.. automodule:: cubicweb.web.httpcache
+
+Cache policies
+--------------
+.. autoclass:: cubicweb.web.httpcache.NoHTTPCacheManager
+.. autoclass:: cubicweb.web.httpcache.MaxAgeHTTPCacheManager
+.. autoclass:: cubicweb.web.httpcache.EtagHTTPCacheManager
+.. autoclass:: cubicweb.web.httpcache.EntityHTTPCacheManager
+
+Exception
+---------
+.. autoexception:: cubicweb.web.httpcache.NoEtag
+
+Helper functions
+----------------
+.. autofunction:: cubicweb.web.httpcache.set_http_cache_headers
+
+.. NOT YET AVAILABLE IN STABLE autofunction:: cubicweb.web.httpcache.lastmodified
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,24 @@
+Web side development
+====================
+
+In this chapter, we will describe the core APIs for web development in
+the *CubicWeb* framework.
+
+.. toctree::
+   :maxdepth: 2
+
+   publisher
+   controllers
+   request
+   searchbar
+   views/index
+   rtags
+   ajax
+   js
+   css
+   edition/index
+   facets
+   internationalization
+   property
+   httpcaching
+   resource
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/internationalization.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,229 @@
+.. -*- coding: utf-8 -*-
+
+.. _internationalization:
+
+Internationalization
+---------------------
+
+Cubicweb fully supports the internalization of its content and interface.
+
+Cubicweb's interface internationalization is based on the translation project `GNU gettext`_.
+
+.. _`GNU gettext`: http://www.gnu.org/software/gettext/
+
+Cubicweb' internalization involves two steps:
+
+* in your Python code and cubicweb-tal templates : mark translatable strings
+
+* in your instance : handle the translation catalog, edit translations
+
+String internationalization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+User defined string
+```````````````````
+
+In the Python code and cubicweb-tal templates translatable strings can be
+marked in one of the following ways :
+
+ * by using the *built-in* function `_`:
+
+   .. sourcecode:: python
+
+     class PrimaryView(EntityView):
+         """the full view of an non final entity"""
+         __regid__ = 'primary'
+         title = _('primary')
+
+  OR
+
+ * by using the equivalent request's method:
+
+   .. sourcecode:: python
+
+     class NoResultView(View):
+         """default view when no result has been found"""
+         __regid__ = 'noresult'
+
+         def call(self, **kwargs):
+             self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
+                 % self._cw._('No result matching query'))
+
+The goal of the *built-in* function `_` is only **to mark the
+translatable strings**, it will only return the string to translate
+itself, but not its translation (it's actually another name for the
+`unicode` builtin).
+
+In the other hand the request's method `self._cw._` is also meant to
+retrieve the proper translation of translation strings in the
+requested language.
+
+Finally you can also use the `__` attribute of request object to get a
+translation for a string *which should not itself added to the catalog*,
+usually in case where the actual msgid is created by string interpolation ::
+
+  self._cw.__('This %s' % etype)
+
+In this example ._cw.__` is used instead of ._cw._` so we don't have 'This %s' in
+messages catalogs.
+
+Translations in cubicweb-tal template can also be done with TAL tags
+`i18n:content` and `i18n:replace`.
+
+If you need to add messages on top of those that can be found in the source,
+you can create a file named `i18n/static-messages.pot`.
+
+You could put there messages not found in the python sources or
+overrides for some messages of used cubes.
+
+Generated string
+````````````````
+
+We do not need to mark the translation strings of entities/relations used by a
+particular instance's schema as they are generated automatically. String for
+various actions are also generated.
+
+For exemple the following schema:
+
+.. sourcecode:: python
+
+
+  class EntityA(EntityType):
+      relation_a2b = SubjectRelation('EntityB')
+
+  class EntityB(EntityType):
+      pass
+
+May generate the following message ::
+
+  add EntityA relation_a2b EntityB subject
+
+This message will be used in views of ``EntityA`` for creation of a new
+``EntityB`` with a preset relation ``relation_a2b`` between the current
+``EntityA`` and the new ``EntityB``. The opposite message ::
+
+  add EntityA relation_a2b EntityB object
+
+Is used for similar creation of an ``EntityA`` from a view of ``EntityB``. The
+title of they respective creation form will be ::
+
+  creating EntityB (EntityA %(linkto)s relation_a2b EntityB)
+
+  creating EntityA (EntityA relation_a2b %(linkto)s EntityA)
+
+In the translated string you can use ``%(linkto)s`` for reference to the source
+``entity``.
+
+Handling the translation catalog
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once the internationalization is done in your code, you need to populate and
+update the translation catalog. Cubicweb provides the following commands for this
+purpose:
+
+
+* `i18ncubicweb` updates Cubicweb framework's translation
+  catalogs. Unless you actually work on the framework itself, you
+  don't need to use this command.
+
+* `i18ncube` updates the translation catalogs of *one particular cube*
+  (or of all cubes). After this command is executed you must update
+  the translation files *.po* in the "i18n" directory of your
+  cube. This command will of course not remove existing translations
+  still in use. It will mark unused translation but not remove them.
+
+* `i18ninstance` recompiles the translation catalogs of *one particular
+  instance* (or of all instances) after the translation catalogs of
+  its cubes have been updated. This command is automatically
+  called every time you create or update your instance. The compiled
+  catalogs (*.mo*) are stored in the i18n/<lang>/LC_MESSAGES of
+  instance where `lang` is the language identifier ('en' or 'fr'
+  for exemple).
+
+
+Example
+```````
+
+You have added and/or modified some translation strings in your cube
+(after creating a new view or modifying the cube's schema for exemple).
+To update the translation catalogs you need to do:
+
+1. `cubicweb-ctl i18ncube <cube>`
+2. Edit the <cube>/i18n/xxx.po  files and add missing translations (empty `msgstr`)
+3. `hg ci -m "updated i18n catalogs"`
+4. `cubicweb-ctl i18ninstance <myinstance>`
+
+Editing po files
+~~~~~~~~~~~~~~~~
+
+Using a PO aware editor
+````````````````````````
+
+Many tools exist to help maintain .po (PO) files. Common editors or
+development environment provides modes for these. One can also find
+dedicated PO files editor, such as `poedit`_.
+
+.. _`poedit`:  http://www.poedit.net/
+
+While usage of such a tool is commendable, PO files are perfectly
+editable with a (unicode aware) plain text editor. It is also useful
+to know their structure for troubleshooting purposes.
+
+Structure of a PO file
+``````````````````````
+
+In this section, we selectively quote passages of the `GNU gettext`_
+manual chapter on PO files, available there::
+
+ http://www.gnu.org/software/hello/manual/gettext/PO-Files.html
+
+One PO file entry has the following schematic structure::
+
+     white-space
+     #  translator-comments
+     #. extracted-comments
+     #: reference...
+     #, flag...
+     #| msgid previous-untranslated-string
+     msgid untranslated-string
+     msgstr translated-string
+
+
+A simple entry can look like this::
+
+     #: lib/error.c:116
+     msgid "Unknown system error"
+     msgstr "Error desconegut del sistema"
+
+It is also possible to have entries with a context specifier. They
+look like this::
+
+     white-space
+     #  translator-comments
+     #. extracted-comments
+     #: reference...
+     #, flag...
+     #| msgctxt previous-context
+     #| msgid previous-untranslated-string
+     msgctxt context
+     msgid untranslated-string
+     msgstr translated-string
+
+
+The context serves to disambiguate messages with the same
+untranslated-string. It is possible to have several entries with the
+same untranslated-string in a PO file, provided that they each have a
+different context. Note that an empty context string and an absent
+msgctxt line do not mean the same thing.
+
+Contexts and CubicWeb
+`````````````````````
+
+CubicWeb PO files have both non-contextual and contextual msgids.
+
+Contextual entries are automatically used in some cases. For instance,
+entity.dc_type(), eschema.display_name(req) or display_name(etype,
+req, form, context) methods/function calls will use them.
+
+It is also possible to explicitly use the with _cw.pgettext(context,
+msgid).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/js.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,394 @@
+.. -*- coding: utf-8 -*-
+
+Javascript
+----------
+
+*CubicWeb* uses quite a bit of javascript in its user interface and
+ships with jquery (1.3.x) and parts of the jquery UI library, plus a
+number of homegrown files and also other third party libraries.
+
+All javascript files are stored in cubicweb/web/data/. There are
+around thirty js files there. In a cube it goes to data/.
+
+Obviously one does not want javascript pieces to be loaded all at
+once, hence the framework provides a number of mechanisms and
+conventions to deal with javascript resources.
+
+Conventions
+~~~~~~~~~~~
+
+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)
+
+Server-side Javascript API
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Javascript resources are typically loaded on demand, from views. The
+request object (available as self._cw from most application objects,
+for instance views and entities objects) has a few methods to do that:
+
+* `add_js(self, jsfiles, localfile=True)` which takes a sequence of
+  javascript files and writes proper entries into the HTML header
+  section. The localfile parameter allows to declare resources which
+  are not from web/data (for instance, residing on a content delivery
+  network).
+
+* `add_onload(self, jscode)` which adds one raw javascript code
+  snippet inline in the html headers. This is quite useful for setting
+  up early jQuery(document).ready(...) initialisations.
+
+Javascript events
+~~~~~~~~~~~~~~~~~
+
+* ``server-response``: this event is triggered on HTTP responses (both
+  standard and ajax). The two following extra parameters are passed
+  to callbacks :
+
+  - ``ajax``: a boolean that says if the reponse was issued by an
+    ajax request
+
+  - ``node``: the DOM node returned by the server in case of an
+    ajax request, otherwise the document itself for standard HTTP
+    requests.
+
+Important javascript AJAX APIS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* `asyncRemoteExec` and `remoteExec` are the base building blocks for
+  doing arbitrary async (resp. sync) communications with the server
+
+* `reloadComponent` is a convenience function to replace a DOM node
+  with server supplied content coming from a specific registry (this
+  is quite handy to refresh the content of some boxes for instances)
+
+* `jQuery.fn.loadxhtml` is an important extension to jQuery which
+  allows proper loading and in-place DOM update of xhtml views. It is
+  suitably augmented to trigger necessary events, and process CubicWeb
+  specific elements such as the facet system, fckeditor, etc.
+
+
+A simple example with asyncRemoteExec
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On the python side, we have to define an
+:class:`cubicweb.web.views.ajaxcontroller.AjaxFunction` object. The
+simplest way to do that is to use the
+:func:`cubicweb.web.views.ajaxcontroller.ajaxfunc` decorator (for more
+details on this, refer to :ref:`ajax`).
+
+.. sourcecode: python
+
+    from cubicweb.web.views.ajaxcontroller import ajaxfunc
+
+    # serialize output to json to get it back easily on the javascript side
+    @ajaxfunc(output_type='json')
+    def js_say_hello(self, name):
+        return u'hello %s' % name
+
+On the javascript side, we do the asynchronous call. Notice how it
+creates a `deferred` object. Proper treatment of the return value or
+error handling has to be done through the addCallback and addErrback
+methods.
+
+.. sourcecode: javascript
+
+    function asyncHello(name) {
+        var deferred = asyncRemoteExec('say_hello', name);
+        deferred.addCallback(function (response) {
+            alert(response);
+        });
+        deferred.addErrback(function (error) {
+            alert('something fishy happened');
+        });
+     }
+
+     function syncHello(name) {
+         alert( remoteExec('say_hello', name) );
+     }
+
+Anatomy of a reloadComponent call
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`reloadComponent` allows to dynamically replace some DOM node with new
+elements. It has the following signature:
+
+* `compid` (mandatory) is the name of the component to be reloaded
+
+* `rql` (optional) will be used to generate a result set given as
+  argument to the selected component
+
+* `registry` (optional) defaults to 'components' but can be any other
+  valid registry name
+
+* `nodeid` (optional) defaults to compid + 'Component' but can be any
+  explicitly specified DOM node id
+
+* `extraargs` (optional) should be a dictionary of values that will be
+  given to the cell_call method of the component
+
+A simple reloadComponent example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The server side implementation of `reloadComponent` is the
+:func:`cubicweb.web.views.ajaxcontroller.component` *AjaxFunction* appobject.
+
+The following function implements a two-steps method to delete a
+standard bookmark and refresh the UI, while keeping the UI responsive.
+
+.. sourcecode:: javascript
+
+    function removeBookmark(beid) {
+        d = asyncRemoteExec('delete_bookmark', beid);
+        d.addCallback(function(boxcontent) {
+	    reloadComponent('bookmarks_box', '', 'boxes', 'bookmarks_box');
+            document.location.hash = '#header';
+            updateMessage(_("bookmark has been removed"));
+         });
+    }
+
+`reloadComponent` is called with the id of the bookmark box as
+argument, no rql expression (because the bookmarks display is actually
+independant of any dataset context), a reference to the 'boxes'
+registry (which hosts all left, right and contextual boxes) and
+finally an explicit 'bookmarks_box' nodeid argument that stipulates
+the target DOM node.
+
+Anatomy of a loadxhtml call
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`jQuery.fn.loadxhtml` is an important extension to jQuery which allows
+proper loading and in-place DOM update of xhtml views. The existing
+`jQuery.load`_ function does not handle xhtml, hence the addition. The
+API of loadxhtml is roughly similar to that of `jQuery.load`_.
+
+.. _`jQuery.load`: http://api.jquery.com/load/
+
+
+* `url` (mandatory) should be a complete url (typically referencing
+  the :class:`cubicweb.web.views.ajaxcontroller.AjaxController`,
+  but this is not strictly mandatory)
+
+* `data` (optional) is a dictionary of values given to the
+  controller specified through an `url` argument; some keys may have a
+  special meaning depending on the choosen controller (such as `fname`
+  for the JSonController); the `callback` key, if present, must refer
+  to a function to be called at the end of loadxhtml (more on this
+  below)
+
+* `reqtype` (optional) specifies the request method to be used (get or
+  post); if the argument is 'post', then the post method is used,
+  otherwise the get method is used
+
+* `mode` (optional) is one of `replace` (the default) which means the
+  loaded node will replace the current node content, `swap` to replace
+  the current node with the loaded node, and `append` which will
+  append the loaded node to the current node content
+
+About the `callback` option:
+
+* it is called with two parameters: the current node, and a list
+  containing the loaded (and post-processed node)
+
+* whenever it returns another function, this function is called in
+  turn with the same parameters as above
+
+This mechanism allows callback chaining.
+
+
+A simple example with loadxhtml
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here we are concerned with the retrieval of a specific view to be
+injected in the live DOM. The view will be of course selected
+server-side using an entity eid provided by the client side.
+
+.. sourcecode:: python
+
+    from cubicweb.web.views.ajaxcontroller import ajaxfunc
+
+    @ajaxfunc(output_type='xhtml')
+    def frob_status(self, eid, frobname):
+        entity = self._cw.entity_from_eid(eid)
+        return entity.view('frob', name=frobname)
+
+.. sourcecode:: javascript
+
+    function updateSomeDiv(divid, eid, frobname) {
+        var params = {fname:'frob_status', eid: eid, frobname:frobname};
+        jQuery('#'+divid).loadxhtml(JSON_BASE_URL, params, 'post');
+     }
+
+In this example, the url argument is the base json url of a cube
+instance (it should contain something like
+`http://myinstance/ajax?`). The actual AjaxController method name is
+encoded in the `params` dictionary using the `fname` key.
+
+A more real-life example
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+A frequent need of Web 2 applications is the delayed (or demand
+driven) loading of pieces of the DOM. This is typically achieved using
+some preparation of the initial DOM nodes, jQuery event handling and
+proper use of loadxhtml.
+
+We present here a skeletal version of the mecanism used in CubicWeb
+and available in web/views/tabs.py, in the `LazyViewMixin` class.
+
+.. sourcecode:: python
+
+    def lazyview(self, vid, rql=None):
+        """ a lazy version of wview """
+        w = self.w
+        self._cw.add_js('cubicweb.lazy.js')
+        urlparams = {'vid' : vid, 'fname' : 'view'}
+        if rql is not None:
+            urlparams['rql'] = rql
+        w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % (
+            vid, xml_escape(self._cw.build_url('json', **urlparams))))
+        w(u'</div>')
+        self._cw.add_onload(u"""
+            jQuery('#lazy-%(vid)s').bind('%(event)s', function() {
+                   loadNow('#lazy-%(vid)s');});"""
+            % {'event': 'load_%s' % vid, 'vid': vid})
+
+This creates a `div` with a specific event associated to it.
+
+The full version deals with:
+
+* optional parameters such as an entity eid, an rset
+
+* the ability to further reload the fragment
+
+* the ability to display a spinning wheel while the fragment is still
+  not loaded
+
+* handling of browsers that do not support ajax (search engines,
+  text-based browsers such as lynx, etc.)
+
+The javascript side is quite simple, due to loadxhtml awesomeness.
+
+.. sourcecode:: javascript
+
+    function loadNow(eltsel) {
+        var lazydiv = jQuery(eltsel);
+        lazydiv.loadxhtml(lazydiv.attr('cubicweb:loadurl'));
+    }
+
+This is all significantly different of the previous `simple example`
+(albeit this example actually comes from real-life code).
+
+Notice how the `cubicweb:loadurl` is used to convey the url
+information. The base of this url is similar to the global javascript
+JSON_BASE_URL. According to the pattern described earlier,
+the `fname` parameter refers to the standard `js_view` method of the
+JSonController. This method renders an arbitrary view provided a view
+id (or `vid`) is provided, and most likely an rql expression yielding
+a result set against which a proper view instance will be selected.
+
+The `cubicweb:loadurl` is one of the 29 attributes extensions to XHTML
+in a specific cubicweb namespace. It is a means to pass information
+without breaking HTML nor XHTML compliance and without resorting to
+ungodly hacks.
+
+Given all this, it is easy to add a small nevertheless useful feature
+to force the loading of a lazy view (for instance, a very
+computation-intensive web page could be scinded into one fast-loading
+part and a delayed part).
+
+On the server side, a simple call to a javascript function is
+sufficient.
+
+.. sourcecode:: python
+
+    def forceview(self, vid):
+        """trigger an event that will force immediate loading of the view
+        on dom readyness
+        """
+        self._cw.add_onload("triggerLoad('%s');" % vid)
+
+The browser-side definition follows.
+
+.. sourcecode:: javascript
+
+    function triggerLoad(divid) {
+        jQuery('#lazy-' + divd).trigger('load_' + divid);
+    }
+
+
+Javascript library: overview
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* jquery.* : jquery and jquery UI library
+
+* cubicweb.ajax.js : concentrates all ajax related facilities (it
+  extends jQuery with the loahxhtml function, provides a handfull of
+  high-level ajaxy operations like asyncRemoteExec, reloadComponent,
+  replacePageChunk, getDomFromResponse)
+
+* cubicweb.python.js : adds a number of practical extension to stdanrd
+  javascript objects (on Date, Array, String, some list and dictionary
+  operations), and a pythonesque way to build classes. Defines a
+  CubicWeb namespace.
+
+* cubicweb.htmlhelpers.js : a small bag of convenience functions used
+  in various other cubicweb javascript resources (baseuri, progress
+  cursor handling, popup login box, html2dom function, etc.)
+
+* cubicweb.widgets.js : provides a widget namespace and constructors
+  and helpers for various widgets (mainly facets and timeline)
+
+* cubicweb.edition.js : used by edition forms
+
+* cubicweb.preferences.js : used by the preference form
+
+* cubicweb.facets.js : used by the facets mechanism
+
+There is also javascript support for massmailing, gmap (google maps),
+fckcwconfig (fck editor), timeline, calendar, goa (CubicWeb over
+AppEngine), flot (charts drawing), tabs and bookmarks.
+
+API
+~~~
+
+.. toctree::
+    :maxdepth: 1
+
+    js_api/index
+
+
+Testing javascript
+~~~~~~~~~~~~~~~~~~
+
+You with the ``cubicweb.qunit.QUnitTestCase`` can include standard Qunit tests
+inside the python unittest run . You simply have to define a new class that
+inherit from ``QUnitTestCase`` and register your javascript test file in the
+``all_js_tests`` lclass attribut. This  ``all_js_tests`` is a sequence a
+3-tuple (<test_file, [<dependencies> ,] [<data_files>]):
+
+The <test_file> should contains the qunit test. <dependencies> defines the list
+of javascript file that must be imported before the test script.  Dependencies
+are included their definition order. <data_files> are additional files copied in the
+test directory. both <dependencies> and <data_files> are optionnal.
+``jquery.js`` is preincluded in for all test.
+
+.. sourcecode:: python
+
+    from cubicweb.qunit import QUnitTestCase
+
+    class MyQUnitTest(QUnitTestCase):
+
+        all_js_tests = (
+            ("relative/path/to/my_simple_testcase.js",)
+            ("relative/path/to/my_qunit_testcase.js",(
+                "rel/path/to/dependency_1.js",
+                "rel/path/to/dependency_2.js",)),
+            ("relative/path/to/my_complexe_qunit_testcase.js",(
+                 "rel/path/to/dependency_1.js",
+                 "rel/path/to/dependency_2.js",
+               ),(
+                 "rel/path/file_dependency.html",
+                 "path/file_dependency.json")
+                ),
+            )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/property.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,15 @@
+.. _cwprops:
+
+The property mecanism
+---------------------
+
+.. XXX CWProperty and co
+
+
+Property API
+~~~~~~~~~~~~
+.. XXX feed me
+
+Registering and using your own property
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. XXX feed me
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/publisher.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,65 @@
+.. _publisher:
+
+Publisher
+---------
+
+What happens when an HTTP request is issued ?
+
+The story begins with the ``CubicWebPublisher.main_publish``
+method. We do not get upper in the bootstrap process because it is
+dependant on the used HTTP library. With `twisted`_ however,
+``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
+  delegated to the `urlpublisher` component)
+
+* the controller is then selected (if not, this is considered an
+  authorization failure and signaled as such) and called
+
+* then either a proper result is returned, in which case the
+  request/connection object issues a ``commit`` and returns the result
+
+* or error handling must happen:
+
+  * ``ValidationErrors`` pop up there and may lead to a redirect to a
+    previously arranged url or standard error handling applies
+  * an HTTP 500 error (`Internal Server Error`) is issued
+
+
+Now, let's turn to the controller. There are many of them in
+:mod:`cubicweb.web.views.basecontrollers`. We can just follow the
+default `view` controller that is selected on a `view` path. See the
+:ref:`controllers` chapter for more information on controllers.
+
+The `View` controller's entry point is the `publish` method. It does
+the following:
+
+* compute the `main` view to be applied, using either the given result
+  set or building one from a user provided rql string (`rql` and `vid`
+  can be forced from the url GET parameters), that is:
+
+    * compute the `vid` using the result set and the schema (see
+      `cubicweb.web.views.vid_from_rset`)
+    * handle all error cases that could happen in this phase
+
+* do some cache management chores
+
+* select a main template (typically `TheMainTemplate`, see chapter
+  :ref:`templates`)
+
+* call it with the result set and the computed view.
+
+What happens next actually depends on the template and the view, but
+in general this is the rendering phase.
+
+
+CubicWebPublisher API
+`````````````````````
+
+.. autoclass:: cubicweb.web.application.CubicWebPublisher
+   :members:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/request.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,131 @@
+The `Request` class (`cubicweb.web.request`)
+--------------------------------------------
+
+Overview
+````````
+
+A request instance is created when an HTTP request is sent to the web
+server.  It contains informations such as form parameters,
+authenticated user, etc. It is a very prevalent object and is used
+throughout all of the framework and applications, as you'll access to
+almost every resources through it.
+
+**A request represents a user query, either through HTTP or not (we
+also talk about RQL queries on the server side for example).**
+
+Here is a non-exhaustive list of attributes and methods available on
+request objects (grouped by category):
+
+* `Browser control`:
+
+  * `ie_browser`: tells if the browser belong to the Internet Explorer
+    family
+
+* `User and identification`:
+
+  * `user`, instance of `cubicweb.entities.authobjs.CWUser` corresponding to the
+    authenticated user
+
+* `Session data handling`
+
+  * `session.data` is the dictionary of the session data; it can be
+    manipulated like an ordinary Python dictionary
+
+* `Edition` (utilities for edition control):
+
+  * `cancel_edition`: resets error url and cleans up pending operations
+  * `create_entity`: utility to create an entity (from an etype,
+    attributes and relation values)
+  * `datadir_url`: returns the url to the merged external resources
+    (|cubicweb|'s `web/data` directory plus all `data` directories of
+    used cubes)
+  * `edited_eids`: returns the list of eids of entities that are
+    edited under the current http request
+  * `eid_rset(eid)`: utility which returns a result set from an eid
+  * `entity_from_eid(eid)`: returns an entity instance from the given eid
+  * `encoding`: returns the encoding of the current HTTP request
+  * `ensure_ro_rql(rql)`: ensure some rql query is a data request
+  * etype_rset
+  * `form`, dictionary containing the values of a web form
+  * `encoding`, character encoding to use in the response
+  * `next_tabindex()`: returns a monotonically growing integer used to
+    build the html tab index of forms
+
+* `HTTP`
+
+  * `authmode`: returns a string describing the authentication mode
+    (http, cookie, ...)
+  * `lang`: returns the user agents/browser's language as carried by
+    the http request
+  * `demote_to_html()`: in the context of an XHTML compliant browser,
+    this will force emission of the response as an HTML document
+    (using the http content negociation)
+
+*  `Cookies handling`
+
+  * `get_cookie()`, returns a dictionary containing the value of the header
+    HTTP 'Cookie'
+  * `set_cookie(cookie, key, maxage=300)`, adds a header HTTP `Set-Cookie`,
+    with a minimal 5 minutes length of duration by default (`maxage` = None
+    returns a *session* cookie which will expire when the user closes the browser
+    window)
+  * `remove_cookie(cookie, key)`, forces a value to expire
+
+* `URL handling`
+
+  * `build_url(__vid, *args, **kwargs)`: return an absolute URL using
+    params dictionary key/values as URL parameters. Values are
+    automatically URL quoted, and the publishing method to use may be
+    specified or will be guessed.
+  * `build_url_params(**kwargs)`: returns a properly prepared (quoted,
+    separators, ...) string from the given parameters
+  * `url()`, returns the full URL of the HTTP request
+  * `base_url()`, returns the root URL of the web application
+  * `relative_path()`, returns the relative path of the request
+
+* `Web resource (.css, .js files, etc.) handling`:
+
+  * `add_css(cssfiles)`: adds the given list of css resources to the current
+    html headers
+  * `add_js(jsfiles)`: adds the given list of javascript resources to the
+    current html headers
+  * `add_onload(jscode)`: inject the given jscode fragment (a unicode
+    string) into the current html headers, wrapped inside a
+    document.ready(...) or another ajax-friendly one-time trigger event
+  * `add_header(header, values)`: adds the header/value pair to the
+    current html headers
+  * `status_out`: control the HTTP status of the response
+
+* `And more...`
+
+  * `set_content_type(content_type, filename=None)`, adds the header HTTP
+    'Content-Type'
+  * `get_header(header)`, returns the value associated to an arbitrary header
+    of the HTTP request
+  * `set_header(header, value)`, adds an arbitrary header in the response
+  * `execute(*args, **kwargs)`, executes an RQL query and return the result set
+  * `property_value(key)`, properties management (`CWProperty`)
+  * dictionary `data` to store data to share informations between components
+    *while a request is executed*
+
+Please note that this class is abstract and that a concrete implementation
+will be provided by the *frontend* web used (in particular *twisted* as of
+today). For the views or others that are executed on the server side,
+most of the interface of `Request` is defined in the session associated
+to the client.
+
+API
+```
+
+The elements we gave in overview for above are built in three layers,
+from ``cubicweb.req.RequestSessionBase``, ``cubicweb.repoapi.Connection`` and
+``cubicweb.web.ConnectionCubicWebRequestBase``.
+
+.. autoclass:: cubicweb.req.RequestSessionBase
+   :members:
+
+.. autoclass:: cubicweb.repoapi.Connection
+   :members:
+
+.. autoclass:: cubicweb.web.request.ConnectionCubicWebRequestBase
+   :members:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/resource.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,18 @@
+.. _resources:
+
+Locate resources
+----------------
+
+.. automethod:: cubicweb.web.webconfig.WebConfiguration.locate_resource
+.. automethod:: cubicweb.web.webconfig.WebConfiguration.locate_doc_file
+.. automethod:: cubicweb.web.webconfig.WebConfiguration.locate_all_files
+
+Static files handling
+---------------------
+
+.. autoattribute:: cubicweb.web.webconfig.WebConfiguration.static_directory
+.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_exists
+.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_open
+.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_add
+.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_del
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/rtags.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,27 @@
+Configuring the user interface
+------------------------------
+
+.. _relation_tags:
+
+Relation tags
+~~~~~~~~~~~~~
+.. automodule:: cubicweb.rtags
+
+.. _uicfg:
+
+The uicfg module
+~~~~~~~~~~~~~~~~
+
+.. note::
+
+ The part of uicfg that deals with primary views is in the
+ :ref:`primary_view_configuration` chapter.
+
+.. automodule:: cubicweb.web.views.uicfg
+
+
+The uihelper module
+~~~~~~~~~~~~~~~~~~~
+
+.. automodule:: cubicweb.web.uihelper
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/searchbar.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,41 @@
+.. _searchbar:
+
+RQL search bar
+--------------
+
+The RQL search bar is a visual component, hidden by default, the tiny *search*
+input being enough for common use cases.
+
+An autocompletion helper is provided to help you type valid queries, both
+in terms of syntax and in terms of schema validity.
+
+.. autoclass:: cubicweb.web.views.magicsearch.RQLSuggestionsBuilder
+
+
+How search is performed
++++++++++++++++++++++++
+
+You can use the *rql search bar* to either type RQL queries, plain text queries
+or standard shortcuts such as *<EntityType>* or *<EntityType> <attrname> <value>*.
+
+Ultimately, all queries are translated to rql since it's the only
+language understood on the server (data) side. To transform the user
+query into RQL, CubicWeb uses the so-called *magicsearch component*,
+defined in :mod:`cubicweb.web.views.magicsearch`, which in turn
+delegates to a number of query preprocessor that are responsible of
+interpreting the user query and generating corresponding RQL.
+
+The code of the main processor loop is easy to understand:
+
+.. sourcecode:: python
+
+  for proc in self.processors:
+      try:
+          return proc.process_query(uquery, req)
+      except (RQLSyntaxError, BadRQLQuery):
+          pass
+
+The idea is simple: for each query processor, try to translate the
+query. If it fails, try with the next processor, if it succeeds,
+we're done and the RQL query will be executed.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/basetemplates.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,161 @@
+.. -*- coding: utf-8 -*-
+
+.. _templates:
+
+Templates
+=========
+
+Templates are the entry point for the |cubicweb| view system. As seen
+in :ref:`views_base_class`, there are two kinds of views: the
+templatable and non-templatable.
+
+
+Non-templatable views
+---------------------
+
+Non-templatable views are standalone. They are responsible for all the details
+such as setting a proper content type (or mime type), the proper document
+headers, namespaces, etc. Examples are pure xml views such as RSS or Semantic Web
+views (`SIOC`_, `DOAP`_, `FOAF`_, `Linked Data`_, etc.), and views which generate
+binary files (pdf, excel files, etc.)
+
+.. _`SIOC`: http://sioc-project.org/
+.. _`DOAP`: http://trac.usefulinc.com/doap
+.. _`FOAF`: http://www.foaf-project.org/
+.. _`Linked Data`: http://linkeddata.org/
+
+
+To notice that a view is not templatable, you just have to set the
+view's class attribute `templatable` to `False`. In this case, it
+should set the `content_type` class attribute to the correct MIME
+type. By default, it is text/xhtml. Additionally, if your view
+generate a binary file, you have to set the view's class attribute
+`binary` to `True` too.
+
+
+Templatable views
+-----------------
+
+Templatable views are not concerned with such pesky details. They
+leave it to the template. Conversely, the template's main job is to:
+
+* set up the proper document header and content type
+* define the general layout of a document
+* invoke adequate views in the various sections of the document
+
+
+Look at :mod:`cubicweb.web.views.basetemplates` and you will find the base
+templates used to generate (X)HTML for your application. The most important
+template there is :class:`~cubicweb.web.views.basetemplates.TheMainTemplate`.
+
+.. _the_main_template_layout:
+
+TheMainTemplate
+~~~~~~~~~~~~~~~
+
+.. _the_main_template_sections:
+
+Layout and sections
+```````````````````
+
+A page is composed as indicated on the schema below :
+
+.. image:: ../../images/main_template.png
+
+The sections dispatches specific views:
+
+* `header`: the rendering of the header is delegated to the
+  `htmlheader` view, whose default implementation can be found in
+  ``basetemplates.py`` and which does the following things:
+
+    * inject the favicon if there is one
+    * inject the global style sheets and javascript resources
+    * call and display a link to an rss component if there is one available
+
+  it also sets up the page title, and fills the actual
+  `header` section with top-level components, using the `header` view, which:
+
+    * tries to display a logo, the name of the application and the `breadcrumbs`
+    * provides a login status area
+    * provides a login box (hiden by default)
+
+* `left column`: this is filled with all selectable boxes matching the
+  `left` context (there is also a right column but nowadays it is
+  seldom used due to bad usability)
+
+* `contentcol`: this is the central column; it is filled with:
+
+    * the `rqlinput` view (hidden by default)
+    * the `applmessages` component
+    * the `contentheader` view which in turns dispatches all available
+      content navigation components having the `navtop` context (this
+      is used to navigate through entities implementing the IPrevNext
+      interface)
+    * the view that was given as input to the template's `call`
+      method, also dealing with pagination concerns
+    * the `contentfooter`
+
+* `footer`: adds all footer actions
+
+.. note::
+
+  How and why a view object is given to the main template is explained
+  in the :ref:`publisher` chapter.
+
+Configure the main template
+```````````````````````````
+
+You can overload some methods of the
+:class:`~cubicweb.web.views.basetemplates.TheMainTemplate`, in order to fulfil
+your needs. There are also some attributes and methods which can be defined on a
+view to modify the base template behaviour:
+
+* `paginable`: if the result set is bigger than a configurable size, your result
+  page will be paginated by default. You can set this attribute to `False` to
+  avoid this.
+
+* `binary`: boolean flag telling if the view generates some text or a binary
+  stream.  Default to False. When view generates text argument given to `self.w`
+  **must be a unicode string**, encoded string otherwise.
+
+* `content_type`, view's content type, default to 'text/xhtml'
+
+* `templatable`, boolean flag telling if the view's content should be returned
+  directly (when `False`) or included in the main template layout (including
+  header, boxes and so on).
+
+* `page_title()`, method that should return a title that will be set as page
+  title in the html headers.
+
+* `html_headers()`, method that should return a list of HTML headers to be
+  included the html headers.
+
+
+You can also modify certain aspects of the main template of a page
+when building a url or setting these parameters in the req.form:
+
+* `__notemplate`, if present (whatever the value assigned), only the content view
+  is returned
+
+* `__force_display`, if present and its value is not null, no pagination whatever
+  the number of entities to display (e.g. similar effect as view's `paginable`
+  attribute described above.
+
+* `__method`, if the result set to render contains only one entity and this
+  parameter is set, it refers to a method to call on the entity by passing it the
+  dictionary of the forms parameters, before going the classic way (through step
+  1 and 2 described juste above)
+
+* `vtitle`, a title to be set as <h1> of the content
+
+Other templates
+~~~~~~~~~~~~~~~
+
+There are also the following other standard templates:
+
+* :class:`cubicweb.web.views.basetemplates.LogInTemplate`
+* :class:`cubicweb.web.views.basetemplates.LogOutTemplate`
+* :class:`cubicweb.web.views.basetemplates.ErrorTemplate` specializes
+  :class:`~cubicweb.web.views.basetemplates.TheMainTemplate` to do
+  proper end-user output if an error occurs during the computation of
+  TheMainTemplate (it is a fallback view).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/baseviews.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,21 @@
+Base views
+----------
+
+|cubicweb| provides a lot of standard views, that can be found in
+:mod:`cubicweb.web.views` sub-modules.
+
+A certain number of views are used to build the web interface, which apply to one
+or more entities. As other appobjects, their identifier is what distinguish them
+from each others. The most generic ones, found in
+:mod:`cubicweb.web.views.baseviews`, are described below.
+
+You'll probably want to customize one or more of the described views which are
+default, generic, implementations.
+
+
+.. automodule:: cubicweb.web.views.baseviews
+
+You will also find modules providing some specific services:
+
+.. automodule:: cubicweb.web.views.navigation
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/boxes.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,36 @@
+Boxes
+-----
+
+(:mod:`cubicweb.web.views.boxes`)
+
+*sidebox*
+  This view displays usually a side box of some related entities
+  in a primary view.
+
+The action box
+~~~~~~~~~~~~~~~
+
+The ``add_related`` is an automatic menu in the action box that allows to create
+an entity automatically related to the initial entity (context in
+which the box is displayed). By default, the links generated in this
+box are computed from the schema properties of the displayed entity,
+but it is possible to explicitly specify them thanks to the
+`cubicweb.web.views.uicfg.rmode` *relation tag*:
+
+* `link`, indicates that a relation is in general created pointing
+  to an existing entity and that we should not to display a link
+  for this relation
+
+* `create`, indicates that a relation is in general created pointing
+  to new entities and that we should display a link to create a new
+  entity and link to it automatically
+
+
+If necessary, it is possible to overwrite the method
+`relation_mode(rtype, targettype, x='subject')` to dynamically
+compute a relation creation category.
+
+Please note that if at least one action belongs to the `addrelated` category,
+the automatic behavior is desactivated in favor of an explicit behavior
+(e.g. display of `addrelated` category actions only).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/breadcrumbs.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,60 @@
+Breadcrumbs
+-----------
+
+Breadcrumbs are a navigation component to help the user locate himself
+along a path of entities.
+
+Display
+~~~~~~~
+
+Breadcrumbs are displayed by default in the header section (see
+:ref:`the_main_template_sections`).  With the default main template,
+the header section is composed by the logo, the application name,
+breadcrumbs and, at the most right, the login box. Breadcrumbs are
+displayed just next to the application name, thus they begin with a
+separator.
+
+Here is the header section of the CubicWeb's forge:
+
+.. image:: ../../images/breadcrumbs_header.png
+
+There are three breadcrumbs components defined in
+:mod:`cubicweb.web.views.ibreadcrumbs`:
+
+- `BreadCrumbEntityVComponent`: displayed for a result set with one line
+  if the entity is adaptable to ``IBreadCrumbsAdapter``.
+- `BreadCrumbETypeVComponent`: displayed for a result set with more than
+  one line, but with all entities of the same type which can adapt to
+  ``IBreadCrumbsAdapter``.
+- `BreadCrumbAnyRSetVComponent`: displayed for any other result set.
+
+Building breadcrumbs
+~~~~~~~~~~~~~~~~~~~~
+
+The ``IBreadCrumbsAdapter`` adapter is defined in the
+:mod:`cubicweb.web.views.ibreadcrumbs` module. It specifies that an
+entity which implements this interface must have a ``breadcrumbs`` and
+a ``parent_entity`` method. A default implementation for each is
+provided. This implementation expoits the ITreeAdapter.
+
+.. note::
+
+   Redefining the breadcrumbs is the hammer way to do it. Another way
+   is to define an `ITreeAdapter` adapter on an entity type. If
+   available, it will be used to compute breadcrumbs.
+
+Here is the API of the ``IBreadCrumbsAdapter`` class:
+
+.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbsAdapter.parent_entity
+.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbsAdapter.breadcrumbs
+
+If the breadcrumbs method return a list of entities, the
+``cubicweb.web.views.ibreadcrumbs.BreadCrumbView`` is used to display
+the elements.
+
+By default, for any entity, if recurs=True, breadcrumbs method returns
+a list of entities, else a list of a simple string.
+
+In order to see a hierarchical breadcrumbs, entities must have a
+``parent`` method which returns the parent entity. By default this
+method doesn't exist on entity, given that it can not be guessed.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/idownloadable.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,22 @@
+The 'download' views
+====================
+
+.. automodule:: cubicweb.web.views.idownloadable
+
+Components
+----------
+
+.. autoclass:: cubicweb.web.views.idownloadable.DownloadBox
+
+Download views
+--------------
+
+.. autoclass:: cubicweb.web.views.idownloadable.DownloadView
+.. autoclass:: cubicweb.web.views.idownloadable.DownloadLinkView
+.. autoclass:: cubicweb.web.views.idownloadable.IDownloadablePrimaryView
+
+Embedded views
+--------------
+
+.. autoclass:: cubicweb.web.views.idownloadable.ImageView
+.. autoclass:: cubicweb.web.views.idownloadable.EHTMLView
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,28 @@
+The View system
+===============
+
+This chapter aims to describe the concept of a `view` used all along
+the development of a web application and how it has been implemented
+in |cubicweb|.
+
+
+.. toctree::
+   :maxdepth: 3
+
+   views
+   basetemplates
+   primary
+   reledit
+   baseviews
+   startup
+   boxes
+   table
+   xmlrss
+   urlpublish
+   breadcrumbs
+   idownloadable
+   wdoc
+
+..   editforms
+..   embedding
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/primary.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,276 @@
+.. _primary_view:
+
+The Primary View
+-----------------
+
+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.
+
+It is automatically selected on a one line result set containing an
+entity.
+
+It lives in the :mod:`cubicweb.web.views.primary` module.
+
+The *primary* view is supposed to render a maximum of informations about the
+entity.
+
+.. _primary_view_layout:
+
+Layout
+``````
+
+The primary view has the following layout.
+
+.. image:: ../../images/primaryview_template.png
+
+.. _primary_view_configuration:
+
+Primary view configuration
+``````````````````````````
+
+If you want to customize the primary view of an entity, overriding the primary
+view class may not be necessary. For simple adjustments (attributes or relations
+display locations and styles), a much simpler way is to use uicfg.
+
+Attributes/relations display location
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In the primary view, there are three sections where attributes and
+relations can be displayed (represented in pink in the image above):
+
+* 'attributes'
+* 'relations'
+* 'sideboxes'
+
+**Attributes** can only be displayed in the attributes section (default
+  behavior). They can also be hidden. By default, attributes of type `Password`
+  and `Bytes` are hidden.
+
+For instance, to hide the ``title`` attribute of the ``Blog`` entity:
+
+.. sourcecode:: python
+
+   from cubicweb.web.views import uicfg
+   uicfg.primaryview_section.tag_attribute(('Blog', 'title'), 'hidden')
+
+**Relations** can be either displayed in one of the three sections or hidden.
+
+For relations, there are two methods:
+
+* ``tag_object_of`` for modifying the primary view of the object
+* ``tag_subject_of`` for modifying the primary view of the subject
+
+These two methods take two arguments:
+
+* a triplet ``(subject, relation_name, object)``, where subject or object can be replaced with ``'*'``
+* the section name or ``hidden``
+
+.. sourcecode:: python
+
+   pv_section = uicfg.primaryview_section
+   # hide every relation `entry_of` in the `Blog` primary view
+   pv_section.tag_object_of(('*', 'entry_of', 'Blog'), 'hidden')
+
+   # display `entry_of` relations in the `relations`
+   # section in the `BlogEntry` primary view
+   pv_section.tag_subject_of(('BlogEntry', 'entry_of', '*'), 'relations')
+
+
+Display content
+^^^^^^^^^^^^^^^
+
+You can use ``primaryview_display_ctrl`` to customize the display of attributes
+or relations. Values of ``primaryview_display_ctrl`` are dictionaries.
+
+
+Common keys for attributes and relations are:
+
+* ``vid``: specifies the regid of the view for displaying the attribute or the relation.
+
+  If ``vid`` is not specified, the default value depends on the section:
+    * ``attributes`` section: 'reledit' view
+    * ``relations`` section: 'autolimited' view
+    * ``sideboxes`` section: 'sidebox' view
+
+* ``order``: int used to control order within a section. When not specified,
+  automatically set according to order in which tags are added.
+
+* ``label``: label for the relations section or side box
+
+* ``showlabel``: boolean telling whether the label is displayed
+
+.. sourcecode:: python
+
+   # let us remind the schema of a blog entry
+   class BlogEntry(EntityType):
+       title = String(required=True, fulltextindexed=True, maxsize=256)
+       publish_date = Date(default='TODAY')
+       content = String(required=True, fulltextindexed=True)
+       entry_of = SubjectRelation('Blog', cardinality='?*')
+
+   # now, we want to show attributes
+   # with an order different from that in the schema definition
+   view_ctrl = uicfg.primaryview_display_ctrl
+   for index, attr in enumerate('title', 'content', 'publish_date'):
+       view_ctrl.tag_attribute(('BlogEntry', attr), {'order': index})
+
+By default, relations displayed in the 'relations' section are being displayed by
+the 'autolimited' view. This view will use comma separated values, or list view
+and/or limit your rset if there is too much items in it (and generate the "view
+all" link in this case).
+
+You can control this view by setting the following values in the
+`primaryview_display_ctrl` relation tag:
+
+* `limit`, maximum number of entities to display. The value of the
+  'navigation.related-limit'  cwproperty is used by default (which is 8 by default).
+  If None, no limit.
+
+* `use_list_limit`, number of entities until which they should be display as a list
+  (eg using the 'list' view). Below that limit, the 'csv' view is used. If None,
+  display using 'csv' anyway.
+
+* `subvid`, the subview identifier (eg view that should be used of each item in the
+  list)
+
+Notice you can also use the `filter` key to set up a callback taking the related
+result set as argument and returning it filtered, to do some arbitrary filtering
+that can't be done using rql for instance.
+
+
+.. sourcecode:: python
+
+   pv_section = uicfg.primaryview_section
+   # in `CWUser` primary view, display `created_by`
+   # relations in relations section
+   pv_section.tag_object_of(('*', 'created_by', 'CWUser'), 'relations')
+
+   # display this relation as a list, sets the label,
+   # limit the number of results and filters on comments
+   def filter_comment(rset):
+       return rset.filtered_rset(lambda x: x.e_schema == 'Comment')
+   pv_ctrl = uicfg.primaryview_display_ctrl
+   pv_ctrl.tag_object_of(('*', 'created_by', 'CWUser'),
+                         {'vid': 'list', 'label': _('latest comment(s):'),
+                          'limit': True,
+                          'filter': filter_comment})
+
+.. warning:: with the ``primaryview_display_ctrl`` rtag, the subject or the
+   object of the relation is ignored for respectively ``tag_object_of`` or
+   ``tag_subject_of``. To avoid warnings during execution, they should be set to
+   ``'*'``.
+
+
+.. automodule:: cubicweb.web.views.primary
+
+
+Example of customization and creation
+`````````````````````````````````````
+
+We'll show you now an example of a ``primary`` view and how to customize it.
+
+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.predicates import is_instance
+   from cubicweb.web.views.primary import Primaryview
+
+   class BlogEntryPrimaryView(PrimaryView):
+       __select__ = PrimaryView.__select__ & is_instance('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)
+
+
+The above source code defines a new primary view for
+``BlogEntry``. The `__reid__` class attribute is not repeated there since it
+is inherited through the `primary.PrimaryView` class.
+
+The selector for this view chains the selector of the inherited class
+with its own specific criterion.
+
+The view method ``self.w()`` is used to output data. Here `lines
+08-09` output HTML for the publication date of the entry.
+
+.. image:: ../../images/lax-book_09-new-view-blogentry_en.png
+   :alt: blog entries now look much nicer
+
+Let us now improve the primary view of a blog
+
+.. sourcecode:: python
+
+ from logilab.mtconverter import xml_escape
+ from cubicweb.predicates import is_instance, one_line_rset
+ from cubicweb.web.views.primary import Primaryview
+
+ class BlogPrimaryView(PrimaryView):
+     __regid__ = 'primary'
+     __select__ = PrimaryView.__select__ & is_instance('Blog')
+     rql = 'Any BE ORDERBY D DESC WHERE BE entry_of B, BE publish_date D, B eid %(b)s'
+
+     def render_entity_relations(self, entity):
+         rset = self._cw.execute(self.rql, {'b' : entity.eid})
+         for entry in rset.entities():
+             self.w(u'<p>%s</p>' % entry.view('inblogcontext'))
+
+ class BlogEntryInBlogView(EntityView):
+     __regid__ = 'inblogcontext'
+     __select__ = is_instance('BlogEntry')
+
+     def cell_call(self, row, col):
+         entity = self.cw_rset.get_entity(row, col)
+         self.w(u'<a href="%s" title="%s">%s</a>' %
+                entity.absolute_url(),
+                xml_escape(entity.content[:50]),
+                xml_escape(entity.description))
+
+This happens in two places. First we override the
+render_entity_relations method of a Blog's primary view. Here we want
+to display our blog entries in a custom way.
+
+At `line 10`, a simple request is made to build a result set with all
+the entities linked to the current ``Blog`` entity by the relationship
+``entry_of``. The part of the framework handling the request knows
+about the schema and infers that such entities have to be of the
+``BlogEntry`` kind and retrieves them (in the prescribed publish_date
+order).
+
+The request returns a selection of data called a result set. Result
+set objects have an .entities() method returning a generator on
+requested entities (going transparently through the `ORM` layer).
+
+At `line 13` the view 'inblogcontext' is applied to each blog entry to
+output HTML. (Note that the 'inblogcontext' view is not defined
+whatsoever in *CubicWeb*. You are absolutely free to define whole view
+families.) We juste arrange to wrap each blogentry output in a 'p'
+html element.
+
+Next, we define the 'inblogcontext' view. This is NOT a primary view,
+with its well-defined sections (title, metadata, attribtues,
+relations/boxes). All a basic view has to define is cell_call.
+
+Since views are applied to result sets which can be tables of data, we
+have to recover the entity from its (row,col)-coordinates (`line
+20`). Then we can spit some HTML.
+
+.. warning::
+
+  Be careful: all strings manipulated in *CubicWeb* are actually
+  unicode strings. While web browsers are usually tolerant to
+  incoherent encodings they are being served, we should not abuse
+  it. Hence we have to properly escape our data. The xml_escape()
+  function has to be used to safely fill (X)HTML elements from Python
+  unicode strings.
+
+Assuming we added entries to the blog titled `MyLife`, displaying it
+now allows to read its description and all its entries.
+
+.. image:: ../../images/lax-book_10-blog-with-two-entries_en.png
+   :alt: a blog and all its entries
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/reledit.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,149 @@
+.. _reledit:
+
+The "Click and Edit" (also `reledit`) View
+------------------------------------------
+
+The principal way to update data through the Web UI is through the
+`modify` action on entities, which brings a full form. This is
+described in the :ref:`webform` chapter.
+
+There is however another way to perform piecewise edition of entities
+and relations, using a specific `reledit` (for *relation edition*)
+view from the :mod:`cubicweb.web.views.reledit` module.
+
+This is typically applied from the default Primary View (see
+:ref:`primary_view`) on the attributes and relation section. It makes
+small editions more convenient.
+
+Of course, this can be used customely in any other view. Here come
+some explanation about its capabilities and instructions on the way to
+use it.
+
+Using `reledit`
+***************
+
+Let's start again with a simple example:
+
+.. sourcecode:: python
+
+   class Company(EntityType):
+        name = String(required=True, unique=True)
+        boss = SubjectRelation('Person', cardinality='1*')
+        status = SubjectRelation('File', cardinality='?*', composite='subject')
+
+In some view code we might want to show these attributes/relations and
+allow the user to edit each of them in turn without having to leave
+the current page. We would write code as below:
+
+.. sourcecode:: python
+
+   company.view('reledit', rtype='name', default_value='<name>') # editable name attribute
+   company.view('reledit', rtype='boss') # editable boss relation
+   company.view('reledit', rtype='status') # editable attribute-like relation
+
+If one wanted to edit the company from a boss's point of view, one
+would have to indicate the proper relation's role. By default the role
+is `subject`.
+
+.. sourcecode:: python
+
+   person.view('reledit', rtype='boss', role='object')
+
+Each of these will provide with a different editing widget. The `name`
+attribute will obviously get a text input field. The `boss` relation
+will be edited through a selection box, allowing to pick another
+`Person` as boss. The `status` relation, given that it defines Company
+as a composite entity with one file inside, will provide additional actions
+
+* to `add` a `File` when there is one
+* to `delete` the `File` (if the cardinality allows it)
+
+Moreover, editing the relation or using the `add` action leads to an
+embedded edition/creation form allowing edition of the target entity
+(which is `File` in our example) instead of merely allowing to choose
+amongst existing files.
+
+The `reledit_ctrl` rtag
+***********************
+
+The behaviour of reledited attributes/relations can be finely
+controlled using the reledit_ctrl rtag, defined in
+:mod:`cubicweb.web.views.uicfg`.
+
+This rtag provides four control variables:
+
+* ``default_value``: alternative default value
+   The default value is what is shown when there is no value.
+* ``reload``: boolean, eid (to reload to) or function taking subject
+   and returning bool/eid This is useful when editing a relation (or
+   attribute) that impacts the url or another parts of the current
+   displayed page. Defaults to false.
+* ``rvid``: alternative view id (as str) for relation or composite
+   edition Default is 'incontext' or 'csv' depending on the
+   cardinality. They can also be statically changed by subclassing
+   ClickAndEditFormView and redefining _one_rvid (resp. _many_rvid).
+* ``edit_target``: 'rtype' (to edit the relation) or 'related' (to
+   edit the related entity) This controls whether to edit the relation
+   or the target entity of the relation.  Currently only one-to-one
+   relations support target entity edition. By default, the 'related'
+   option is taken whenever the relation is composite and one-to-one.
+
+Let's see how to use these controls.
+
+.. sourcecode:: python
+
+    from logilab.mtconverter import xml_escape
+    from cubicweb.web.views.uicfg import reledit_ctrl
+    reledit_ctrl.tag_attribute(('Company', 'name'),
+                               {'reload': lambda x:x.eid,
+                                'default_value': xml_escape(u'<logilab tastes better>')})
+    reledit_ctrl.tag_object_of(('*', 'boss', 'Person'), {'edit_target': 'related'})
+
+The `default_value` needs to be an xml escaped unicode string.
+
+The `edit_target` tag on the `boss` relation being set to `related` will
+ensure edition of the `Person` entity instead (using a standard
+automatic form) of the association of Company and Person.
+
+Finally, the `reload` key accepts either a boolean, an eid or a
+unicode string representing a url. If an eid is provided, it will be
+internally transformed into a url. The eid/url case helps when one
+needs to reload and the current url is inappropriate. A common case is
+edition of a key attribute, which is part of the current url. If one
+user changed the Company's name from `lozilab` to `logilab`, reloading
+on http://myapp/company/lozilab would fail. Providing the entity's
+eid, then, forces to reload on something like http://myapp/company/42,
+which always work.
+
+
+Disable `reledit`
+*****************
+
+By default, `reledit` is available on attributes and relations displayed in
+the 'attribute' section of the default primary view.  If you want to disable
+it for some attribute or relation, you have use `uicfg`:
+
+.. sourcecode:: python
+
+    from cubicweb.web.views.uicfg import primaryview_display_ctrl as _pvdc
+    _pvdc.tag_attribute(('Company', 'name'), {'vid': 'incontext'})
+
+To deactivate it everywhere it's used automatically, you may use the code snippet
+below somewhere in your cube's views:
+
+.. sourcecode:: python
+
+    from cubicweb.web.views import reledit
+
+    class DeactivatedAutoClickAndEditFormView(reledit.AutoClickAndEditFormView):
+	def _should_edit_attribute(self, rschema):
+	    return False
+
+	def _should_edit_attribute(self, rschema, role):
+	    return False
+
+    def registration_callback(vreg):
+	vreg.register_and_replace(DeactivatedAutoClickAndEditFormView,
+				  reledit.AutoClickAndEditFormView)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/startup.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,18 @@
+Startup views
+-------------
+
+Startup views are views requiring no context, from which you usually start
+browsing (for instance the index page). The usual selectors are
+:class:`~cubicweb.predicates.none_rset` or :class:`~logilab.common.registry.yes`.
+
+You'll find here a description of startup views provided by the framework.
+
+.. automodule:: cubicweb.web.views.startup
+
+
+Other startup views:
+
+*schema*
+    A view dedicated to the display of the schema of the instance
+
+.. XXX to be continued
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/table.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,145 @@
+Table views
+-----------
+
+.. automodule:: cubicweb.web.views.tableview
+
+Example
+```````
+
+Let us take an example from the timesheet cube:
+
+.. sourcecode:: python
+
+    class ActivityResourcesTable(EntityView):
+        __regid__ = 'activity.resources.table'
+        __select__ = is_instance('Activity')
+
+        def call(self, showresource=True):
+            eids = ','.join(str(row[0]) for row in self.cw_rset)
+            rql = ('Any R,D,DUR,WO,DESCR,S,A, SN,RT,WT ORDERBY D DESC '
+                   'WHERE '
+                   '   A is Activity, A done_by R, R title RT, '
+                   '   A diem D, A duration DUR, '
+                   '   A done_for WO, WO title WT, '
+                   '   A description DESCR, A in_state S, S name SN, '
+                   '   A eid IN (%s)' % eids)
+            rset = self._cw.execute(rql)
+            self.wview('resource.table', rset, 'null')
+
+    class ResourcesTable(RsetTableView):
+        __regid__ = 'resource.table'
+        # notice you may wish a stricter selector to check rql's shape
+        __select__ = is_instance('Resource')
+        # my table headers
+        headers  = ['Resource', 'diem', 'duration', 'workpackage', 'description', 'state']
+        # I want a table where attributes are editable (reledit inside)
+        finalvid = 'editable-final'
+
+        cellvids = {3: 'editable-final'}
+        # display facets and actions with a menu
+        layout_args = {'display_filter': 'top',
+                       'add_view_actions': None}
+
+To obtain an editable table, you may specify the 'editable-table' view identifier
+using some of `cellvids`, `finalvid` or `nonfinalvid`.
+
+The previous example results in:
+
+.. image:: ../../images/views-table-shadow.png
+
+In order to activate table filter mechanism, the `display_filter` option is given
+as a layout argument. A small arrow will be displayed at the table's top right
+corner. Clicking on `show filter form` action, will display the filter form as
+below:
+
+.. image:: ../../images/views-table-filter-shadow.png
+
+By the same way, you can display additional actions for the selected entities
+by setting `add_view_actions` layout option to `True`. This will add actions
+returned by the view's :meth:`~cubicweb.web.views.tableview.TableMixIn.table_actions`.
+
+You can notice that all columns of the result set are not displayed. This is
+because of given `headers`, implying to display only columns from 0 to
+len(headers).
+
+Also Notice that the `ResourcesTable` view relies on a particular rql shape
+(which is not ensured by the way, the only checked thing is that the result set
+contains instance of the `Resource` type). That usually implies that you can't
+use this view for user specific queries (e.g. generated by facets or typed
+manually).
+
+
+So another option would be to write this view using
+:class:`~cubicweb.web.views.tableview.EntityTableView`, as below.
+
+.. sourcecode:: python
+
+    class ResourcesTable(EntityTableView):
+        __regid__ = 'resource.table'
+        __select__ = is_instance('Resource')
+        # table columns definition
+        columns  = ['resource', 'diem', 'duration', 'workpackage', 'description', 'in_state']
+        # I want a table where attributes are editable (reledit inside)
+        finalvid = 'editable-final'
+        # display facets and actions with a menu
+        layout_args = {'display_filter': 'top',
+                       'add_view_actions': None}
+
+        def workpackage_cell(entity):
+            activity = entity.reverse_done_in[0]
+            activity.view('reledit', rtype='done_for', role='subject', w=w)
+        def workpackage_sortvalue(entity):
+            activity = entity.reverse_done_in[0]
+            return activity.done_for[0].sortvalue()
+
+        column_renderers = {
+            'resource': MainEntityColRenderer(),
+            'workpackage': EntityTableColRenderer(
+               header='Workpackage',
+               renderfunc=worpackage_cell,
+               sortfunc=worpackage_sortvalue,),
+            'in_state': EntityTableColRenderer(
+               renderfunc=lambda w,x: w(x.cw_adapt_to('IWorkflowable').printable_state),
+               sortfunc=lambda x: x.cw_adapt_to('IWorkflowable').printable_state),
+         }
+
+Notice the following point:
+
+* `cell_<column>(w, entity)` will be searched for rendering the content of a
+  cell. If not found, `column` is expected to be an attribute of `entity`.
+
+* `cell_sortvalue_<column>(entity)` should return a typed value to use for
+  javascript sorting or None for not sortable columns (the default).
+
+* The :func:`etable_entity_sortvalue` decorator will set a 'sortvalue' function
+  for the column containing the main entity (the one given as argument to all
+  methods), which will call `entity.sortvalue()`.
+
+* You can set a column header using the :func:`etable_header_title` decorator.
+  This header will be translated. If it's not an already existing msgid, think
+  to mark it using `_()` (the example supposes headers are schema defined msgid).
+
+
+Pro/cons of each approach
+`````````````````````````
+:class:`EntityTableView` and :class:`RsetableView` provides basically the same
+set of features, though they don't share the same properties. Let's try to sum
+up pro and cons of each class.
+
+* `EntityTableView` view is:
+
+  - more verbose, but usually easier to understand
+
+  - easily extended (easy to add/remove columns for instance)
+
+  - doesn't rely on a particular rset shape. Simply give it a title and will be
+    listed in the 'possible views' box if any.
+
+* `RsetTableView` view is:
+
+  - hard to beat to display barely a result set, or for cases where some of
+    `headers`, `displaycols` or `cellvids` could be defined to enhance the table
+    while you don't care about e.g. pagination or facets.
+
+  - hardly extensible, as you usually have to change places where the view is
+    called to modify the RQL (hence the view's result set shape).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/urlpublish.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,137 @@
+.. -*- coding: utf-8 -*-
+
+URL publishing
+--------------
+
+(:mod:`cubicweb.web.views.urlpublishing`)
+
+.. automodule:: cubicweb.web.views.urlpublishing
+
+.. autoclass:: cubicweb.web.views.urlpublishing.URLPublisherComponent
+   :members:
+
+
+You can write your own *URLPathEvaluator* class to handle custom paths.
+For instance, if you want */my-card-id* to redirect to the corresponding
+card's primary view, you would write:
+
+.. sourcecode:: python
+
+    class CardWikiidEvaluator(URLPathEvaluator):
+        priority = 3 # make it be evaluated *before* RestPathEvaluator
+
+        def evaluate_path(self, req, segments):
+            if len(segments) != 1:
+                raise PathDontMatch()
+            rset = req.execute('Any C WHERE C wikiid %(w)s',
+                               {'w': segments[0]})
+            if len(rset) == 0:
+                # Raise NotFound if no card is found
+                raise PathDontMatch()
+            return None, rset
+
+On the other hand, you can also deactivate some of the standard
+evaluators in your final application. The only thing you have to
+do is to unregister them, for instance in a *registration_callback*
+in your cube:
+
+.. sourcecode:: python
+
+    def registration_callback(vreg):
+        vreg.unregister(RestPathEvaluator)
+
+You can even replace the :class:`cubicweb.web.views.urlpublishing.URLPublisherComponent`
+class if you want to customize the whole toolchain process or if you want
+to plug into an early enough extension point to control your request
+parameters:
+
+.. sourcecode:: python
+
+    class SanitizerPublisherComponent(URLPublisherComponent):
+        """override default publisher component to explicitly ignore
+        unauthorized request parameters in anonymous mode.
+        """
+        unauthorized_form_params = ('rql', 'vid', '__login', '__password')
+
+        def process(self, req, path):
+            if req.session.anonymous_session:
+                self._remove_unauthorized_params(req)
+            return super(SanitizerPublisherComponent, self).process(req, path)
+
+        def _remove_unauthorized_params(self, req):
+            for param in req.form.keys():
+                if param in self.unauthorized_form_params:
+                     req.form.pop(param)
+
+
+    def registration_callback(vreg):
+        vreg.register_and_replace(SanitizerPublisherComponent, URLPublisherComponent)
+
+
+.. autoclass:: cubicweb.web.views.urlpublishing.RawPathEvaluator
+.. autoclass:: cubicweb.web.views.urlpublishing.EidPathEvaluator
+.. autoclass:: cubicweb.web.views.urlpublishing.URLRewriteEvaluator
+.. autoclass:: cubicweb.web.views.urlpublishing.RestPathEvaluator
+.. autoclass:: cubicweb.web.views.urlpublishing.ActionPathEvaluator
+
+URL rewriting
+-------------
+
+(:mod:`cubicweb.web.views.urlrewrite`)
+
+.. autoclass:: cubicweb.web.views.urlrewrite.URLRewriter
+   :members:
+
+.. autoclass:: cubicweb.web.views.urlrewrite.SimpleReqRewriter
+   :members:
+
+.. autoclass:: cubicweb.web.views.urlrewrite.SchemaBasedRewriter
+   :members:
+
+
+``SimpleReqRewriter`` is enough for a certain number of simple cases. If it is not sufficient, ``SchemaBasedRewriter`` allows to do more elaborate things.
+
+Here is an example of ``SimpleReqRewriter`` usage with plain string:
+
+.. sourcecode:: python
+
+   from cubicweb.web.views.urlrewrite import SimpleReqRewriter
+   class TrackerSimpleReqRewriter(SimpleReqRewriter):
+       rules = [
+        ('/versions', dict(vid='versionsinfo')),
+        ]
+
+When the url is `<base_url>/versions`, the view with the __regid__ `versionsinfo` is displayed.
+
+Here is an example of ``SimpleReqRewriter`` usage with regular expressions:
+
+.. sourcecode:: python
+
+    from cubicweb.web.views.urlrewrite import (
+        SimpleReqRewriter, rgx)
+
+    class BlogReqRewriter(SimpleReqRewriter):
+        rules = [
+            (rgx('/blogentry/([a-z_]+)\.rss'),
+             dict(rql=('Any X ORDERBY CD DESC LIMIT 20 WHERE X is BlogEntry,'
+                       'X creation_date CD, X created_by U, '
+                       'U login "%(user)s"'
+                       % {'user': r'\1'}), vid='rss'))
+            ]
+
+When a url matches the regular expression, the view with the __regid__
+`rss` which match the result set is displayed.
+
+Here is an example of ``SchemaBasedRewriter`` usage:
+
+.. sourcecode:: python
+
+    from cubicweb.web.views.urlrewrite import (
+        SchemaBasedRewriter, rgx, build_rset)
+
+    class TrackerURLRewriter(SchemaBasedRewriter):
+        rules = [
+            (rgx('/project/([^/]+)/([^/]+)/tests'),
+             build_rset(rql='Version X WHERE X version_of P, P name %(project)s, X num %(num)s',
+                        rgxgroups=[('project', 1), ('num', 2)], vid='versiontests')),
+            ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/views.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,120 @@
+
+.. _Views:
+
+Principles
+----------
+
+We'll start with a description of the interface providing a basic
+understanding of the available classes and methods, then detail the
+view selection principle.
+
+A `View` is an object responsible for the rendering of data from the
+model into an end-user consummable form. They typically churn out an
+XHTML stream, but there are views concerned with email other non-html
+outputs.
+
+.. _views_base_class:
+
+Discovering possible views
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is possible to configure the web user interface to have a left box
+showing all the views than can be applied to the current result set.
+
+To enable this, click on your login at the top right corner. Chose
+"user preferences", then "boxes", then "possible views box" and check
+"visible = yes" before validating your changes.
+
+The views listed there we either not selected because of a lower
+score, or they were deliberately excluded by the main template logic.
+
+
+Basic class for views
+~~~~~~~~~~~~~~~~~~~~~
+
+Class :class:`~cubicweb.view.View`
+``````````````````````````````````
+
+.. autoclass:: cubicweb.view.View
+
+The basic interface for views is as follows (remember that the result
+set has a tabular structure with rows and columns, hence cells):
+
+* `render(**context)`, render the view by calling `call` or
+  `cell_call` depending on the context
+
+* `call(**kwargs)`, call the view for a complete result set or null
+  (the default implementation calls `cell_call()` on each cell of the
+  result set)
+
+* `cell_call(row, col, **kwargs)`, call the view for a given cell of a
+  result set (`row` and `col` being integers used to access the cell)
+
+* `url()`, returns the URL enabling us to get the view with the current
+  result set
+
+* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of
+  identifier `__vid` on the given result set. It is possible to give a
+  fallback view identifier that will be used if the requested view is
+  not applicable to the result set.
+
+* `html_headers()`, returns a list of HTML headers to be set by the
+  main template
+
+* `page_title()`, returns the title to use in the HTML header `title`
+
+Other basic view classes
+````````````````````````
+Here are some of the subclasses of :class:`~cubicweb.view.View` defined in :mod:`cubicweb.view`
+that are more concrete as they relate to data rendering within the application:
+
+.. autoclass:: cubicweb.view.EntityView
+.. autoclass:: cubicweb.view.StartupView
+.. autoclass:: cubicweb.view.EntityStartupView
+.. autoclass:: cubicweb.view.AnyRsetView
+
+Examples of views class
+```````````````````````
+
+- Using `templatable`, `content_type` and HTTP cache configuration
+
+.. sourcecode:: python
+
+    class RSSView(XMLView):
+        __regid__ = 'rss'
+        title = _('rss')
+        templatable = False
+        content_type = 'text/xml'
+        http_cache_manager = MaxAgeHTTPCacheManager
+        cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
+
+
+- Using a custom selector
+
+.. sourcecode:: python
+
+    class SearchForAssociationView(EntityView):
+        """view called by the edition view when the user asks
+        to search for something to link to the edited eid
+        """
+        __regid__ = 'search-associate'
+        title = _('search for association')
+        __select__ = one_line_rset() & match_search_state('linksearch') & is_instance('Any')
+
+
+XML views, binaries views...
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For views generating other formats than HTML (an image generated dynamically
+for example), and which can not simply be included in the HTML page generated
+by the main template (see above), you have to:
+
+* set the attribute `templatable` of the class to `False`
+* set, through the attribute `content_type` of the class, the MIME
+  type generated by the view to `application/octet-stream` or any
+  relevant and more specialised mime type
+
+For views dedicated to binary content creation (like dynamically generated
+images), we have to set the attribute `binary` of the class to `True` (which
+implies that `templatable == False`, so that the attribute `w` of the view could be
+replaced by a binary flow instead of unicode).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/wdoc.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,15 @@
+.. -*- coding: utf-8 -*-
+
+Online documentation system
+===========================
+
+.. automodule:: cubicweb.web.views.wdoc
+
+Help views
+----------
+.. autoclass:: cubicweb.web.views.wdoc.InlineHelpView
+
+Actions
+-------
+.. autoclass:: cubicweb.web.views.wdoc.HelpAction
+.. autoclass:: cubicweb.web.views.wdoc.AboutAction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/devweb/views/xmlrss.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,66 @@
+.. _XmlAndRss:
+
+XML and RSS views
+-----------------
+
+(:mod:`cubicweb.web.views.xmlrss`)
+
+Overview
++++++++++
+
+*rss*
+    Creates a RSS/XML view and call the view `rssitem` for each entity of
+    the result set.
+
+*rssitem*
+    Create a RSS/XML view for each entity based on the results of the dublin core
+    methods of the entity (`dc_*`)
+
+RSS Channel Example
+++++++++++++++++++++
+
+Assuming you have several blog entries, click on the title of the
+search box in the left column. A larger search box should appear. Enter:
+
+.. sourcecode:: sql
+
+   Any X ORDERBY D WHERE X is BlogEntry, X creation_date D
+
+and you get a list of blog entries.
+
+Click on your login at the top right corner. Chose "user preferences",
+then "boxes", then "possible views box" and check "visible = yes"
+before validating your changes.
+
+Enter the same query in the search box and you will see the same list,
+plus a box titled "possible views" in the left column. Click on
+"entityview", then "RSS".
+
+You just applied the "RSS" view to the RQL selection you requested.
+
+That's it, you have a RSS channel for your blog.
+
+Try again with:
+
+.. sourcecode:: sql
+
+    Any X ORDERBY D WHERE X is BlogEntry, X creation_date D,
+    X entry_of B, B title "MyLife"
+
+Another RSS channel, but a bit more focused.
+
+A last one for the road:
+
+.. sourcecode:: sql
+
+    Any C ORDERBY D WHERE C is Comment, C creation_date D LIMIT 15
+
+displayed with the RSS view, that's a channel for the last fifteen
+comments posted.
+
+[WRITE ME]
+
+* show that the RSS view can be used to display an ordered selection
+  of blog entries, thus providing a RSS channel
+
+* show that a different selection (by category) means a different channel
Binary file doc/book/en/.static/cubicweb.png has changed
Binary file doc/book/en/.static/logilab.png has changed
--- a/doc/book/en/.static/sphinx-default.css	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,861 +0,0 @@
-/**
- * Sphinx Doc Design
- */
-
-html, body {
-    background: white;
-}
-
-body {
-    font-family: Verdana, sans-serif;
-    font-size: 100%;
-    background-color: white;
-    color: black;
-    margin: 0;
-    padding: 0;
-}
-
-/* :::: LAYOUT :::: */
-
-div.logilablogo {
-    padding: 10px 10px 10px 10px;
-    height:75;
-}
-
-
-div.document {
-    background-color: white;
-}
-
-div.documentwrapper {
-    float: left;
-    width: 100%;
-}
-
-div.bodywrapper {
-    margin: 0 0 0 230px;
-}
-
-div.body {
-    background-color: white;
-    padding: 0 20px 30px 20px;
-    border-left:solid;
-    border-left-color:#e2e2e2;
-    border-left-width:thin;
-}
-
-div.sphinxsidebarwrapper {
-    padding: 10px 5px 0 10px;
-}
-
-div.sphinxsidebar {
-    float: left;
-    width: 230px;
-    margin-left: -100%;
-    font-size: 90%;
-}
-
-div.clearer {
-    clear: both;
-}
-
-div.footer {
-    color: #ff4500;
-    width: 100%;
-    padding: 9px 0 9px 0;
-    text-align: center;
-    font-size: 75%;
-}
-
-div.footer a {
-    color: #ff4500;
-    text-decoration: underline;
-}
-
-div.related {
-    background-color: #ff7700;
-    color: white;
-    width: 100%;
-    height: 30px;
-    line-height: 30px;
-    font-size: 90%;
-}
-
-div.related h3 {
-    display: none;
-}
-
-div.related ul {
-    margin: 0;
-    padding: 0 0 0 10px;
-    list-style: none;
-}
-
-div.related li {
-    display: inline;
-}
-
-div.related li.right {
-    float: right;
-    margin-right: 5px;
-}
-
-div.related a {
-    color: white;
-    font-weight:bold;
-}
-
-/* ::: TOC :::: */
-
-div.sphinxsidebar {
-    border-style:solid;
-    border-color: white;
-/*    background-color:#e2e2e2;*/
-    padding-bottom:5px;
-}
-
-div.sphinxsidebar h3 {
-    font-family: Verdana, sans-serif;
-    color: black;
-    font-size: 1.2em;
-    font-weight: normal;
-    margin: 0;
-    padding: 0;
-    font-weight:bold;
-    font-style:italic;
-}
-
-div.sphinxsidebar h4 {
-    font-family: Verdana, sans-serif;
-    color: black;
-    font-size: 1.1em;
-    font-weight: normal;
-    margin: 5px 0 0 0;
-    padding: 0;
-    font-weight:bold;
-    font-style:italic;
-}
-
-div.sphinxsidebar p {
-    color: black;
-}
-
-div.sphinxsidebar p.topless {
-    margin: 5px 10px 10px 10px;
-}
-
-div.sphinxsidebar ul {
-    margin: 10px;
-    padding: 0;
-    list-style: none;
-    color: black;
-}
-
-div.sphinxsidebar ul ul,
-div.sphinxsidebar ul.want-points {
-    margin-left: 20px;
-    list-style: square;
-}
-
-div.sphinxsidebar ul ul {
-    margin-top: 0;
-    margin-bottom: 0;
-}
-
-div.sphinxsidebar a {
-    color: black;
-    text-decoration: none;
-}
-
-div.sphinxsidebar form {
-    margin-top: 10px;
-}
-
-div.sphinxsidebar input {
-    border: 1px solid #e2e2e2;
-    font-family: sans-serif;
-    font-size: 1em;
-    padding-bottom: 5px;
-}
-
-/* :::: MODULE CLOUD :::: */
-div.modulecloud {
-    margin: -5px 10px 5px 10px;
-    padding: 10px;
-    line-height: 160%;
-    border: 1px solid #cbe7e5;
-    background-color: #f2fbfd;
-}
-
-div.modulecloud a {
-    padding: 0 5px 0 5px;
-}
-
-/* :::: SEARCH :::: */
-ul.search {
-    margin: 10px 0 0 20px;
-    padding: 0;
-}
-
-ul.search li {
-    padding: 5px 0 5px 20px;
-    background-image: url(file.png);
-    background-repeat: no-repeat;
-    background-position: 0 7px;
-}
-
-ul.search li a {
-    font-weight: bold;
-}
-
-ul.search li div.context {
-    color: #888;
-    margin: 2px 0 0 30px;
-    text-align: left;
-}
-
-ul.keywordmatches li.goodmatch a {
-    font-weight: bold;
-}
-
-/* :::: COMMON FORM STYLES :::: */
-
-div.actions {
-    padding: 5px 10px 5px 10px;
-    border-top: 1px solid #cbe7e5;
-    border-bottom: 1px solid #cbe7e5;
-    background-color: #e0f6f4;
-}
-
-form dl {
-    color: #333;
-}
-
-form dt {
-    clear: both;
-    float: left;
-    min-width: 110px;
-    margin-right: 10px;
-    padding-top: 2px;
-}
-
-input#homepage {
-    display: none;
-}
-
-div.error {
-    margin: 5px 20px 0 0;
-    padding: 5px;
-    border: 1px solid #d00;
-    font-weight: bold;
-}
-
-/* :::: INLINE COMMENTS :::: */
-
-div.inlinecomments {
-    position: absolute;
-    right: 20px;
-}
-
-div.inlinecomments a.bubble {
-    display: block;
-    float: right;
-    background-image: url(style/comment.png);
-    background-repeat: no-repeat;
-    width: 25px;
-    height: 25px;
-    text-align: center;
-    padding-top: 3px;
-    font-size: 0.9em;
-    line-height: 14px;
-    font-weight: bold;
-    color: black;
-}
-
-div.inlinecomments a.bubble span {
-    display: none;
-}
-
-div.inlinecomments a.emptybubble {
-    background-image: url(style/nocomment.png);
-}
-
-div.inlinecomments a.bubble:hover {
-    background-image: url(style/hovercomment.png);
-    text-decoration: none;
-    color: #3ca0a4;
-}
-
-div.inlinecomments div.comments {
-    float: right;
-    margin: 25px 5px 0 0;
-    max-width: 50em;
-    min-width: 30em;
-    border: 1px solid #2eabb0;
-    background-color: #f2fbfd;
-    z-index: 150;
-}
-
-div#comments {
-    border: 1px solid #2eabb0;
-    margin-top: 20px;
-}
-
-div#comments div.nocomments {
-    padding: 10px;
-    font-weight: bold;
-}
-
-div.inlinecomments div.comments h3,
-div#comments h3 {
-    margin: 0;
-    padding: 0;
-    background-color: #2eabb0;
-    color: white;
-    border: none;
-    padding: 3px;
-}
-
-div.inlinecomments div.comments div.actions {
-    padding: 4px;
-    margin: 0;
-    border-top: none;
-}
-
-div#comments div.comment {
-    margin: 10px;
-    border: 1px solid #2eabb0;
-}
-
-div.inlinecomments div.comment h4,
-div.commentwindow div.comment h4,
-div#comments div.comment h4 {
-    margin: 10px 0 0 0;
-    background-color: #2eabb0;
-    color: white;
-    border: none;
-    padding: 1px 4px 1px 4px;
-}
-
-div#comments div.comment h4 {
-    margin: 0;
-}
-
-div#comments div.comment h4 a {
-    color: #d5f4f4;
-}
-
-div.inlinecomments div.comment div.text,
-div.commentwindow div.comment div.text,
-div#comments div.comment div.text {
-    margin: -5px 0 -5px 0;
-    padding: 0 10px 0 10px;
-}
-
-div.inlinecomments div.comment div.meta,
-div.commentwindow div.comment div.meta,
-div#comments div.comment div.meta {
-    text-align: right;
-    padding: 2px 10px 2px 0;
-    font-size: 95%;
-    color: #538893;
-    border-top: 1px solid #cbe7e5;
-    background-color: #e0f6f4;
-}
-
-div.commentwindow {
-    position: absolute;
-    width: 500px;
-    border: 1px solid #cbe7e5;
-    background-color: #f2fbfd;
-    display: none;
-    z-index: 130;
-}
-
-div.commentwindow h3 {
-    margin: 0;
-    background-color: #2eabb0;
-    color: white;
-    border: none;
-    padding: 5px;
-    font-size: 1.5em;
-    cursor: pointer;
-}
-
-div.commentwindow div.actions {
-    margin: 10px -10px 0 -10px;
-    padding: 4px 10px 4px 10px;
-    color: #538893;
-}
-
-div.commentwindow div.actions input {
-    border: 1px solid #2eabb0;
-    background-color: white;
-    color: #135355;
-    cursor: pointer;
-}
-
-div.commentwindow div.form {
-    padding: 0 10px 0 10px;
-}
-
-div.commentwindow div.form input,
-div.commentwindow div.form textarea {
-    border: 1px solid #3c9ea2;
-    background-color: white;
-    color: black;
-}
-
-div.commentwindow div.error {
-    margin: 10px 5px 10px 5px;
-    background-color: #fbe5dc;
-    display: none;
-}
-
-div.commentwindow div.form textarea {
-    width: 99%;
-}
-
-div.commentwindow div.preview {
-    margin: 10px 0 10px 0;
-    background-color: #70d0d4;
-    padding: 0 1px 1px 25px;
-}
-
-div.commentwindow div.preview h4 {
-    margin: 0 0 -5px -20px;
-    padding: 4px 0 0 4px;
-    color: white;
-    font-size: 1.3em;
-}
-
-div.commentwindow div.preview div.comment {
-    background-color: #f2fbfd;
-}
-
-div.commentwindow div.preview div.comment h4 {
-    margin: 10px 0 0 0!important;
-    padding: 1px 4px 1px 4px!important;
-    font-size: 1.2em;
-}
-
-/* :::: SUGGEST CHANGES :::: */
-div#suggest-changes-box input, div#suggest-changes-box textarea {
-    border: 1px solid #ccc;
-    background-color: white;
-    color: black;
-}
-
-div#suggest-changes-box textarea {
-    width: 99%;
-    height: 400px;
-}
-
-
-/* :::: PREVIEW :::: */
-div.preview {
-    background-image: url(style/preview.png);
-    padding: 0 20px 20px 20px;
-    margin-bottom: 30px;
-}
-
-
-/* :::: INDEX PAGE :::: */
-
-table.contentstable {
-    width: 90%;
-}
-
-table.contentstable p.biglink {
-    line-height: 150%;
-}
-
-a.biglink {
-    font-size: 1.3em;
-}
-
-span.linkdescr {
-    font-style: italic;
-    padding-top: 5px;
-    font-size: 90%;
-}
-
-/* :::: INDEX STYLES :::: */
-
-table.indextable td {
-    text-align: left;
-    vertical-align: top;
-}
-
-table.indextable dl, table.indextable dd {
-    margin-top: 0;
-    margin-bottom: 0;
-}
-
-table.indextable tr.pcap {
-    height: 10px;
-}
-
-table.indextable tr.cap {
-    margin-top: 10px;
-    background-color: #f2f2f2;
-}
-
-img.toggler {
-    margin-right: 3px;
-    margin-top: 3px;
-    cursor: pointer;
-}
-
-form.pfform {
-    margin: 10px 0 20px 0;
-}
-
-/* :::: GLOBAL STYLES :::: */
-
-.docwarning {
-    background-color: #ffe4e4;
-    padding: 10px;
-    margin: 0 -20px 0 -20px;
-    border-bottom: 1px solid #f66;
-}
-
-p.subhead {
-    font-weight: bold;
-    margin-top: 20px;
-}
-
-a {
-    color: orangered;
-    text-decoration: none;
-}
-
-a:hover {
-    text-decoration: underline;
-}
-
-div.body h1,
-div.body h2,
-div.body h3,
-div.body h4,
-div.body h5,
-div.body h6 {
-    font-family: 'Verdana', sans-serif;
-    background-color: white;
-    font-weight: bold;
-    color: black;
-    border-bottom: 1px solid #ccc;
-    margin: 20px -20px 10px -20px;
-    padding: 3px 0 3px 10px;
-}
-
-div.body h1 { margin-top: 10pt; font-size: 150%; }
-div.body h2 { font-size: 120%; }
-div.body h3 { font-size: 100%; }
-div.body h4 { font-size: 80%; }
-div.body h5 { font-size: 600%; }
-div.body h6 { font-size: 40%; }
-
-a.headerlink {
-    color: #c60f0f;
-    font-size: 0.8em;
-    padding: 0 4px 0 4px;
-    text-decoration: none;
-    visibility: hidden;
-}
-
-h1:hover > a.headerlink,
-h2:hover > a.headerlink,
-h3:hover > a.headerlink,
-h4:hover > a.headerlink,
-h5:hover > a.headerlink,
-h6:hover > a.headerlink,
-dt:hover > a.headerlink {
-    visibility: visible;
-}
-
-a.headerlink:hover {
-    background-color: #c60f0f;
-    color: white;
-}
-
-div.body p, div.body dd, div.body li {
-    text-align: justify;
-    line-height: 130%;
-}
-
-div.body p.caption {
-    text-align: inherit;
-}
-
-div.body td {
-    text-align: left;
-}
-
-ul.fakelist {
-    list-style: none;
-    margin: 10px 0 10px 20px;
-    padding: 0;
-}
-
-.field-list ul {
-    padding-left: 1em;
-}
-
-.first {
-    margin-top: 0 !important;
-}
-
-/* "Footnotes" heading */
-p.rubric {
-    margin-top: 30px;
-    font-weight: bold;
-}
-
-/* "Topics" */
-
-div.topic {
-    background-color: #eee;
-    border: 1px solid #ccc;
-    padding: 0 7px 0 7px;
-    margin: 10px 0 10px 0;
-}
-
-p.topic-title {
-    font-size: 1.1em;
-    font-weight: bold;
-    margin-top: 10px;
-}
-
-/* Admonitions */
-
-div.admonition {
-    margin-top: 10px;
-    margin-bottom: 10px;
-    padding: 7px;
-}
-
-div.admonition dt {
-    font-weight: bold;
-}
-
-div.admonition dl {
-    margin-bottom: 0;
-}
-
-div.admonition p {
-    display: inline;
-}
-
-div.seealso {
-    background-color: #ffc;
-    border: 1px solid #ff6;
-}
-
-div.warning {
-    background-color: #ffe4e4;
-    border: 1px solid #f66;
-}
-
-div.note {
-    background-color: #eee;
-    border: 1px solid #ccc;
-}
-
-p.admonition-title {
-    margin: 0px 10px 5px 0px;
-    font-weight: bold;
-    display: inline;
-}
-
-p.admonition-title:after {
-    content: ":";
-}
-
-div.body p.centered {
-    text-align: center;
-    margin-top: 25px;
-}
-
-table.docutils {
-    border: 0;
-}
-
-table.docutils td, table.docutils th {
-    padding: 1px 8px 1px 0;
-    border-top: 0;
-    border-left: 0;
-    border-right: 0;
-    border-bottom: 1px solid #aaa;
-}
-
-table.field-list td, table.field-list th {
-    border: 0 !important;
-}
-
-table.footnote td, table.footnote th {
-    border: 0 !important;
-}
-
-.field-list ul {
-    margin: 0;
-    padding-left: 1em;
-}
-
-.field-list p {
-    margin: 0;
-}
-
-dl {
-    margin-bottom: 15px;
-    clear: both;
-}
-
-dd p {
-    margin-top: 0px;
-}
-
-dd ul, dd table {
-    margin-bottom: 10px;
-}
-
-dd {
-    margin-top: 3px;
-    margin-bottom: 10px;
-    margin-left: 30px;
-}
-
-.refcount {
-    color: #060;
-}
-
-dt:target,
-.highlight {
-    background-color: #fbe54e;
-}
-
-dl.glossary dt {
-    font-weight: bold;
-    font-size: 1.1em;
-}
-
-th {
-    text-align: left;
-    padding-right: 5px;
-}
-
-pre {
-    padding: 5px;
-    background-color: #efc;
-    color: #333;
-    border: 1px solid #ac9;
-    border-left: none;
-    border-right: none;
-    overflow: auto;
-}
-
-td.linenos pre {
-    padding: 5px 0px;
-    border: 0;
-    background-color: transparent;
-    color: #aaa;
-}
-
-table.highlighttable {
-    margin-left: 0.5em;
-}
-
-table.highlighttable td {
-    padding: 0 0.5em 0 0.5em;
-}
-
-tt {
-    background-color: #ecf0f3;
-    padding: 0 1px 0 1px;
-    font-size: 0.95em;
-}
-
-tt.descname {
-    background-color: transparent;
-    font-weight: bold;
-    font-size: 1.2em;
-}
-
-tt.descclassname {
-    background-color: transparent;
-}
-
-tt.xref, a tt {
-    background-color: transparent;
-    font-weight: bold;
-}
-
-.footnote:target  { background-color: #ffa }
-
-h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
-    background-color: transparent;
-}
-
-.optional {
-    font-size: 1.3em;
-}
-
-.versionmodified {
-    font-style: italic;
-}
-
-form.comment {
-    margin: 0;
-    padding: 10px 30px 10px 30px;
-    background-color: #eee;
-}
-
-form.comment h3 {
-    background-color: #326591;
-    color: white;
-    margin: -10px -30px 10px -30px;
-    padding: 5px;
-    font-size: 1.4em;
-}
-
-form.comment input,
-form.comment textarea {
-    border: 1px solid #ccc;
-    padding: 2px;
-    font-family: sans-serif;
-    font-size: 100%;
-}
-
-form.comment input[type="text"] {
-    width: 240px;
-}
-
-form.comment textarea {
-    width: 100%;
-    height: 200px;
-    margin-bottom: 10px;
-}
-
-.system-message {
-    background-color: #fda;
-    padding: 5px;
-    border: 3px solid red;
-}
-
-/* :::: PRINT :::: */
-@media print {
-    div.document,
-    div.documentwrapper,
-    div.bodywrapper {
-        margin: 0;
-        width : 100%;
-    }
-
-    div.sphinxsidebar,
-    div.related,
-    div.footer,
-    div#comments div.new-comment-box,
-    #top-link {
-        display: none;
-    }
-}
--- a/doc/book/en/.templates/layout.html	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-{%- block doctype -%}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-{%- endblock %}
-{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
-{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
-{%- macro relbar() %}
-    <div class="related">
-      <h3>Navigation</h3>
-      <ul>
-        {%- for rellink in rellinks %}
-        <li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
-          <a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags }}"
-             accesskey="{{ rellink[2] }}">{{ rellink[3] }}</a>
-          {%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
-        {%- endfor %}
-        {%- block rootrellink %}
-        <li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
-        {%- endblock %}
-        {%- for parent in parents %}
-          <li><a href="{{ parent.link|e }}" accesskey="U">{{ parent.title }}</a>{{ reldelim1 }}</li>
-        {%- endfor %}
-        {%- block relbaritems %}{% endblock %}
-      </ul>
-    </div>
-{%- endmacro %}
-{%- macro sidebar() %}
-      {%- if builder != 'htmlhelp' %}
-      <div class="sphinxsidebar">
-        <div class="sphinxsidebarwrapper">
-          {%- block sidebarlogo %}
-          {%- if logo %}
-            <p class="logo"><img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/></p>
-          {%- endif %}
-          {%- endblock %}
-          {%- block sidebartoc %}
-          {%- if display_toc %}
-            <h3>Table Of Contents</h3>
-            {{ toc }}
-          {%- endif %}
-          {%- endblock %}
-          {%- block sidebarrel %}
-          {%- if prev %}
-            <h4>Previous topic</h4>
-            <p class="topless"><a href="{{ prev.link|e }}" title="previous chapter">{{ prev.title }}</a></p>
-          {%- endif %}
-          {%- if next %}
-            <h4>Next topic</h4>
-            <p class="topless"><a href="{{ next.link|e }}" title="next chapter">{{ next.title }}</a></p>
-          {%- endif %}
-          {%- endblock %}
-          {%- if sourcename %}
-            <!--<h3>This Page</h3>
-            <ul class="this-page-menu">
-            {%- if builder == 'web' %}
-              <li><a href="#comments">Comments ({{ comments|length }} so far)</a></li>
-              <li><a href="{{ pathto('@edit/' + sourcename)|e }}">Suggest Change</a></li>
-              <li><a href="{{ pathto('@source/' + sourcename)|e }}">Show Source</a></li>
-            {%- elif builder == 'html' %}
-              <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}">Show Source</a></li>
-            {%- endif %}
-            </ul>-->
-          {%- endif %}
-          {%- if customsidebar %}
-          {{ rendertemplate(customsidebar) }}
-          {%- endif %}
-          {%- block sidebarsearch %}
-          {%- if pagename != "search" %}
-            <h3>{{ builder == 'web' and 'Keyword' or 'Quick' }} search</h3>
-            <form class="search" action="{{ pathto('search') }}" method="get">
-              <input type="text" name="q" size="18" /> <input type="submit" value="Go" />
-              <input type="hidden" name="check_keywords" value="yes" />
-              <input type="hidden" name="area" value="default" />
-            </form>
-            {%- if builder == 'web' %}
-            <p style="font-size: 90%">Enter a module, class or function name.</p>
-            {%- endif %}
-          {%- endif %}
-          {%- endblock %}
-        </div>
-      </div>
-      {%- endif %}
-{%- endmacro -%}
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    {%- if builder != 'htmlhelp' %}
-      {%- set titlesuffix = " &mdash; " + docstitle %}
-    {%- endif %}
-    <title>{{ title|striptags }}{{ titlesuffix }}</title>
-    {%- if builder == 'web' %}
-    <link rel="stylesheet" href="{{ pathto('index') }}?do=stylesheet{%
-      if in_admin_panel %}&admin=yes{% endif %}" type="text/css" />
-    {%- for link, type, title in page_links %}
-    <link rel="alternate" type="{{ type|e(true) }}" title="{{ title|e(true) }}" href="{{ link|e(true) }}" />
-    {%- endfor %}
-    {%- else %}
-    <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
-    <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
-    {%- endif %}
-    {%- if builder != 'htmlhelp' %}
-    <script type="text/javascript">
-      var DOCUMENTATION_OPTIONS = {
-          URL_ROOT:    '{{ pathto("", 1) }}',
-          VERSION:     '{{ release }}',
-          COLLAPSE_MODINDEX: false,
-          FILE_SUFFIX: '{{ file_suffix }}'
-      };
-    </script>
-    <script type="text/javascript" src="{{ pathto('_static/jquery.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/interface.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/doctools.js', 1) }}"></script>
-    <script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
-    {%- if use_opensearch %}
-    <link rel="search" type="application/opensearchdescription+xml"
-          title="Search within {{ docstitle }}"
-          href="{{ pathto('_static/opensearch.xml', 1) }}"/>
-    {%- endif %}
-    {%- if favicon %}
-    <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
-    {%- endif %}
-    {%- endif %}
-{%- block rellinks %}
-    {%- if hasdoc('about') %}
-    <link rel="author" title="About these documents" href="{{ pathto('about') }}" />
-    {%- endif %}
-    <link rel="contents" title="Global table of contents" href="{{ pathto('contents') }}" />
-    <link rel="index" title="Global index" href="{{ pathto('genindex') }}" />
-    <link rel="search" title="Search" href="{{ pathto('search') }}" />
-    {%- if hasdoc('copyright') %}
-    <link rel="copyright" title="Copyright" href="{{ pathto('copyright') }}" />
-    {%- endif %}
-    <link rel="top" title="{{ docstitle }}" href="{{ pathto('index') }}" />
-    {%- if parents %}
-    <link rel="up" title="{{ parents[-1].title|striptags }}" href="{{ parents[-1].link|e }}" />
-    {%- endif %}
-    {%- if next %}
-    <link rel="next" title="{{ next.title|striptags }}" href="{{ next.link|e }}" />
-    {%- endif %}
-    {%- if prev %}
-    <link rel="prev" title="{{ prev.title|striptags }}" href="{{ prev.link|e }}" />
-    {%- endif %}
-{%- endblock %}
-{%- block extrahead %}{% endblock %}
-  </head>
-  <body>
-
-{% block logilablogo %}
-<div class="logilablogo">
-	<a class="logogo" href="http://www.cubicweb.org"><img border="0" src="{{ pathto('_static/cubicweb.png', 1) }}"/></a>
-  </div>
-{% endblock %}
-
-{%- block relbar1 %}{{ relbar() }}{% endblock %}
-
-{%- block sidebar1 %}{# possible location for sidebar #}{% endblock %}
-
-{%- block document %}
-    <div class="document">
-      <div class="documentwrapper">
-      {%- if builder != 'htmlhelp' %}
-        <div class="bodywrapper">
-      {%- endif %}
-          <div class="body">
-            {% block body %}{% endblock %}
-          </div>
-      {%- if builder != 'htmlhelp' %}
-        </div>
-      {%- endif %}
-      </div>
-{%- endblock %}
-
-{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
-      <div class="clearer"></div>
-    </div>
-
-{%- block relbar2 %}{{ relbar() }}{% endblock %}
-
-{%- block footer %}
-    <div class="footer">
-    {%- if hasdoc('copyright') %}
-      &copy; <a href="{{ pathto('copyright') }}">Copyright</a> {{ copyright }}.
-    {%- else %}
-      &copy; Copyright {{ copyright }}.
-    {%- endif %}
-    {%- if last_updated %}
-      Last updated on {{ last_updated }}.
-    {%- endif %}
-    {%- if show_sphinx %}
-      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
-    {%- endif %}
-    </div>
-{%- endblock %}
-  </body>
-</html>
--- a/doc/book/en/MERGE_ME-tut-create-app.en.txt	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,386 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-
-Tutoriel : créer votre première application web pour Google AppEngine
-=====================================================================
-
-[TRANSLATE ME TO FRENCH]
-
-This tutorial will guide you step by step to build a blog application 
-and discover the unique features of `LAX`. It assumes that you followed
-the :ref:`installation` guidelines and that both the `AppEngine SDK` and the
-`LAX` framework are setup on your computer.
-
-Creating a new application
---------------------------
-
-We choosed in this tutorial to develop a blog as an example of web application
-and will go through each required steps/actions to have it running with `LAX`.
-When you installed `LAX`, you saw a directory named ``skel``. Make a copy of
-this directory and call it ``BlogDemo``.
-
-The location of this directory does not matter. But once decided, make sure your ``PYTHONPATH`` is properly set (:ref:`installation`).
-
-
-Defining a schema
------------------
-
-With `LAX`, the schema/datamodel is the core of the application. This is where
-you will define the type of content you have to hanlde in your application.
-
-Let us start with something simple and improve on it iteratively. 
-
-In schema.py, we define two entities: ``Blog`` and ``BlogEntry``.
-
-::
-
-  class Blog(EntityType):
-      title = String(maxsize=50, required=True)
-      description = String()
-
-  class BlogEntry(EntityType):
-      title = String(maxsize=100, required=True)
-      publish_date = Date(default='TODAY')
-      text = String(fulltextindexed=True)
-      category = String(vocabulary=('important','business'))
-      entry_of = SubjectRelation('Blog', cardinality='?*')
-
-A Blog has a title and a description. The title is a string that is
-required by the class EntityType and must be less than 50 characters. 
-The description is a string that is not constrained.
-
-A BlogEntry has a title, a publish_date and a text. The title is a
-string that is required and must be less than 100 characters. The
-publish_date is a Date with a default value of TODAY, meaning that
-when a BlogEntry is created, its publish_date will be the current day
-unless it is modified. The text is a string that will be indexed in
-the full-text index and has no constraint.
-
-A BlogEntry also has a relationship ``entry_of`` that link it to a
-Blog. The cardinality ``?*`` means that a BlogEntry can be part of
-zero or one Blog (``?`` means `zero or one`) and that a Blog can
-have any number of BlogEntry (``*`` means `any number including
-zero`). For completeness, remember that ``+`` means `one or more`.
-
-Running the application
------------------------
-
-Defining this simple schema is enough to get us started. Make sure you
-followed the setup steps described in detail in the installation
-chapter (especially visiting http://localhost:8080/_load as an
-administrator), then launch the application with the command::
-
-   python dev_appserver.py BlogDemo
-
-and point your browser at http://localhost:8080/ (if it is easier for
-you, use the on-line demo at http://lax.appspot.com/).
-
-.. image:: images/lax-book.00-login.en.png
-   :alt: login screen
-
-After you log in, you will see the home page of your application. It
-lists the entity types: Blog and BlogEntry. If these links read
-``blog_plural`` and ``blogentry_plural`` it is because
-internationalization (i18n) is not working for you yet. Please ignore
-this for now.
-
-.. image:: images/lax-book.01-start.en.png
-   :alt: home page
-
-Creating system entities
-------------------------
-You can only create new users if you decided not to use google authentication.
-
-
-[WRITE ME : create users manages permissions etc]
-
-
-
-Creating application entites
-----------------------------
-
-Create a Blog
-~~~~~~~~~~~~~
-
-Let us create a few of these entities. Click on the [+] at the right
-of the link Blog.  Call this new Blog ``Tech-blog`` and type in
-``everything about technology`` as the description, then validate the
-form by clicking on ``Validate``.
-
-.. image:: images/lax-book.02-create-blog.en.png
-   :alt: from to create blog
-
-Click on the logo at top left to get back to the home page, then
-follow the Blog link that will list for you all the existing Blog.
-You should be seeing a list with a single item ``Tech-blog`` you
-just created.
-
-.. image:: images/lax-book.03-list-one-blog.en.png
-   :alt: displaying a list of a single blog
-
-Clicking on this item will get you to its detailed description except
-that in this case, there is not much to display besides the name and
-the phrase ``everything about technology``.
-
-.. image:: images/lax-book.04-detail-one-blog.en.png
-  :alt: displaying the detailed view of a blog
-
-Now get back to the home page by clicking on the top-left logo, then
-create a new Blog called ``MyLife`` and get back to the home page
-again to follow the Blog link for the second time. The list now
-has two items.
-
-.. image:: images/lax-book.05-list-two-blog.en.png
-   :alt: displaying a list of two blogs
-
-
-Create a BlogEntry
-~~~~~~~~~~~~~~~~~~
-
-Get back to the home page and click on [+] at the right of the link
-BlogEntry. Call this new entry ``Hello World`` and type in some text
-before clicking on ``Validate``. You added a new blog entry without
-saying to what blog it belongs. There is a box on the left entitled
-``actions``, click on the menu item ``modify``. You are back to the form
-to edit the blog entry you just created, except that the form now has
-another section with a combobox titled ``add relation``. Chose
-``entry_of`` in this menu and a second combobox appears where you pick
-``MyLife``. 
-
-You could also have, at the time you started to fill the form for a
-new entity BlogEntry, hit ``Apply`` instead of ``Validate`` and the 
-combobox titled ``add relation`` would have showed up.
-
-.. image:: images/lax-book.06-add-relation-entryof.en.png
-   :alt: editing a blog entry to add a relation to a blog
-
-Validate the changes by clicking ``Validate``. The entity BlogEntry
-that is displayed now includes a link to the entity Blog named
-``MyLife``.
-
-.. image:: images/lax-book.07-detail-one-blogentry.en.png
-   :alt: displaying the detailed view of a blogentry
-
-Remember that all of this was handled by the framework and that the
-only input that was provided so far is the schema. To get a graphical
-view of the schema, run the ``laxctl genschema BlogDemo`` command as
-explained in the installation section and point your browser to the
-URL http://localhost:8080/schema
-
-.. image:: images/lax-book.08-schema.en.png
-   :alt: graphical view of the schema (aka data-model)
-
-Site configuration
-------------------
-
-.. image:: images/lax-book.03-site-config-panel.en.png
-
-This panel allows you to configure the appearance of your application site.
-Six menus are available and we will go through each of them to explain how
-to use them.
-
-Navigation
-~~~~~~~~~~
-This menu provides you a way to adjust some navigation options depending on
-your needs, such as the number of entities to display by page of results.
-Follows the detailled list of available options:
-  
-* navigation.combobox-limit: maximum number of entities to display in related
-  combo box (sample format: 23)
-* navigation.page-size: maximum number of objects displayed by page of results 
-  (sample format: 23)
-* navigation.related-limit: maximum number of related entities to display in 
-  the primary view (sample format: 23)
-* navigation.short-line-size: maximum number of characters in short description
-  (sample format: 23)
-
-UI
-~~
-This menu provides you a way to customize the user interface settings such as
-date format or encoding in the produced html.
-Follows the detailled list of available options:
-
-* ui.date-format : how to format date in the ui ("man strftime" for format description)
-* ui.datetime-format : how to format date and time in the ui ("man strftime" for format
-  description)
-* ui.default-text-format : default text format for rich text fields.
-* ui.encoding : user interface encoding
-* ui.fckeditor : should html fields being edited using fckeditor (a HTML WYSIWYG editor).
-  You should also select text/html as default text format to actually get fckeditor.
-* ui.float-format : how to format float numbers in the ui
-* ui.language : language of the user interface
-* ui.main-template : id of main template used to render pages
-* ui.site-title	: site title, which is displayed right next to the logo in the header
-* ui.time-format : how to format time in the ui ("man strftime" for format description)
-
-
-Actions
-~~~~~~~
-This menu provides a way to configure the context in which you expect the actions
-to be displayed to the user and if you want the action to be visible or not. 
-You must have notice that when you view a list of entities, an action box is 
-available on the left column which display some actions as well as a drop-down 
-menu for more actions. 
-
-The context available are:
-
-* mainactions : actions listed in the left box
-* moreactions : actions listed in the `more` menu of the left box
-* addrelated : add actions listed in the left box
-* useractions : actions listed in the first section of drop-down menu 
-  accessible from the right corner user login link
-* siteactions : actions listed in the second section of drop-down menu
-  accessible from the right corner user login link
-* hidden : select this to hide the specific action
-
-Boxes
-~~~~~
-The application has already a pre-defined set of boxes you can use right away. 
-This configuration section allows you to place those boxes where you want in the
-application interface to customize it. 
-
-The available boxes are:
-
-* actions box : box listing the applicable actions on the displayed data
-
-* boxes_blog_archives_box : box listing the blog archives 
-
-* possible views box : box listing the possible views for the displayed data
-
-* rss box : RSS icon to get displayed data as a RSS thread
-
-* search box : search box
-
-* startup views box : box listing the configuration options available for 
-  the application site, such as `Preferences` and `Site Configuration`
-
-Components
-~~~~~~~~~~
-[WRITE ME]
-
-Contextual components
-~~~~~~~~~~~~~~~~~~~~~
-[WRITE ME]
-
-Set-up a workflow
------------------
-
-Before starting, make sure you refresh your mind by reading [link to
-definition_workflow chapter].
-
-We want to create a workflow to control the quality of the BlogEntry 
-submitted on your application. When a BlogEntry is created by a user
-its state should be `submitted`. To be visible to all, it needs to
-be in the state `published`. To move from `submitted` to `published`
-we need a transition that we can name `approve_blogentry`.
-
-We do not want every user to be allowed to change the state of a 
-BlogEntry. We need to define a group of user, `moderators`, and 
-this group will have appropriate permissions to approve BlogEntry
-to be published and visible to all.
-
-There are two ways to create a workflow, form the user interface,
-and also by defining it in ``migration/postcreate.py``. This script
-is executed each time a new ``./bin/laxctl db-init`` is done. 
-If you create the states and transitions through the user interface
-this means that next time you will need to initialize the database
-you will have to re-create all the entities. 
-We strongly recommand you create the workflow in ``migration\postcreate.py``
-and we will now show you how.
-The user interface would only be a reference for you to view the states 
-and transitions but is not the appropriate interface to define your
-application workflow.
-
-Update the schema
-~~~~~~~~~~~~~~~~~
-To enable a BlogEntry to have a State, we have to define a relation
-``in_state`` in the schema of BlogEntry. Please do as follows, add
-the line ``in_state (...)``::
-
-  class BlogEntry(EntityType):
-      title = String(maxsize=100, required=True)
-      publish_date = Date(default='TODAY')
-      text_format = String(meta=True, internationalizable=True, maxsize=50,
-                           default='text/rest', constraints=[format_constraint])
-      text = String(fulltextindexed=True)
-      category = String(vocabulary=('important','business'))
-      entry_of = SubjectRelation('Blog', cardinality='?*')
-      in_state = SubjectRelation('State', cardinality='1*')
-
-As you updated the schema, you will have re-execute ``./bin/laxctl db-init``
-to initialize the database and migrate your existing entities.
-[WRITE ABOUT MIGRATION]
-
-Create states, transitions and group permissions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-At the time the ``postcreate.py`` script is executed, several methods
-can be used. They are all defined in the ``class ServerMigrationHelper``.
-We will only discuss the method we use to create a wrokflow here.
-
-To define our workflow for BlogDemo, please add the following lines
-to ``migration/postcreate.py``::
-  
-  _ = unicode
-
-  moderators      = add_entity('CWGroup', name=u"moderators")
-
-  submitted = add_state(_('submitted'), 'BlogEntry', initial=True)
-  published = add_state(_('published'), 'BlogEntry')
-
-  add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),)
-
-  checkpoint()
-
-``add_entity`` is used here to define the new group of users that we
-need to define the transitions, `moderators`.
-If this group required by the transition is not defined before the
-transition is created, it will not create the relation `transition 
-require the group moderator`.
-
-``add_state`` expects as the first argument the name of the state you are
-willing to create, then the entity type on which the state can be applied, 
-and an optionnal argument to set if the state is the initial state
-of the entity type or not.
-
-``add_transition`` expects as the first argument the name of the 
-transition, then the entity type on which we can apply the transition,
-then the list of possible initial states from which the transition
-can be applied, the target state of the transition, and the permissions
-(e.g. list of the groups of users who can apply the transition).
-
-.. image:: images/lax-book.03-transitions-view.en.png
-
-You can now notice that in the actions box of a BlogEntry, the state
-is now listed as well as the possible transitions from this state
-defined by the workflow. This transition, as defined in the workflow,
-will only being displayed for the users belonging to the group
-moderators of managers.
-
-Change view permission
-~~~~~~~~~~~~~~~~~~~~~~
-
-
-
-Conclusion
-----------
-
-Exercise
-~~~~~~~~
-
-Create new blog entries in ``Tech-blog``.
-
-What we learned
-~~~~~~~~~~~~~~~
-
-Creating a simple schema was enough to set up a new application that
-can store blogs and blog entries. 
-
-What is next ?
-~~~~~~~~~~~~~~
-
-Although the application is fully functionnal, its look is very
-basic. In the following section we will learn to create views to
-customize how data is displayed.
-
-
--- a/doc/book/en/MERGE_ME-tut-create-gae-app.en.txt	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _tutorielGAE:
-
-Tutoriel : créer votre première application web pour Google AppEngine
-=====================================================================
-
-Ce tutoriel va vous guider pas à pas a construire une apllication web 
-de gestion de Blog afin de vous faire découvrir les fonctionnalités de
-*CubicWeb*.
-
-Nous supposons que vous avec déjà suivi le guide :ref:`installationGAE`.
-
-
-Créez une nouvelle application
-------------------------------
-
-Nous choisissons dans ce tutoriel de développer un blog comme un exemple
-d'application web et nous allons expliciter toutes les étapes nécessaires
-à sa réalisation.  
-
-::
-  
-  cubicweb-ctl newgapp blogdemo
-
-`newgapp` est la commande permettant de créer une instance *CubicWeb* pour
-le datastore.
-
-Assurez-vous que votre variable d'environnement ``PYTHONPATH`` est correctement
-initialisée (:ref:`installationGAE`)
-
-Définissez un schéma
---------------------
-
-Le modèle de données ou schéma est au coeur d'une application *CubicWeb*.
-C'est là où vous allez devoir définir le type de contenu que votre application
-devra gérer.
-
-Commençons par un schéma simple que nous améliorerons progressivemment.
-
-Une fois votre instance ``blogdemo`` crée, vous trouverez un fichier ``schema.py``
-contenant la définition des entités suivantes : ``Blog`` and ``BlogEntry``.
-
-::
-
-  class Blog(EntityType):
-      title = String(maxsize=50, required=True)
-      description = String()
-
-  class BlogEntry(EntityType):
-      title = String(maxsize=100, required=True)
-      publish_date = Date(default='TODAY')
-      text = String(fulltextindexed=True)
-      category = String(vocabulary=('important','business'))
-      entry_of = SubjectRelation('Blog', cardinality='?*')
-
-
-Un ``Blog`` a un titre et une description. Le titre est une chaîne 
-de caractères requise par la classe parente EntityType and ne doit
-pas excéder 50 caractères. La description est une chaîne de 
-caractères sans contraintes.
-
-Une ``BlogEntry`` a un titre, une date de publication et du texte
-étant son contenu. Le titre est une chaîne de caractères qui ne 
-doit pas excéder 100 caractères. La date de publication est de type Date et a
-pour valeur par défaut TODAY, ce qui signifie que lorsqu'une 
-``BlogEntry`` sera créée, sa date de publication sera la date
-courante a moins de modifier ce champ. Le texte est une chaîne de
-caractères qui sera indexée en plein texte et sans contraintes.
-
-Une ``BlogEntry`` a aussi une relation nommée ``entry_of`` qui la
-relie à un ``Blog``. La cardinalité ``?*`` signifie que BlogEntry
-peut faire partie de zero a un Blog (``?`` signifie `zero ou un`) et
-qu'un Blog peut avoir une infinité de BlogEntry (``*`` signifie
-`n'importe quel nombre incluant zero`). 
-Par soucis de complétude, nous rappellerons que ``+`` signifie
-`un ou plus`.
-
-Lancez l'application
---------------------
-
-Définir ce simple schéma est suffisant pour commencer. Assurez-vous 
-que vous avez suivi les étapes décrites dans la section installation
-(en particulier visitez http://localhost:8080/_load en tant qu'administrateur
-afin d'initialiser le datastore), puis lancez votre application avec la commande ::
-   
-   python dev_appserver.py BlogDemo
-
-puis dirigez vous vers http://localhost:8080/ (ou si c'est plus facile
-vous pouvez utiliser la démo en ligne http://lax.appspot.com/).
-[FIXME] -- changer la demo en ligne en quelque chose qui marche (!)
-
-.. image:: images/lax-book.00-login.en.png
-   :alt: login screen
-
-Après vous être authentifié, vous arrivez sur la page d'accueil de votre 
-application. Cette page liste les types d'entités accessibles dans votre
-application, en l'occurrence : Blog et Articles. Si vous lisez ``blog_plural``
-et ``blogentry_plural`` cela signifie que l'internationalisation (i18n)
-n'a pas encore fonctionné. Ignorez cela pour le moment.
-
-.. image:: images/lax-book.01-start.en.png
-   :alt: home page
-
-Créez des entités système
--------------------------
-
-Vous ne pourrez créer de nouveaux utilisateurs que dans le cas où vous
-avez choisi de ne pas utiliser l'authentification Google.
-
-
-[WRITE ME : create users manages permissions etc]
-
-
-
-Créez des entités applicatives
-------------------------------
-
-Créez un Blog
-~~~~~~~~~~~~~
-
-Créons à présent quelques entités. Cliquez sur `[+]` sur la
-droite du lien Blog. Appelez cette nouvelle entité Blog ``Tech-Blog``
-et tapez pour la description ``everything about technology``,
-puis validez le formulaire d'édition en cliquant sur le bouton
-``Validate``.
-
-
-.. image:: images/lax-book.02-create-blog.en.png
-   :alt: from to create blog
-
-En cliquant sur le logo situé dans le coin gauche de la fenêtre,
-vous allez être redirigé vers la page d'accueil. Ensuite, si vous allez 
-sur le lien Blog, vous devriez voir la liste des entités Blog, en particulier
-celui que vous venez juste de créer ``Tech-Blog``.
-
-.. image:: images/lax-book.03-list-one-blog.en.png
-   :alt: displaying a list of a single blog
-
-Si vous cliquez sur ``Tech-Blog`` vous devriez obtenir une description
-détaillée, ce qui dans notre cas, n'est rien de plus que le titre
-et la phrase ``everything about technology``
-
-
-.. image:: images/lax-book.04-detail-one-blog.en.png
-   :alt: displaying the detailed view of a blog
-
-Maintenant retournons sur la page d'accueil et créons un nouveau
-Blog ``MyLife`` et retournons sur la page d'accueil, puis suivons
-le lien Blog et nous constatons qu'à présent deux blogs sont listés.
-
-.. image:: images/lax-book.05-list-two-blog.en.png
-   :alt: displaying a list of two blogs
-
-Créons un article
-~~~~~~~~~~~~~~~~~
-
-Revenons sur la page d'accueil et cliquons sur `[+]` à droite du lien
-`articles`. Appellons cette nouvelle entité ``Hello World`` et introduisons
-un peut de texte avant de ``Valider``. Vous venez d'ajouter un article
-sans avoir précisé à quel Blog il appartenait. Dans la colonne de gauche
-se trouve une boite intitulé ``actions``, cliquez sur le menu ``modifier``.
-Vous êtes de retour sur le formulaire d'édition de l'article que vous 
-venez de créer, à ceci près que ce formulaire a maintenant une nouvelle
-section intitulée ``ajouter relation``. Choisissez ``entry_of`` dans ce menu,
-cela va faire apparaitre une deuxième menu déroulant dans lequel vous
-allez pouvoir séléctionner le Blog ``MyLife``.
-
-Vous auriez pu aussi, au moment où vous avez crée votre article, sélectionner
-``appliquer`` au lieu de ``valider`` et le menu ``ajouter relation`` serait apparu.
-
-.. image:: images/lax-book.06-add-relation-entryof.en.png
-   :alt: editing a blog entry to add a relation to a blog
-
-Validez vos modifications en cliquant sur ``Valider``. L'entité article
-qui est listée contient maintenant un lien vers le Blog auquel il 
-appartient, ``MyLife``.
-
-.. image:: images/lax-book.07-detail-one-blogentry.en.png
-   :alt: displaying the detailed view of a blogentry
-
-Rappelez-vous que pour le moment, tout a été géré par la plate-forme
-*CubicWeb* et que la seule chose qui a été fournie est le schéma de
-données. D'ailleurs pour obtenir une vue graphique du schéma, exécutez
-la commande ``laxctl genschema blogdemo`` et vous pourrez visualiser
-votre schéma a l'URL suivante : http://localhost:8080/schema
-
-.. image:: images/lax-book.08-schema.en.png
-   :alt: graphical view of the schema (aka data-model)
-
-
-Change view permission
-~~~~~~~~~~~~~~~~~~~~~~
-
-
-
-Conclusion
-----------
-
-Exercise
-~~~~~~~~
-
-Create new blog entries in ``Tech-blog``.
-
-What we learned
-~~~~~~~~~~~~~~~
-
-Creating a simple schema was enough to set up a new application that
-can store blogs and blog entries. 
-
-What is next ?
-~~~~~~~~~~~~~~
-
-Although the application is fully functionnal, its look is very
-basic. In the following section we will learn to create views to
-customize how data is displayed.
-
-
--- a/doc/book/en/_themes/cubicweb/layout.html	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-{% extends "basic/layout.html" %}
-
-{%- block extrahead %}
-<!--[if lte IE 6]>
-<link rel="stylesheet" href="{{ pathto('_static/ie6.css', 1) }}" type="text/css" media="screen" charset="utf-8" />
-<![endif]-->
-{%- if theme_favicon %}
-<link rel="shortcut icon" href="{{ pathto('_static/'+theme_favicon, 1) }}"/>
-{%- endif %}
-
-{%- if theme_canonical_url %}
-<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html"/>
-{%- endif %}
-{% endblock %}
-
-{% block header %}
-
-{% if theme_in_progress|tobool %}
-    <img style="position: fixed; display: block; width: 165px; height: 165px; bottom: 60px; right: 0; border: 0;" src="{{ pathto('_static/in_progress.png', 1) }}" alt="Documentation in progress" />
-{% endif %}
-
-{% if theme_outdated|tobool %}
-    <div style="bottom: 60px; right: 20px;position: fixed;"><a href="{{ latest_url }}" class="btn btn-large btn-danger"><strong>&gt;</strong> Read the latest version of this page</a></div>
-{% endif %}
-
-<div class="header-small">
-	{%- if theme_logo %}
-	{% set img, ext = theme_logo.split('.', -1) %}
-	<div class="logo-small">
-		<a href="{{ pathto(master_doc) }}">
-      		<img class="logo" src="{{ pathto('_static/%s-small.%s' % (img, ext), 1)}}" alt="Logo"/>
-		</a>
-  	</div>
-  	{%- endif %}
-</div>
-{% endblock %}
-
-{%- macro relbar() %}
-<div class="related">
-	<h3>{{ _('Navigation') }}</h3>
-	<ul>
-		{%- for rellink in rellinks %}
-		<li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
-			<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
-			{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
-			{%- if not loop.first %}{{ reldelim2 }}{% endif %}
-		</li>
-		{%- endfor %}
-    	{%- block rootrellink %}
-    	<li><a href="{{ pathto(master_doc) }}">{{ docstitle|e }}</a>{{ reldelim1 }}</li>
-    	{%- endblock %}
-    	{%- for parent in parents %}
-          <li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
-        {%- endfor %}
-        {%- block relbaritems %} {% endblock %}
-  	</ul>
-</div>
-{%- endmacro %}
-
-{%- block sidebarlogo %}{%- endblock %}
-{%- block sidebarsourcelink %}{%- endblock %}
--- a/doc/book/en/_themes/cubicweb/static/cubicweb.css_t	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * cubicweb.css_t
- * ~~~~~~~~~~~~~~
- *
- * Sphinx stylesheet -- cubicweb theme.
- *
- * :copyright: Copyright 2014 by the Cubicweb team, see AUTHORS.
- * :license: LGPL, see LICENSE for details.
- *
- */
- 
-@import url("pyramid.css");
-
-div.header-small {
-  background-image: linear-gradient(white, #e2e2e2);
-  border-bottom: 1px solid #bbb;
-}
-
-div.logo-small {
-  padding: 10px;
-}
-
-img.logo {
-  width: 150px;
-}
-
-div.related a {
-  color: #e6820e;
-}
-
-a, a .pre {
-  color: #e6820e;
-}
--- a/doc/book/en/_themes/cubicweb/static/cubicweb.ico	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../../../../../../web/data/favicon.ico
\ No newline at end of file
--- a/doc/book/en/_themes/cubicweb/static/logo-cubicweb-small.svg	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-logo-cubicweb.svg
\ No newline at end of file
--- a/doc/book/en/_themes/cubicweb/static/logo-cubicweb.svg	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../../../../../../web/data/logo-cubicweb.svg
\ No newline at end of file
--- a/doc/book/en/_themes/cubicweb/theme.conf	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-[theme]
-inherit = pyramid
-pygments_style = sphinx.pygments_styles.PyramidStyle
-stylesheet = cubicweb.css
-
-
-[options]
-logo = logo-cubicweb.svg
-favicon = cubicweb.ico
-in_progress = false
-outdated = false
-canonical_url = 
--- a/doc/book/en/additionnal_services/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-Additional services
-===================
-
-In this chapter, we introduce services crossing the *web -
-repository - administration* organisation of the first parts of the
-CubicWeb book. Those services can be either proper services (like the
-undo functionality) or mere *topical cross-sections* across CubicWeb.
-
-.. toctree::
-   :maxdepth: 2
-
-   undo
-
-
--- a/doc/book/en/additionnal_services/undo.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-Undoing changes in CubicWeb
----------------------------
-
-Many desktop applications offer the possibility for the user to
-undo its last changes : this *undo feature* has now been
-integrated into the CubicWeb framework. This document will
-introduce you to the *undo feature* both from the end-user and the
-application developer point of view.
-
-But because a semantic web application and a common desktop
-application are not the same thing at all, especially as far as
-undoing is concerned, we will first introduce *what* is the *undo
-feature* for now.
-
-What's *undoing* in a CubicWeb application
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-What is an *undo feature* is quite intuitive in the context of a
-desktop application. But it is a bit subtler in the context of a
-Semantic Web application. This section introduces some of the main
-differences between a classical desktop and a Semantic Web
-applications to keep in mind in order to state precisely *what we
-want*.
-
-The notion transactions
-```````````````````````
-
-A CubicWeb application acts upon an *Entity-Relationship* model,
-described by a schema. This allows to ensure some data integrity
-properties. It also implies that changes are made by all-or-none
-groups called *transactions*, such that the data integrity is
-preserved whether the transaction is completely applied *or* none
-of it is applied.
-
-A transaction can thus include more actions than just those
-directly required by the main purpose of the user.  For example,
-when a user *just* writes a new blog entry, the underlying
-*transaction* holds several *actions* as illustrated below :
-
-* By admin on 2012/02/17 15:18 - Created Blog entry : Torototo
-
-  #. Created Blog entry : Torototo
-  #. Added relation : Torototo owned by admin
-  #. Added relation : Torototo blog entry of Undo Blog
-  #. Added relation : Torototo in state draft (draft)
-  #. Added relation : Torototo created by admin
-
-Because of the very nature (all-or-none) of the transactions, the
-"undoable stuff" are the transactions and not the actions !
-
-Public and private actions within a transaction
-```````````````````````````````````````````````
-
-Actually, within the *transaction* "Created Blog entry :
-Torototo", two of those *actions* are said to be *public* and
-the others are said to be *private*. *Public* here means that the
-public actions (1 and 3) were directly requested by the end user ;
-whereas *private* means that the other actions (2, 4, 5) were
-triggered "under the hood" to fulfill various requirements for the
-user operation (ensuring integrity, security, ... ).
-
-And because quite a lot of actions can be triggered by a "simple"
-end-user request, most of which the end-user is not (and does not
-need or wish to be) aware, only the so-called public actions will
-appear [1]_ in the description of the an undoable transaction.
-
-* By admin on 2012/02/17 15:18 - Created Blog entry : Torototo
-
-  #. Created Blog entry : Torototo
-  #. Added relation : Torototo blog entry of Undo Blog
-
-But note that both public and private actions will be undone
-together when the transaction is undone.
-
-(In)dependent transactions : the simple case
-````````````````````````````````````````````
-
-A CubicWeb application can be used *simultaneously* by different users
-(whereas a single user works on an given office document at a
-given time), so that there is not always a single history
-time-line in the CubicWeb case. Moreover CubicWeb provides
-security through the mechanism of *permissions* granted to each
-user. This can lead to some transactions *not* being undoable in
-some contexts.
-
-In the simple case two (unprivileged) users Alice and Bob make
-relatively independent changes : then both Alice and Bob can undo
-their changes. But in some case there is a clean dependency
-between Alice's and Bob's actions or between actions of one of
-them. For example let's suppose that :
-
-- Alice has created a blog,
-- then has published a first post inside,
-- then Bob has published a second post in the same blog,
-- and finally Alice has updated its post contents.
-
-Then it is clear that Alice can undo her contents changes and Bob
-can undo his post creation independently. But Alice can not undo
-her post creation while she has not first undone her changes.
-It is also clear that Bob should *not* have the
-permissions to undo any of Alice's transactions.
-
-
-More complex dependencies between transactions
-``````````````````````````````````````````````
-
-But more surprising things can quickly happen. Going back to the
-previous example, Alice *can* undo the creation of the blog after
-Bob has published its post in it ! But this is possible only
-because the schema does not *require* for a post to be in a
-blog. Would the *blog entry of* relation have been mandatory, then
-Alice could not have undone the blog creation because it would
-have broken integrity constraint for Bob's post.
-
-When a user attempts to undo a transaction the system will check
-whether a later transaction has explicit dependency on the
-would-be-undone transaction. In this case the system will not even
-attempt the undo operation and inform the user.
-
-If no such dependency is detected the system will attempt the undo
-operation but it can fail, typically because of integrity
-constraint violations. In such a case the undo operation is
-completely [3]_ rollbacked.
-
-
-The *undo feature* for CubicWeb end-users
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The exposition of the undo feature to the end-user through a Web
-interface is still quite basic and will be improved toward a
-greater usability. But it is already fully functional.  For now
-there are two ways to access the *undo feature* as long as the it
-has been activated in the instance configuration file with the
-option *undo-support=yes*.
-
-Immediately after having done the change to be canceled through
-the **undo** link in the message. This allows to undo an
-hastily action immediately. For example, just after having
-validated the creation of the blog entry *A second blog entry* we
-get the following message, allowing to undo the creation.
-
-.. image:: /images/undo_mesage_w600.png
-   :width: 600px
-   :alt: Screenshot of the undo link in the message
-   :align: center
-
-At any time we can access the **undo-history view** accessible from the
-start-up page.
-
-.. image:: /images/undo_startup-link_w600.png
-   :width: 600px
-   :alt: Screenshot of the startup menu with access to the history view
-   :align: center
-
-This view will provide inspection of the transaction and their (public)
-actions. Each transaction provides its own **undo** link. Only the
-transactions the user has permissions to see and undo will be shown.
-
-.. image:: /images/undo_history-view_w600.png
-   :width: 600px
-   :alt: Screenshot of the undo history main view
-   :align: center
-
-If the user attempts to undo a transaction which can't be undone or
-whose undoing fails, then a message will explain the situation and
-no partial undoing will be left behind.
-
-This is all for the end-user side of the undo mechanism : this is
-quite simple indeed ! Now, in the following section, we are going
-to introduce the developer side of the undo mechanism.
-
-The *undo feature* for CubicWeb application developers
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A word of warning : this section is intended for developers,
-already having some knowledge of what's under CubicWeb's hood. If
-it is not *yet* the case, please refer to CubicWeb documentation
-http://docs.cubicweb.org/ .
-
-Overview
-````````
-
-The core of the undo mechanisms is at work in the *native source*,
-beyond the RQL. This does mean that *transactions* and *actions*
-are *no entities*. Instead they are represented at the SQL level
-and exposed through the *DB-API* supported by the repository
-*Connection* objects.
-
-Once the *undo feature* has been activated in the instance
-configuration file with the option *undo-support=yes*, each
-mutating operation (cf. [2]_) will be recorded in some special SQL
-table along with its associated transaction. Transaction are
-identified by a *txuuid* through which the functions of the
-*DB-API* handle them.
-
-On the web side the last commited transaction *txuuid* is
-remembered in the request's data to allow for imediate undoing
-whereas the *undo-history view* relies upon the *DB-API* to list
-the accessible transactions. The actual undoing is performed by
-the *UndoController* accessible at URL of the form
-`www.my.host/my/instance/undo?txuuid=...`
-
-The repository side
-```````````````````
-
-Please refer to the file `cubicweb/server/sources/native.py` and
-`cubicweb/transaction.py` for the details.
-
-The undoing information is mainly stored in three SQL tables:
-
-`transactions`
-    Stores the txuuid, the user eid and the date-and-time of
-    the transaction. This table is referenced by the two others.
-
-`tx_entity_actions`
-    Stores the undo information for actions on entities.
-
-`tx_relation_actions`
-    Stores the undo information for the actions on relations.
-
-When the undo support is activated, entries are added to those
-tables for each mutating operation on the data repository, and are
-deleted on each transaction undoing.
-
-Those table are accessible through the following methods of the
-repository `Connection` object :
-
-`undoable_transactions`
-    Returns a list of `Transaction` objects accessible to the user
-    and according to the specified filter(s) if any.
-
-`tx_info`
-    Returns a `Transaction` object from a `txuuid`
-
-`undo_transaction`
-    Returns the list of `Action` object for the given `txuuid`.
-
-    NB:  By default it only return *public* actions.
-
-The web side
-````````````
-
-The exposure of the *undo feature* to the end-user through the Web
-interface relies on the *DB-API* introduced above. This implies
-that the *transactions* and *actions* are not *entities* linked by
-*relations* on which the usual views can be applied directly.
-
-That's why the file `cubicweb/web/views/undohistory.py` defines
-some dedicated views to access the undo information :
-
-`UndoHistoryView`
-    This is a *StartupView*, the one accessible from the home
-    page of the instance which list all transactions.
-
-`UndoableTransactionView`
-    This view handles the display of a single `Transaction` object.
-
-`UndoableActionBaseView`
-    This (abstract) base class provides private methods to build
-    the display of actions whatever their nature.
-
-`Undoable[Add|Remove|Create|Delete|Update]ActionView`
-    Those views all inherit from `UndoableActionBaseView` and
-    each handles a specific kind of action.
-
-`UndoableActionPredicate`
-    This predicate is used as a *selector* to pick the appropriate
-    view for actions.
-
-Apart from this main *undo-history view* a `txuuid` is stored in
-the request's data `last_undoable_transaction` in order to allow
-immediate undoing of a hastily validated operation. This is
-handled in `cubicweb/web/application.py` in the `main_publish` and
-`add_undo_link_to_msg` methods for the storing and displaying
-respectively.
-
-Once the undo information is accessible, typically through a
-`txuuid` in an *undo* URL, the actual undo operation can be
-performed by the `UndoController` defined in
-`cubicweb/web/views/basecontrollers.py`. This controller basically
-extracts the `txuuid` and performs a call to `undo_transaction` and
-in case of an undo-specific error, lets the top level publisher
-handle it as a validation error.
-
-
-Conclusion
-~~~~~~~~~~
-
-The undo mechanism relies upon a low level recording of the
-mutating operation on the repository. Those records are accessible
-through some method added to the *DB-API* and exposed to the
-end-user either through a whole history view of through an
-immediate undoing link in the message box.
-
-The undo feature is functional but the interface and configuration
-options are still quite reduced. One major improvement would be to
-be able to filter with a finer grain which transactions or actions
-one wants to see in the *undo-history view*. Another critical
-improvement would be to enable the undo feature on a part only of
-the entity-relationship schema to avoid storing too much useless
-data and reduce the underlying overhead.
-
-But both functionality are related to the strong design choice not
-to represent transactions and actions as entities and
-relations. This has huge benefits in terms of safety and conceptual
-simplicity but prevents from using lots of convenient CubicWeb
-features such as *facets* to access undo information.
-
-Before developing further the undo feature or eventually revising
-this design choice, it appears that some return of experience is
-strongly needed. So don't hesitate to try the undo feature in your
-application and send us some feedback.
-
-
-Notes
-~~~~~
-
-.. [1] The end-user Web interface could be improved to enable
-       user to choose whether he wishes to see private actions.
-
-.. [2] There is only five kind of elementary actions (beyond
-       merely accessing data for reading):
-
-       * **C** : creating an entity
-       * **D** : deleting an entity
-       * **U** : updating an entity attributes
-       * **A** : adding a relation
-       * **R** : removing a relation
-
-.. [3] Meaning none of the actions in the transaction is
-       undone. Depending upon the application, it might make sense
-       to enable *partial* undo. That is to say undo in which some
-       actions could not be undo without preventing to undo the
-       others actions in the transaction (as long as it does not
-       break schema integrity). This is not forbidden by the
-       back-end but is deliberately not supported by the front-end
-       (for now at least).
--- a/doc/book/en/admin/additional-tips.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-
-.. _Additional Tips:
-
-Backups (mostly with postgresql)
---------------------------------
-
-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.
-
-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
-
-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
-
-Using :command:`cubicweb-ctl db-dump`
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-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>
-
-The postgres documentation for the `.pgpass` format can be found `here`_
-
-Then add the following command to the crontab of the user (`crontab -e`)::
-
-    # m h  dom mon dow   command
-    0 2 * * * cubicweb-ctl db-dump <instance>
-
-
-Backup ninja
-~~~~~~~~~~~~
-
-You can use a combination `backup-ninja`_ (which has a postgres script in the
-example directory), `backuppc`)_ (for versionning).
-
-Please note that in the *CubicWeb way* it adds a second location for your
-password which is error-prone.
-
-.. _`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/admin/config.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _ConfigEnv:
-
-Set-up of a *CubicWeb* environment
-==================================
-
-You can `configure the database`_ system of your choice:
-
-  - `PostgreSQL configuration`_
-  - `MySql configuration`_
-  - `SQLServer configuration`_
-  - `SQLite configuration`_
-
-For advanced features, have a look to:
-
-  - `Cubicweb resources configuration`_
-
-.. _`configure the database`: DatabaseInstallation_
-.. _`PostgreSQL configuration`: PostgresqlConfiguration_
-.. _`MySql configuration`: MySqlConfiguration_
-.. _`SQLServer configuration`: SQLServerConfiguration_
-.. _`SQLite configuration`: SQLiteConfiguration_
-.. _`Cubicweb resources configuration`: RessourcesConfiguration_
-
-
-
-.. _RessourcesConfiguration:
-
-Cubicweb resources configuration
---------------------------------
-
-.. autodocstring:: cubicweb.cwconfig
-
-
-.. _DatabaseInstallation:
-
-Databases configuration
------------------------
-
-Each instance can be configured with its own database connection information,
-that will be stored in the instance's :file:`sources` file. The database to use
-will be chosen when creating the instance. CubicWeb is known to run with
-Postgresql (recommended), SQLServer and SQLite, and may run with MySQL.
-
-Other possible sources of data include CubicWeb, Subversion, LDAP and Mercurial,
-but at least one relational database is required for CubicWeb to work. You do
-not need to install a backend that you do not intend to use for one of your
-instances. SQLite is not fit for production use, but it works well for testing
-and ships with Python, which saves installation time when you want to get
-started quickly.
-
-.. _PostgresqlConfiguration:
-
-PostgreSQL
-~~~~~~~~~~
-
-Many Linux distributions ship with the appropriate PostgreSQL packages.
-Basically, you need to install the following packages:
-
-* `postgresql` and `postgresql-client`, which will pull the respective
-  versioned packages (e.g. `postgresql-9.1` and `postgresql-client-9.1`) and,
-  optionally,
-* a `postgresql-plpython-X.Y` package with a version corresponding to that of
-  the aforementioned packages (e.g. `postgresql-plpython-9.1`).
-
-If you run postgres version prior to 8.3, you'll also need the
-`postgresql-contrib-8.X` package for full-text search extension.
-
-If you run postgres on another host than the |cubicweb| repository, you should
-install the `postgresql-client` package on the |cubicweb| host, and others on the
-database host.
-
-For extra details concerning installation, please refer to the `PostgreSQL
-project online documentation`_.
-
-.. _`PostgreSQL project online documentation`: http://www.postgresql.org/docs
-
-
-Database cluster
-++++++++++++++++
-
-If you already have an existing cluster and PostgreSQL server running, you do
-not need to execute the initilization step of your PostgreSQL database unless
-you want a specific cluster for |cubicweb| databases or if your existing
-cluster doesn't use the UTF8 encoding (see note below).
-
-To initialize a PostgreSQL cluster, use the command ``initdb``::
-
-    $ initdb -E UTF8 -D /path/to/pgsql
-
-Notice the encoding specification. This is necessary since |cubicweb| usually
-want UTF8 encoded database. If you use a cluster with the wrong encoding, you'll
-get error like::
-
-  new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)
-  HINT:  Use the same encoding as in the template database, or use template0 as template.
-
-Once initialized, start the database server PostgreSQL with the command::
-
-  $ postgres -D /path/to/psql
-
-If you cannot execute this command due to permission issues, please make sure
-that your username has write access on the database.  ::
-
-  $ chown username /path/to/pgsql
-
-Database authentication
-+++++++++++++++++++++++
-
-The database authentication is configured in `pg_hba.conf`. It can be either set
-to `ident sameuser` or `md5`.  If set to `md5`, make sure to use an existing
-user of your database.  If set to `ident sameuser`, make sure that your client's
-operating system user name has a matching user in the database. If not, please
-do as follow to create a user::
-
-  $ su
-  $ su - postgres
-  $ createuser -s -P username
-
-The option `-P` (for password prompt), will encrypt the password with the
-method set in the configuration file :file:`pg_hba.conf`.  If you do not use this
-option `-P`, then the default value will be null and you will need to set it
-with::
-
-  $ su postgres -c "echo ALTER USER username WITH PASSWORD 'userpasswd' | psql"
-
-The above login/password will be requested when you will create an instance with
-`cubicweb-ctl create` to initialize the database of your instance.
-
-Notice that the `cubicweb-ctl db-create` does database initialization that
-may requires a postgres superuser. That's why a login/password is explicitly asked
-at this step, so you can use there a superuser without using this user when running
-the instance. Things that require special privileges at this step:
-
-* database creation, require the 'create database' permission
-* install the plpython extension language (require superuser)
-* install the tsearch extension for postgres version prior to 8.3 (require superuser)
-
-To avoid using a super user each time you create an install, a nice trick is to
-install plpython (and tsearch when needed) on the special `template1` database,
-so they will be installed automatically when cubicweb databases are created
-without even with needs for special access rights. To do so, run ::
-
-  # Installation of plpythonu language by default ::
-  $ createlang -U pgadmin plpythonu template1
-  $ psql -U pgadmin template1
-  template1=# update pg_language set lanpltrusted=TRUE where lanname='plpythonu';
-
-Where `pgadmin` is a postgres superuser. The last command is necessary since by
-default plpython is an 'untrusted' language and as such can't be used by non
-superuser. This update fix that problem by making it trusted.
-
-To install the tsearch plain-text index extension on postgres prior to 8.3, run::
-
-    cat /usr/share/postgresql/8.X/contrib/tsearch2.sql | psql -U username template1
-
-
-.. _MySqlConfiguration:
-
-MySql
-~~~~~
-.. warning::
-    CubicWeb's MySQL support is not commonly used, so things may or may not work properly.
-
-You must add the following lines in ``/etc/mysql/my.cnf`` file::
-
-    transaction-isolation=READ-COMMITTED
-    default-storage-engine=INNODB
-    default-character-set=utf8
-    max_allowed_packet = 128M
-
-.. Note::
-    It is unclear whether mysql supports indexed string of arbitrary length or
-    not.
-
-
-.. _SQLServerConfiguration:
-
-SQLServer
-~~~~~~~~~
-
-As of this writing, support for SQLServer 2005 is functional but incomplete. You
-should be able to connect, create a database and go quite far, but some of the
-SQL generated from RQL queries is still currently not accepted by the
-backend. Porting to SQLServer 2008 is also an item on the backlog.
-
-The `source` configuration file may look like this (specific parts only are
-shown)::
-
-  [system]
-  db-driver=sqlserver2005
-  db-user=someuser
-  # database password not needed
-  #db-password=toto123
-  #db-create/init may ask for a pwd: just say anything
-  db-extra-arguments=Trusted_Connection
-  db-encoding=utf8
-
-
-You need to change the default settings on the database by running::
-
- ALTER DATABASE <databasename> SET READ_COMMITTED_SNAPSHOT ON;
-
-The ALTER DATABASE command above requires some permissions that your
-user may not have. In that case you will have to ask your local DBA to
-run the query for you.
-
-You can check that the setting is correct by running the following
-query which must return '1'::
-
-   SELECT is_read_committed_snapshot_on
-     FROM sys.databases WHERE name='<databasename>';
-
-
-
-.. _SQLiteConfiguration:
-
-SQLite
-~~~~~~
-
-SQLite has the great advantage of requiring almost no configuration. Simply
-use 'sqlite' as db-driver, and set path to the dabase as db-name. Don't specify
-anything for db-user and db-password, they will be ignore anyway.
-
-.. Note::
-  SQLite is great for testing and to play with cubicweb but is not suited for
-  production environments.
-
--- a/doc/book/en/admin/create-instance.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Creation of your first instance
-===============================
-
-Instance creation
------------------
-
-Now that we created a cube, we can create an instance and access it via a web
-browser. We will use a `all-in-one` configuration to simplify things ::
-
-  cubicweb-ctl create -c all-in-one mycube myinstance
-
-.. note::
-  Please note that we created a new cube for a demo purposes but
-  you could have used an existing cube available in our standard library
-  such as blog or person for example.
-
-A series of questions will be prompted to you, the default answer is usually
-sufficient. You can anyway modify the configuration later on by editing
-configuration files. When a login/password are requested to access the database
-please use the credentials you created at the time you configured the database
-(:ref:`PostgresqlConfiguration`).
-
-It is important to distinguish here the user used to access the database and the
-user used to login to the cubicweb instance. When an instance starts, it uses
-the login/password for the database to get the schema and handle low level
-transaction. But, when :command:`cubicweb-ctl create` asks for a manager
-login/psswd of *CubicWeb*, it refers to the user you will use during the
-development to administrate your web instance. It will be possible, later on,
-to use this user to create other users for your final web instance.
-
-
-Instance administration
------------------------
-
-start / stop
-~~~~~~~~~~~~
-
-When this command is completed, the definition of your instance is
-located in :file:`~/etc/cubicweb.d/myinstance/*`. To launch it, you
-just type ::
-
-  cubicweb-ctl start -D myinstance
-
-The option `-D` specifies the *debug mode* : the instance is not
-running in server mode and does not disconnect from the terminal,
-which simplifies debugging in case the instance is not properly
-launched. You can see how it looks by visiting the URL
-`http://localhost:8080` (the port number depends of your
-configuration). To login, please use the cubicweb administrator
-login/password you defined when you created the instance.
-
-To shutdown the instance, Crtl-C in the terminal window is enough.
-If you did not use the option `-D`, then type ::
-
-  cubicweb-ctl stop myinstance
-
-This is it! All is settled down to start developping your data model...
-
-.. note::
-
-  The output of `cubicweb-ctl start -D myinstance` can be
-  overwhelming. It is possible to reduce the log level with the
-  `--loglevel` parameter as in `cubicweb-ctl start -D myinstance -l
-  info` to filter out all logs under `info` gravity.
-
-upgrade
-~~~~~~~
-
-A manual upgrade step is necessary whenever a new version of CubicWeb or
-a cube is installed, in order to synchronise the instance's
-configuration and schema with the new code.  The command is::
-
-  cubicweb-ctl upgrade myinstance
-
-A series of questions will be asked. It always starts with a proposal
-to make a backup of your sources (where it applies). Unless you know
-exactly what you are doing (i.e. typically fiddling in debug mode, but
-definitely NOT migrating a production instance), you should answer YES
-to that.
-
-The remaining questions concern the migration steps of |cubicweb|,
-then of the cubes that form the whole application, in reverse
-dependency order.
-
-In principle, if the migration scripts have been properly written and
-tested, you should answer YES to all questions.
-
-Somtimes, typically while debugging a migration script, something goes
-wrong and the migration fails. Unfortunately the databse may be in an
-incoherent state. You have two options here:
-
-* fix the bug, restore the database and restart the migration process
-  from scratch (quite recommended in a production environement)
-
-* try to replay the migration up to the last successful commit, that
-  is answering NO to all questions up to the step that failed, and
-  finish by answering YES to the remaining questions.
-
--- a/doc/book/en/admin/cubicweb-ctl.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _cubicweb-ctl:
-
-``cubicweb-ctl`` tool
-=====================
-
-`cubicweb-ctl` is the swiss knife to manage *CubicWeb* instances.
-The general syntax is ::
-
-  cubicweb-ctl <command> [options command] <arguments commands>
-
-To view available commands ::
-
-  cubicweb-ctl
-  cubicweb-ctl --help
-
-Please note that the commands available depends on the *CubicWeb* packages
-and cubes that have been installed.
-
-To view the help menu on specific command ::
-
-  cubicweb-ctl <command> --help
-
-Listing available cubes and instance
--------------------------------------
-
-* ``list``, provides a list of the available configuration, cubes
-  and instances.
-
-
-Creation of a new cube
------------------------
-
-Create your new cube cube ::
-
-   cubicweb-ctl newcube
-
-This will create a new cube in
-``/path/to/grshell-cubicweb/cubes/<mycube>`` for a Mercurial
-installation, or in ``/usr/share/cubicweb/cubes`` for a debian
-packages installation.
-
-Create an instance
--------------------
-
-You must ensure `~/etc/cubicweb.d/` exists prior to this. On windows, the
-'~' part will probably expand to 'Documents and Settings/user'.
-
-To create an instance from an existing cube, execute the following
-command ::
-
-   cubicweb-ctl create <cube_name> <instance_name>
-
-This command will create the configuration files of an instance in
-``~/etc/cubicweb.d/<instance_name>``.
-
-The tool ``cubicweb-ctl`` executes the command ``db-create`` and
-``db-init`` when you run ``create`` so that you can complete an
-instance creation in a single command. But of course it is possible
-to issue these separate commands separately, at a later stage.
-
-Command to create/initialize an instance database
--------------------------------------------------
-
-* ``db-create``, creates the system database of an instance (tables and
-  extensions only)
-* ``db-init``, initializes the system database of an instance
-  (schema, groups, users, workflows...)
-
-Commands to control instances
------------------------------
-
-* ``start``, starts one or more or all instances
-
-of special interest::
-
-  start -D
-
-will start in debug mode (under windows, starting without -D will not
-work; you need instead to setup your instance as a service).
-
-* ``stop``, stops one or more or all instances
-* ``restart``, restarts one or more or all instances
-* ``status``, returns the status of the instance(s)
-
-Commands to maintain instances
-------------------------------
-
-* ``upgrade``, launches the existing instances migration when a new version
-  of *CubicWeb* or the cubes installed is available
-* ``shell``, opens a (Python based) migration shell for manual maintenance of the instance
-* ``db-dump``, creates a dump of the system database
-* ``db-restore``, restores a dump of the system database
-* ``db-check``, checks data integrity of an instance. If the automatic correction
-  is activated, it is recommanded to create a dump before this operation.
-* ``schema-sync``, synchronizes the persistent schema of an instance with
-  the instance schema. It is recommanded to create a dump before this operation.
-
-Commands to maintain i18n catalogs
-----------------------------------
-* ``i18ncubicweb``, regenerates messages catalogs of the *CubicWeb* library
-* ``i18ncube``, regenerates the messages catalogs of a cube
-* ``i18ninstance``, recompiles the messages catalogs of an instance.
-  This is automatically done while upgrading.
-
-See also chapter :ref:`internationalization`.
-
-Other commands
---------------
-* ``delete``, deletes an instance (configuration files and database)
--- a/doc/book/en/admin/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _Part3:
-
---------------
-Administration
---------------
-
-This part is for installation and administration of the *CubicWeb* framework and
-instances based on that framework.
-
-.. toctree::
-   :maxdepth: 1
-   :numbered:
-
-   setup
-   setup-windows
-   config
-   cubicweb-ctl
-   create-instance
-   instance-config
-   site-config
-   multisources
-   ldap
-   migration
-   additional-tips
-   rql-logs
-
--- a/doc/book/en/admin/instance-config.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-
-Configure an instance
-=====================
-
-While creating an instance, a configuration file is generated in::
-
-    $ (CW_INSTANCES_DIR) / <instance> / <configuration name>.conf
-
-For example::
-
-    /etc/cubicweb.d/myblog/all-in-one.conf
-
-It is a simple text file in the INI format
-(http://en.wikipedia.org/wiki/INI_file). In the following description,
-each option name is prefixed with its own section and followed by its
-default value if necessary, e.g. "`<section>.<option>` [value]."
-
-.. _`WebServerConfig`:
-
-Configuring the Web server
---------------------------
-:`web.auth-model` [cookie]:
-    authentication mode, cookie or http
-:`web.realm`:
-    realm of the instance in http authentication mode
-:`web.http-session-time` [0]:
-    period of inactivity of an HTTP session before it closes automatically.
-    Duration in seconds, 0 meaning no expiration (or more exactly at the
-    closing of the browser client)
-
-:`main.anonymous-user`, `main.anonymous-password`:
-    login and password to use to connect to the RQL server with
-    HTTP anonymous connection. CWUser account should exist.
-
-:`main.base-url`:
-    url base site to be used to generate the urls of web pages
-
-Https configuration
-```````````````````
-It is possible to make a site accessible for anonymous http connections
-and https for authenticated users. This requires to
-use apache (for example) for redirection and the variable `main.https-url`
-of configuration file.
-
-For this to work you have to activate the following apache modules :
-
-* rewrite
-* proxy
-* http_proxy
-
-The command on Debian based systems for that is ::
-
-  a2enmod rewrite http_proxy proxy
-  /etc/init.d/apache2 restart
-
-:Example:
-
-   For an apache redirection of a site accessible via `http://localhost/demo`
-   and `https://localhost/demo` and actually running on port 8080, it
-   takes to the http:::
-
-     ProxyPreserveHost On
-     RewriteEngine On
-     RewriteCond %{REQUEST_URI} ^/demo
-     RewriteRule ^/demo$ /demo/
-     RewriteRule ^/demo/(.*) http://127.0.0.1:8080/$1 [L,P]
-
-   and for the https:::
-
-     ProxyPreserveHost On
-     RewriteEngine On
-     RewriteCond %{REQUEST_URI} ^/ demo
-     RewriteRule ^/demo$/demo/
-     RewriteRule ^/demo/(.*) http://127.0.0.1:8080/https/$1 [L,P]
-
-
-   and we will file in the all-in-one.conf of the instance:::
-
-     base-url = http://localhost/demo
-     https-url = https://localhost/demo
-
-Notice that if you simply want a site accessible through https, not *both* http
-and https, simply set `base-url` to the https url and the first section into your
-apache configuration (as you would have to do for an http configuration with an
-apache front-end).
-
-Setting up the web client
--------------------------
-:`web.embed-allowed`:
-    regular expression matching sites which could be "embedded" in
-    the site (controllers 'embed')
-:`web.submit-url`:
-    url where the bugs encountered in the instance can be mailed to
-
-
-RQL server configuration
-------------------------
-:`main.host`:
-    host name if it can not be detected correctly
-:`main.pid-file`:
-    file where will be written the server pid
-:`main.uid`:
-    user account to use for launching the server when it is
-    root launched by init
-:`main.session-time [30*60]`:
-    timeout of a RQL session
-:`main.query-log-file`:
-    file where all requests RQL executed by the server are written
-
-
-Configuring e-mail
-------------------
-RQL and web server side:
-
-:`email.mangle-mails [no]`:
-    indicates whether the email addresses must be displayed as is or
-    transformed
-
-RQL server side:
-
-:`email.smtp-host [mail]`:
-    hostname hosting the SMTP server to use for outgoing mail
-:`email.smtp-port [25]`:
-    SMTP server port to use for outgoing mail
-:`email.sender-name`:
-    name to use for outgoing mail of the instance
-:`email.sender-addr`:
-    address for outgoing mail of the instance
-:`email.default dest-addrs`:
-    destination addresses by default, if used by the configuration of the
-    dissemination of the model (separated by commas)
-:`email.supervising-addrs`:
-    destination addresses of e-mails of supervision (separated by
-    commas)
-
-
-Configuring logging
--------------------
-:`main.log-threshold`:
-    level of filtering messages (DEBUG, INFO, WARNING, ERROR)
-:`main.log-file`:
-    file to write messages
-
-
-.. _PersistentProperties:
-
-Configuring persistent properties
----------------------------------
-Other configuration settings are in the form of entities `CWProperty`
-in the database. It must be edited via the web interface or by
-RQL queries.
-
-:`ui.encoding`:
-    Character encoding to use for the web
-:`navigation.short-line-size`:
-    number of characters for "short" display
-:`navigation.page-size`:
-    maximum number of entities to show per results page
-:`navigation.related-limit`:
-    number of related entities to show up on primary entity view
-:`navigation.combobox-limit`:
-    number of entities unrelated to show up on the drop-down lists of
-    the sight on an editing entity view
-
-Cross-Origin Resource Sharing
------------------------------
-
-CubicWeb provides some support for the CORS_ protocol. For now, the
-provided implementation only deals with access to a CubicWeb instance
-as a whole. Support for a finer granularity may be considered in the
-future.
-
-Specificities of the provided implementation:
-
-- ``Access-Control-Allow-Credentials`` is always true
-- ``Access-Control-Allow-Origin`` header in response will never be
-  ``*``
-- ``Access-Control-Expose-Headers`` can be configured globally (see below)
-- ``Access-Control-Max-Age`` can be configured globally (see below)
-- ``Access-Control-Allow-Methods`` can be configured globally (see below)
-- ``Access-Control-Allow-Headers`` can be configured globally (see below)
-
-
-A few parameters can be set to configure the CORS_ capabilities of CubicWeb.
-
-.. _CORS: http://www.w3.org/TR/cors/
-
-:`access-control-allow-origin`:
-   comma-separated list of allowed origin domains or "*" for any domain
-:`access-control-allow-methods`:
-   comma-separated list of allowed HTTP methods
-:`access-control-max-age`:
-   maximum age of cross-origin resource sharing (in seconds)
-:`access-control-allow-headers`:
-   comma-separated list of allowed HTTP custom headers (used in simple requests)
-:`access-control-expose-headers`:
-   comma-separated list of allowed HTTP custom headers (used in preflight requests)
-
--- a/doc/book/en/admin/ldap.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-.. _LDAP:
-
-LDAP integration
-================
-
-Overview
---------
-
-Using LDAP as a source for user credentials and information is quite
-easy. The most difficult part lies in building an LDAP schema or
-using an existing one.
-
-At cube creation time, one is asked if more sources are wanted. LDAP
-is one possible option at this time. Of course, it is always possible
-to set it up later using the `CWSource` entity type, which we discuss
-there.
-
-It is possible to add as many LDAP sources as wanted, which translates
-in as many `CWSource` entities as needed.
-
-The general principle of the LDAP source is, given a proper
-configuration, to create local users matching the users available in
-the directory and deriving local user attributes from directory users
-attributes. Then a periodic task ensures local user information
-synchronization with the directory.
-
-Users handled by such a source should not be edited directly from
-within the application instance itself. Rather, updates should happen
-at the LDAP server level.
-
-Credential checks are _always_ done against the LDAP server.
-
-.. Note::
-
-  There are currently two ldap source types: the older `ldapuser` and
-  the newer `ldapfeed`. The older will be deprecated anytime soon, as
-  the newer has now gained all the features of the old and does not
-  suffer from some of its illnesses.
-
-  The ldapfeed creates real `CWUser` entities, and then
-  activate/deactivate them depending on their presence/absence in the
-  corresponding LDAP source. Their attribute and state
-  (activated/deactivated) are hence managed by the source mechanism;
-  they should not be altered by other means (as such alterations may
-  be overridden in some subsequent source synchronisation).
-
-
-Configuration of an LDAPfeed source
------------------------------------
-
-Additional sources are created at cube creation time or later through the
-user interface.
-
-Configure an `ldapfeed` source from the user interface under `Manage` then
-`data sources`:
-
-* At this point `type` has been set to `ldapfeed`.
-
-* The `parser` attribute shall be set to `ldapfeed`.
-
-* The `url` attribute shall be set to an URL such as ldap://ldapserver.domain/.
-
-* The `configuration` attribute contains many options. They are described in
-  detail in the next paragraph.
-
-
-Options of an LDAPfeed source
------------------------------
-
-Let us enumerate the options by categories (LDAP server connection,
-LDAP schema mapping information).
-
-LDAP server connection options:
-
-* `auth-mode`, (choices are simple, cram_md5, digest_md5, gssapi, support
-  for the later being partial as of now)
-
-* `auth-realm`, realm to use when using gssapi/kerberos authentication
-
-* `data-cnx-dn`, user dn to use to open data connection to the ldap (eg
-  used to respond to rql queries)
-
-* `data-cnx-password`, password to use to open data connection to the
-  ldap (eg used to respond to rql queries)
-
-If the LDAP server accepts anonymous binds, then it is possible to
-leave data-cnx-dn and data-cnx-password empty. This is, however, quite
-unlikely in practice. Beware that the LDAP server might hide attributes
-such as "userPassword" while the rest of the attributes remain visible
-through an anonymous binding.
-
-LDAP schema mapping options:
-
-* `user-base-dn`, base DN to lookup for users
-
-* `user-scope`, user search scope (valid values: "BASE", "ONELEVEL",
-  "SUBTREE")
-
-* `user-classes`, classes of user (with Active Directory, you want to
-  say "user" here)
-
-* `user-filter`, additional filters to be set in the ldap query to
-  find valid users
-
-* `user-login-attr`, attribute used as login on authentication (with
-  Active Directory, you want to use "sAMAccountName" here)
-
-* `user-default-group`, name of a group in which ldap users will be by
-  default. You can set multiple groups by separating them by a comma
-
-* `user-attrs-map`, map from ldap user attributes to cubicweb
-  attributes (with Active Directory, you want to use
-  sAMAccountName:login,mail:email,givenName:firstname,sn:surname)
-
-
-Other notes
------------
-
-* Cubicweb is able to start if ldap cannot be reached, even on
-  cubicweb-ctl start ... If some source ldap server cannot be used
-  while an instance is running, the corresponding users won't be
-  authenticated but their status will not change (e.g. they will not
-  be deactivated)
-
-* The user-base-dn is a key that helps cubicweb map CWUsers to LDAP
-  users: beware updating it
-
-* When a user is removed from an LDAP source, it is deactivated in the
-  CubicWeb instance; when a deactivated user comes back in the LDAP
-  source, it (automatically) is activated again
-
-* You can use the :class:`CWSourceHostConfig` to have variants for a source
-  configuration according to the host the instance is running on. To do so
-  go on the source's view from the sources management view.
--- a/doc/book/en/admin/migration.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Migrating cubicweb instances - benefits from a distributed architecture
-=======================================================================
-
-Migrate apache & cubicweb
--------------------------
-
-**Aim** : do the migration for N cubicweb instances hosted on a server to another with no downtime.
-
-**Prerequisites** : have an explicit definition of the database host (not default or localhost). In our case, the database is hosted on another host.
-
-**Steps** :
-
-1. *on new machine* : install your environment (*pseudocode*) ::
-
-     apt-get install cubicweb cubicweb-applications apache2
-
-2. *on old machine* : copy your cubicweb and apache configuration to the new machine ::
-
-    scp /etc/cubicweb.d/ newmachine:/etc/cubicweb.d/
-    scp /etc/apache2/sites-available/ newmachine:/etc/apache2/sites-available/
-
-3. *on new machine* : start your instances ::
-
-     cubicweb start
-
-4. *on new machine* : enable sites and modules for apache and start it, test it using by modifying your /etc/host file.
-
-5. change dns entry from your oldmachine to newmachine
-
-6. shutdown your *old machine* (if it doesn't host other services or your database)
-
-7. That's it.
-
-**Possible enhancements** : use right from the start a pound server behind your apache, that way you can add backends and smoothily migrate by shuting down backends that pound will take into account.
-
-
--- a/doc/book/en/admin/multisources.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-Multiple sources of data
-========================
-
-Data sources include SQL, LDAP, RQL, mercurial and subversion.
-
-.. XXX feed me
--- a/doc/book/en/admin/rql-logs.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-RQL logs
-========
-
-You can configure the *CubicWeb* instance to keep a log
-of the queries executed against your database. To do so,
-edit the configuration file of your instance
-``.../etc/cubicweb.d/myapp/all-in-one.conf`` and uncomment the
-variable ``query-log-file``::
-
-  # web instance query log file
-  query-log-file=/tmp/rql-myapp.log
-
--- a/doc/book/en/admin/setup-windows.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _SetUpWindowsEnv:
-
-Installing a development environement on Windows
-================================================
-
-Setting up a Windows development environment is not too complicated
-but it requires a series of small steps.
-
-We propose an example of a typical |cubicweb| installation on Windows
-from sources. We assume everything goes into ``C:\\`` and for any
-package, without version specification, "the latest is
-the greatest".
-
-Mind that adjusting the installation drive should be straightforward.
-
-
-
-Install the required elements
------------------------------
-
-|cubicweb| requires some base elements that must be installed to run
-correctly. So, first of all, you must install them :
-
-* python >= 2.6 and < 3
-  (`Download Python <http://www.python.org/download/>`_).
-  You can also consider the Python(x,y) distribution
-  (`Download Python(x,y) <http://code.google.com/p/pythonxy/wiki/Downloads>`_)
-  as it makes things easier for Windows user by wrapping in a single installer
-  python 2.7 plus numerous useful third-party modules and
-  applications (including Eclipse + pydev, which is an arguably good
-  IDE for Python under Windows).
-
-* `Twisted <http://twistedmatrix.com/trac/>`_ is an event-driven
-  networking engine
-  (`Download Twisted <http://twistedmatrix.com/trac/>`_)
-
-* `lxml <http://codespeak.net/lxml/>`_ library
-  (version >=2.2.1) allows working with XML and HTML
-  (`Download lxml <http://pypi.python.org/pypi/lxml/2.2.1>`_)
-
-* `Postgresql <http://www.postgresql.org/>`_,
-  an object-relational database system
-  (`Download Postgresql <http://www.enterprisedb.com/products/pgdownload.do#windows>`_)
-  and its python drivers
-  (`Download psycopg <http://www.stickpeople.com/projects/python/win-psycopg/#Version2>`_)
-
-* A recent version of `gettext`
-  (`Download gettext <http://download.logilab.org/pub/gettext/gettext-0.17-win32-setup.exe>`_).
-
-* `rql <http://www.logilab.org/project/rql>`_,
-  the recent version of the Relationship Query Language parser.
-
-Install optional elements
--------------------------
-
-We recommend you to install the following elements. They are not
-mandatory but they activate very interesting features in |cubicweb|:
-
-* `python-ldap <http://pypi.python.org/pypi/python-ldap>`_
-  provides access to LDAP/Active directory directories
-  (`Download python-ldap <http://www.osuch.org/python-ldap>`_).
-
-* `graphviz <http://www.graphviz.org/>`_
-  which allow schema drawings.
-  (`Download graphviz <http://www.graphviz.org/Download_windows.php>`_).
-  It is quite recommended (albeit not mandatory).
-
-Other elements will activate more features once installed. Take a look
-at :ref:`InstallDependencies`.
-
-Useful tools
-------------
-
-Some additional tools could be useful to develop :ref:`cubes <AvailableCubes>`
-with the framework.
-
-* `mercurial <http://mercurial.selenic.com/>`_ and its standard windows GUI
-  (`TortoiseHG <http://tortoisehg.bitbucket.org/>`_) allow you to get the source
-  code of |cubicweb| from control version repositories. So you will be able to
-  get the latest development version and pre-release bugfixes in an easy way
-  (`Download mercurial <http://bitbucket.org/tortoisehg/stable/wiki/download>`_).
-
-* You can also consider the ssh client `Putty` in order to peruse
-  mercurial over ssh (`Download <http://www.putty.org/>`_).
-
-* If you are an Eclipse user, mercurial can be integrated using the
-  `MercurialEclipse` plugin
-  (`Home page <http://www.vectrace.com/mercurialeclipse/>`_).
-
-Getting the sources
--------------------
-
-There are two ways to get the sources of |cubicweb| and its
-:ref:`cubes <AvailableCubes>`:
-
-* download the latest release (:ref:`SourceInstallation`)
-* get the development version using Mercurial
-  (:ref:`MercurialInstallation`)
-
-Environment variables
----------------------
-
-You will need some convenience environment variables once all is set up. These
-variables are settable through the GUI by getting at the `System properties`
-window (by righ-clicking on `My Computer` -> `properties`).
-
-In the `advanced` tab, there is an `Environment variables` button. Click on
-it. That opens a small window allowing edition of user-related and system-wide
-variables.
-
-We will consider only user variables. First, the ``PATH`` variable. Assuming
-you are logged as user *Jane*, add the following paths, separated by
-semi-colons::
-
-  C:\Documents and Settings\Jane\My Documents\Python\cubicweb\cubicweb\bin
-  C:\Program Files\Graphviz2.24\bin
-
-The ``PYTHONPATH`` variable should also contain::
-
-  C:\Documents and Settings\Jane\My Documents\Python\cubicweb\
-
-From now, on a fresh `cmd` shell, you should be able to type::
-
-  cubicweb-ctl list
-
-... and get a meaningful output.
-
-Running an instance as a service
---------------------------------
-
-This currently assumes that the instances configurations is located at
-``C:\\etc\\cubicweb.d``. For a cube 'my_instance', you will find
-``C:\\etc\\cubicweb.d\\my_instance\\win32svc.py``.
-
-Now, register your instance as a windows service with::
-
-  win32svc install
-
-Then start the service with::
-
-  net start cubicweb-my_instance
-
-In case this does not work, you should be able to see error reports in
-the application log, using the windows event log viewer.
--- a/doc/book/en/admin/setup.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,269 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _SetUpEnv:
-
-Installation of a *CubicWeb* environment
-========================================
-
-Official releases are available from the `CubicWeb.org forge`_ and from
-`PyPI`_. Since CubicWeb is developed using `Agile software development
-<http://en.wikipedia.org/wiki/Agile_software_development>`_ techniques, releases
-happen frequently. In a version numbered X.Y.Z, X changes after a few years when
-the API breaks, Y changes after a few weeks when features are added and Z
-changes after a few days when bugs are fixed.
-
-Depending on your needs, you will chose a different way to install CubicWeb on
-your system:
-
-- `Installation on Debian/Ubuntu`_
-- `Installation on Windows`_
-- `Installation in a virtualenv`_
-- `Installation with pip`_
-- `Installation with easy_install`_
-- `Installation from tarball`_
-
-If you are a power-user and need the very latest features, you will
-
-- `Install from version control`_
-
-Once the software is installed, move on to :ref:`ConfigEnv` for better control
-and advanced features of |cubicweb|.
-
-.. _`Installation on Debian/Ubuntu`: DebianInstallation_
-.. _`Installation on Windows`: WindowsInstallation_
-.. _`Installation in a virtualenv`: VirtualenvInstallation_
-.. _`Installation with pip`: PipInstallation_
-.. _`Installation with easy_install`: EasyInstallInstallation_
-.. _`Installation from tarball`: TarballInstallation_
-.. _`Install from version control`: MercurialInstallation_
-
-
-.. _DebianInstallation:
-
-Debian/Ubuntu install
----------------------
-
-|cubicweb| is packaged for Debian/Ubuntu (and derived
-distributions). Their integrated package-management system make
-installation and upgrade much easier for users since
-dependencies (like databases) are automatically installed.
-
-Depending on the distribution you are using, add the appropriate line to your
-`list of sources` (for example by editing ``/etc/apt/sources.list``).
-
-For Debian 7.0 Wheezy (stable)::
-
-  deb http://download.logilab.org/production/ wheezy/
-
-For Debian Sid (unstable)::
-
-  deb http://download.logilab.org/production/ sid/
-
-For Ubuntu 12.04 Precise Pangolin (Long Term Support) and newer::
-
-  deb http://download.logilab.org/production/ precise/
-
-The repositories are signed with the `Logilab's gnupg key`_. You can download
-and register the key to avoid warnings::
-
-  wget -q http://download.logilab.org/logilab-dists-key.asc -O- | sudo apt-key add -
-
-Update your list of packages and perform the installation::
-
-  apt-get update
-  apt-get install cubicweb cubicweb-dev
-
-``cubicweb`` installs the framework itself, allowing you to create new
-instances. ``cubicweb-dev`` installs the development environment
-allowing you to develop new cubes.
-
-There is also a wide variety of :ref:`cubes <AvailableCubes>`. You can access a
-list of available cubes using ``apt-cache search cubicweb`` or at the
-`CubicWeb.org forge`_.
-
-.. note::
-
-  `cubicweb-dev` will install basic sqlite support. You can easily setup
-  :ref:`cubicweb with other database <DatabaseInstallation>` using the following
-  virtual packages :
-
-  * `cubicweb-postgresql-support` contains the necessary dependencies for
-    using :ref:`cubicweb with postgresql datatabase <PostgresqlConfiguration>`
-
-  * `cubicweb-mysql-support` contains the necessary dependencies for using
-    :ref:`cubicweb with mysql database <MySqlConfiguration>`.
-
-.. _`list of sources`: http://wiki.debian.org/SourcesList
-.. _`Logilab's gnupg key`: http://download.logilab.org/logilab-dists-key.asc
-.. _`CubicWeb.org Forge`: http://www.cubicweb.org/project/
-
-.. _WindowsInstallation:
-
-Windows Install
----------------
-
-You need to have `python`_ version >= 2.5 and < 3 installed.
-
-If you want an automated install, your best option is probably the
-:ref:`EasyInstallInstallation`. EasyInstall is a tool that helps users to
-install python packages along with their dependencies, searching for suitable
-pre-compiled binaries on the `The Python Package Index`_.
-
-If you want better control over the process as well as a suitable development
-environment or if you are having problems with `easy_install`, read on to
-:ref:`SetUpWindowsEnv`.
-
-.. _python:  http://www.python.org/
-.. _`The Python Package Index`: http://pypi.python.org
-
-.. _VirtualenvInstallation:
-
-`Virtualenv` install
---------------------
-
-|cubicweb| can be safely installed, used and contained inside a
-`virtualenv`_. You can use either :ref:`pip <PipInstallation>` or
-:ref:`easy_install <EasyInstallInstallation>` to install |cubicweb|
-inside an activated virtual environment.
-
-.. _PipInstallation:
-
-`pip` install
--------------
-
-`pip <http://pip.openplans.org/>`_ is a python tool that helps downloading,
-building, installing, and managing Python packages and their dependencies. It
-is fully compatible with `virtualenv`_ and installs the packages from sources
-published on the `The Python Package Index`_.
-
-.. _`virtualenv`: http://virtualenv.openplans.org/
-
-A working compilation chain is needed to build the modules that include C
-extensions. If you really do not want to compile anything, installing `lxml <http://lxml.de/>`_,
-`Twisted Web <http://twistedmatrix.com/trac/wiki/Downloads/>`_ and `libgecode
-<http://www.gecode.org/>`_ will help.
-
-For Debian, these minimal dependencies can be obtained by doing::
-
-  apt-get install gcc python-pip python-dev python-lxml
-
-or, if you prefer to get as much as possible from pip::
-
-  apt-get install gcc python-pip python-dev libxslt1-dev libxml2-dev
-
-For Windows, you can install pre-built packages (possible `source
-<http://www.lfd.uci.edu/~gohlke/pythonlibs/>`_). For a minimal setup, install:
-
-- pip http://www.lfd.uci.edu/~gohlke/pythonlibs/#pip
-- setuptools http://www.lfd.uci.edu/~gohlke/pythonlibs/#setuptools
-- libxml-python http://www.lfd.uci.edu/~gohlke/pythonlibs/#libxml-python>
-- lxml http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml and
-- twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
-
-Make sure to choose the correct architecture and version of Python.
-
-Finally, install |cubicweb| and its dependencies, by running::
-
-  pip install cubicweb
-
-Many other :ref:`cubes <AvailableCubes>` are available. A list is available at
-`PyPI <http://pypi.python.org/pypi?%3Aaction=search&term=cubicweb&submit=search>`_
-or at the `CubicWeb.org forge`_.
-
-For example, installing the *blog cube* is achieved by::
-
-  pip install cubicweb-blog
-
-.. _EasyInstallInstallation:
-
-`easy_install` install
-----------------------
-
-.. note::
-
-   If you are not a Windows user and you have a compilation environment, we
-   recommend you to use the PipInstallation_.
-
-`easy_install`_ is a python utility that helps downloading, installing, and
-managing python packages and their dependencies.
-
-Install |cubicweb| and its dependencies, run::
-
-  easy_install cubicweb
-
-There is also a wide variety of :ref:`cubes <AvailableCubes>`. You can access a
-list of available cubes on `PyPI
-<http://pypi.python.org/pypi?%3Aaction=search&term=cubicweb&submit=search>`_
-or at the `CubicWeb.org Forge`_.
-
-For example, installing the *blog cube* is achieved by::
-
-  easy_install cubicweb-blog
-
-.. note::
-
-  If you encounter problem with :ref:`cubes <AvailableCubes>` installation,
-  consider using :ref:`PipInstallation` which is more stable
-  but can not installed pre-compiled binaries.
-
-.. _`easy_install`: http://packages.python.org/distribute/easy_install.html
-
-
-.. _SourceInstallation:
-
-Install from source
--------------------
-
-.. _TarballInstallation:
-
-You can download the archive containing the sources from
-`http://download.logilab.org/pub/cubicweb/ <http://download.logilab.org/pub/cubicweb/>`_.
-
-Make sure you also have all the :ref:`InstallDependencies`.
-
-Once uncompressed, you can install the framework from inside the uncompressed
-folder with::
-
-  python setup.py install
-
-Or you can run |cubicweb| directly from the source directory by
-setting the :ref:`resource mode <RessourcesConfiguration>` to `user`. This will
-ease the development with the framework.
-
-There is also a wide variety of :ref:`cubes <AvailableCubes>`. You can access a
-list of availble cubes at the `CubicWeb.org Forge`_.
-
-
-.. _MercurialInstallation:
-
-Install from version control system
------------------------------------
-
-To keep-up with on-going development, clone the :ref:`Mercurial
-<MercurialPresentation>` repository::
-
-  hg clone -u stable http://hg.logilab.org/cubicweb # stable branch
-  hg clone http://hg.logilab.org/cubicweb # development branch
-
-To get many of CubicWeb's dependencies and a nice set of base cubes, run the
-`clone_deps.py` script located in `cubicweb/bin/`::
-
-  python cubicweb/bin/clone_deps.py
-
-(Windows users should replace slashes with antislashes).
-
-This script will clone a set of mercurial repositories into the
-directory containing the ``cubicweb`` repository, and update them to the
-latest published version tag (if any).
-
-.. note::
-
-  In every cloned repositories, a `hg tags` will display a list of
-  tags in reverse chronological order. One reasonnable option is to go to a
-  tagged version: the latest published version or example, as done by
-  the `clone_deps` script)::
-
-   hg update cubicweb-version-3.12.2
-
-Make sure you also have all the :ref:`InstallDependencies`.
-
--- a/doc/book/en/admin/site-config.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-User interface for web site configuration
-=========================================
-
-.. image:: ../images/lax-book_03-site-config-panel_en.png
-
-This panel allows you to configure the appearance of your instance site.
-Six menus are available and we will go through each of them to explain how
-to use them.
-
-Navigation
-~~~~~~~~~~
-This menu provides you a way to adjust some navigation options depending on
-your needs, such as the number of entities to display by page of results.
-Follows the detailled list of available options :
-
-* navigation.combobox-limit : maximum number of entities to display in related
-  combo box (sample format: 23)
-* navigation.page-size : maximum number of objects displayed by page of results
-  (sample format: 23)
-* navigation.related-limit : maximum number of related entities to display in
-  the primary view (sample format: 23)
-* navigation.short-line-size : maximum number of characters in short description
-  (sample format: 23)
-
-UI
-~~
-This menu provides you a way to customize the user interface settings such as
-date format or encoding in the produced html.
-Follows the detailled list of available options :
-
-* ui.date-format : how to format date in the ui ("man strftime" for format description)
-* ui.datetime-format : how to format date and time in the ui ("man strftime" for format
-  description)
-* ui.default-text-format : default text format for rich text fields.
-* ui.encoding : user interface encoding
-* ui.fckeditor :should html fields being edited using fckeditor (a HTML WYSIWYG editor).
-  You should also select text/html as default text format to actually get fckeditor.
-* ui.float-format : how to format float numbers in the ui
-* ui.language : language of the user interface
-* ui.main-template : id of main template used to render pages
-* ui.site-title	: site title, which is displayed right next to the logo in the header
-* ui.time-format : how to format time in the ui ("man strftime" for format description)
-
-
-Actions
-~~~~~~~
-This menu provides a way to configure the context in which you expect the actions
-to be displayed to the user and if you want the action to be visible or not.
-You must have notice that when you view a list of entities, an action box is
-available on the left column which display some actions as well as a drop-down
-menu for more actions.
-
-The context available are :
-
-* mainactions : actions listed in the left box
-* moreactions : actions listed in the `more` menu of the left box
-* addrelated : add actions listed in the left box
-* useractions : actions listed in the first section of drop-down menu
-  accessible from the right corner user login link
-* siteactions : actions listed in the second section of drop-down menu
-  accessible from the right corner user login link
-* hidden : select this to hide the specific action
-
-Boxes
-~~~~~
-The instance has already a pre-defined set of boxes you can use right away.
-This configuration section allows you to place those boxes where you want in the
-instance interface to customize it.
-
-The available boxes are :
-
-* actions box : box listing the applicable actions on the displayed data
-
-* boxes_blog_archives_box : box listing the blog archives
-
-* possible views box : box listing the possible views for the displayed data
-
-* rss box : RSS icon to get displayed data as a RSS thread
-
-* search box : search box
-
-* startup views box : box listing the configuration options available for
-  the instance site, such as `Preferences` and `Site Configuration`
-
-Components
-~~~~~~~~~~
-[WRITE ME]
-
-Contextual components
-~~~~~~~~~~~~~~~~~~~~~
-[WRITE ME]
-
--- a/doc/book/en/annexes/depends.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _InstallDependencies:
-
-Installation dependencies
-=========================
-
-When you run CubicWeb from source, either by downloading the tarball or
-cloning the mercurial tree, here is the list of tools and libraries you need
-to have installed in order for CubicWeb to work:
-
-* yapps - http://theory.stanford.edu/~amitp/yapps/ -
-  http://pypi.python.org/pypi/Yapps2
-
-* pygraphviz - http://networkx.lanl.gov/pygraphviz/ -
-  http://pypi.python.org/pypi/pygraphviz
-
-* docutils - http://docutils.sourceforge.net/ - http://pypi.python.org/pypi/docutils
-
-* lxml - http://codespeak.net/lxml - http://pypi.python.org/pypi/lxml
-
-* twisted - http://twistedmatrix.com/ - http://pypi.python.org/pypi/Twisted
-
-* logilab-common - http://www.logilab.org/project/logilab-common -
-  http://pypi.python.org/pypi/logilab-common/
-
-* logilab-database - http://www.logilab.org/project/logilab-database -
-  http://pypi.python.org/pypi/logilab-database/
-
-* logilab-constraint - http://www.logilab.org/project/logilab-constraint -
-  http://pypi.python.org/pypi/constraint/
-
-* logilab-mtconverter - http://www.logilab.org/project/logilab-mtconverter -
-  http://pypi.python.org/pypi/logilab-mtconverter
-
-* rql - http://www.logilab.org/project/rql - http://pypi.python.org/pypi/rql
-
-* yams - http://www.logilab.org/project/yams - http://pypi.python.org/pypi/yams
-
-* indexer - http://www.logilab.org/project/indexer -
-  http://pypi.python.org/pypi/indexer
-
-* passlib - https://code.google.com/p/passlib/ -
-  http://pypi.python.org/pypi/passlib
-
-If you're using a Postgresql database (recommended):
-
-* psycopg2 - http://initd.org/projects/psycopg2 - http://pypi.python.org/pypi/psycopg2
-* plpythonu extension
-
-Other optional packages:
-
-* fyzz - http://www.logilab.org/project/fyzz -
-  http://pypi.python.org/pypi/fyzz *to activate Sparql querying*
-
-
-Any help with the packaging of CubicWeb for more than Debian/Ubuntu (including
-eggs, buildouts, etc) will be greatly appreciated.
--- a/doc/book/en/annexes/docstrings-conventions.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-Javascript docstrings
-=====================
-
-Whereas in Python source code we only need to include a module docstrings
-using the directive `.. automodule:: mypythonmodule`, we will have to
-explicitely define Javascript modules and functions in the doctrings since
-there is no native directive to include Javascript files.
-
-Rest generation
----------------
-
-`pyjsrest` is a small utility parsing Javascript doctrings and generating the
-corresponding Restructured file used by Sphinx to generate HTML documentation.
-This script will have the following structure::
-
-  ===========
-  filename.js
-  ===========
-  .. module:: filename.js
-
-We use the `.. module::` directive to register a javascript library
-as a Python module for Sphinx. This provides an entry in the module index.
-
-The contents of the docstring found in the javascript file will be added as is
-following the module declaration. No treatment will be done on the doctring.
-All the documentation structure will be in the docstrings and will comply
-with the following rules.
-
-Docstring structure
--------------------
-
-Basically we document javascript with RestructuredText docstring
-following the same convention as documenting Python code.
-
-The doctring in Javascript files must be contained in standard
-Javascript comment signs, starting with `/**` and ending with `*/`,
-such as::
-
- /**
-  * My comment starts here.
-  * This is the second line prefixed with a `*`.
-  * ...
-  * ...
-  * All the follwing line will be prefixed with a `*` followed by a space.
-  * ...
-  * ...
-  */
-
-
-Comments line prefixed by `//` will be ignored. They are reserved for source
-code comments dedicated to developers.
-
-
-Javscript functions docstring
------------------------------
-
-By default, the `function` directive describes a module-level function.
-
-`function` directive
-~~~~~~~~~~~~~~~~~~~~
-
-Its purpose is to define the function prototype such as::
-
-    .. function:: loadxhtml(url, data, reqtype, mode)
-
-If any namespace is used, we should add it in the prototype for now,
-until we define an appropriate directive::
-
-    .. function:: jQuery.fn.loadxhtml(url, data, reqtype, mode)
-
-Function parameters
-~~~~~~~~~~~~~~~~~~~
-
-We will define function parameters as a bulleted list, where the
-parameter name will be backquoted and followed by its description.
-
-Example of a javascript function docstring::
-
-    .. function:: loadxhtml(url, data, reqtype, mode)
-
-    cubicweb loadxhtml plugin to make jquery handle xhtml response
-
-    fetches `url` and replaces this's content with the result
-
-    Its arguments are:
-
-    * `url`
-
-    * `mode`, how the replacement should be done (default is 'replace')
-       Possible values are :
-           - 'replace' to replace the node's content with the generated HTML
-           - 'swap' to replace the node itself with the generated HTML
-           - 'append' to append the generated HTML to the node's content
-
-
-Optional parameter specification
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Javascript functions handle arguments not listed in the function signature.
-In the javascript code, they will be flagged using `/* ... */`. In the docstring,
-we flag those optional arguments the same way we would define it in
-Python::
-
-    .. function:: asyncRemoteExec(fname, arg1=None, arg2=None)
-
-
--- a/doc/book/en/annexes/faq.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,437 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Frequently Asked Questions (FAQ)
-================================
-
-
-Generalities
-````````````
-
-Why do you use the LGPL license to prevent me from doing X ?
-------------------------------------------------------------
-
-LGPL means that *if* you redistribute your application, you need to
-redistribute the changes you made to CubicWeb under the LGPL licence.
-
-Publishing a web site has nothing to do with redistributing source
-code according to the terms of the LGPL. A fair amount of companies
-use modified LGPL code for internal use. And someone could publish a
-*CubicWeb* component under a BSD licence for others to plug into a
-LGPL framework without any problem. The only thing we are trying to
-prevent here is someone taking the framework and packaging it as
-closed source to his own clients.
-
-Why does not CubicWeb have a template language ?
-------------------------------------------------
-
-There are enough template languages out there. You can use your
-preferred template language if you want. [explain how to use a
-template language]
-
-*CubicWeb* does not define its own templating language as this was
-not our goal. Based on our experience, we realized that
-we could gain productivity by letting designers use design tools
-and developpers develop without the use of the templating language
-as an intermediary that could not be anyway efficient for both parties.
-Python is the templating language that we use in *CubicWeb*, but again,
-it does not prevent you from using a templating language.
-
-Moreover, CubicWeb currently supports `simpletal`_ out of the box and
-it is also possible to use the `cwtags`_ library to build html trees
-using the `with statement`_ with more comfort than raw strings.
-
-.. _`simpletal`: http://www.owlfish.com/software/simpleTAL/
-.. _`cwtags`: http://www.cubicweb.org/project/cwtags
-.. _`with statement`: http://www.python.org/dev/peps/pep-0343/
-
-Why do you think using pure python is better than using a template language ?
------------------------------------------------------------------------------
-
-Python is an Object Oriented Programming language and as such it
-already provides a consistent and strong architecture and syntax
-a templating language would not reach.
-
-Using Python instead of a template langage for describing the user interface
-makes it to maintain with real functions/classes/contexts without the need of
-learning a new dialect. By using Python, we use standard OOP techniques and
-this is a key factor in a robust application.
-
-CubicWeb looks pretty recent. Is it stable ?
---------------------------------------------
-
-It is constantly evolving, piece by piece.  The framework has evolved since
-2001 and data has been migrated from one schema to the other ever since. There
-is a well-defined way to handle data and schema migration.
-
-You can see the roadmap there:
-http://www.cubicweb.org/project/cubicweb?tab=projectroadmap_tab.
-
-
-Why is the RQL query language looking similar to X ?
-----------------------------------------------------
-
-It may remind you of SQL but it is higher level than SQL, more like
-SPARQL. Except that SPARQL did not exist when we started the project.
-With version 3.4, CubicWeb has support for SPARQL.
-
-The RQL language is what is going to make a difference with django-
-like frameworks for several reasons.
-
-1. accessing data is *much* easier with it. One can write complex
-   queries with RQL that would be tedious to define and hard to maintain
-   using an object/filter suite of method calls.
-
-2. it offers an abstraction layer allowing your applications to run
-   on multiple back-ends. That means not only various SQL backends
-   (postgresql, sqlite, sqlserver, mysql), but also non-SQL data stores like
-   LDAP directories and subversion/mercurial repositories (see the `vcsfile`
-   component).
-
-Which ajax library is CubicWeb using ?
---------------------------------------
-
-CubicWeb uses jQuery_ and provides a few helpers on top of that. Additionally,
-some jQuery plugins are provided (some are provided in specific cubes).
-
-.. _jQuery: http://jquery.com
-
-
-Development
-```````````
-
-How to change the instance logo ?
----------------------------------
-
-The logo is managed by css. You must provide a custom css that will contain
-the code below: 
-
-::
-   
-     #logo {
-        background-image: url("logo.jpg");
-     }
-
-
-``logo.jpg`` is in ``mycube/data`` directory.
-
-How to create an anonymous user ?
----------------------------------
-
-This allows to browse the site without being authenticated. In the
-``all-in-one.conf`` file of your instance, define the anonymous user
-as follows ::
-
-  # login of the CubicWeb user account to use for anonymous user (if you want to
-  # allow anonymous)
-  anonymous-user=anon
-
-  # password of the CubicWeb user account matching login
-  anonymous-password=anon
-
-You also must ensure that this `anon` user is a registered user of
-the DB backend. If not, you can create through the administation
-interface of your instance by adding a user with in the group `guests`.
-
-.. note::
-    While creating a new instance, you can decide to allow access
-    to anonymous user, which will automatically execute what is
-    decribed above.
-
-How to load data from a python script ?
----------------------------------------
-Please, refer to :ref:`UsingPyro`.
-
-
-How to format an entity date attribute ?
-----------------------------------------
-
-If your schema has an attribute of type `Date` or `Datetime`, you usually want to
-format it when displaying it. First, you should define your preferred format
-using the site configuration panel
-``http://appurl/view?vid=systempropertiesform`` and then set ``ui.date`` and/or
-``ui.datetime``.  Then in the view code, use:
-
-.. sourcecode:: python
-
-    entity.printable_value(date_attribute)
-
-which will always return a string whatever the attribute's type (so it's
-recommended also for other attribute types). By default it expects to generate
-HTML, so it deals with rich text formating, xml escaping...
-
-How to update a database after a schema modification ?
-------------------------------------------------------
-
-It depends on what has been modified in the schema.
-
-* update the permissions and properties of an entity or a relation:
-  ``sync_schema_props_perms('MyEntityOrRelation')``.
-
-* add an attribute: ``add_attribute('MyEntityType', 'myattr')``.
-
-* add a relation: ``add_relation_definition('SubjRelation', 'MyRelation', 'ObjRelation')``.
-
-I get `NoSelectableObject` exceptions, how do I debug selectors ?
------------------------------------------------------------------
-
-You just need to put the appropriate context manager around view/component
-selection. One standard place for components is in cubicweb/vregistry.py: 
-
-.. sourcecode:: python
-
-    def possible_objects(self, *args, **kwargs):
-        """return an iterator on possible objects in this registry for the given
-        context
-        """
-        from logilab.common.registry import traced_selection
-        with traced_selection():
-            for appobjects in self.itervalues():
-                try:
-                    yield self._select_best(appobjects, *args, **kwargs)
-                except NoSelectableObject:
-                    continue
-
-This will yield additional WARNINGs, like this::
-
-    2009-01-09 16:43:52 - (cubicweb.selectors) WARNING: selector one_line_rset returned 0 for <class 'cubicweb.web.views.basecomponents.WFHistoryVComponent'>
-
-For views, you can put this context in `cubicweb/web/views/basecontrollers.py` in
-the `ViewController`:
-
-.. sourcecode:: python
-
-    def _select_view_and_rset(self, rset):
-        ...
-        try:
-            from logilab.common.registry import traced_selection
-            with traced_selection():
-                view = self._cw.vreg['views'].select(vid, req, rset=rset)
-        except ObjectNotFound:
-            self.warning("the view %s could not be found", vid)
-            req.set_message(req._("The view %s could not be found") % vid)
-            vid = vid_from_rset(req, rset, self._cw.vreg.schema)
-            view = self._cw.vreg['views'].select(vid, req, rset=rset)
-        ...
-
-I get "database is locked" when executing tests
------------------------------------------------
-
-If you have "database is locked" as error when you are executing security tests,
-it is usually because commit or rollback are missing before login() calls.
-
-You can also use a context manager, to avoid such errors, as described
-here: :ref:`securitytest`.
-
-
-What are hooks used for ?
--------------------------
-
-Hooks are executed around (actually before or after) events.  The most common
-events are data creation, update and deletion.  They permit additional constraint
-checking (those not expressible at the schema level), pre and post computations
-depending on data movements.
-
-As such, they are a vital part of the framework.
-
-Other kinds of hooks, called Operations, are available
-for execution just before commit.
-
-For more information, read :ref:`hooks` section.
-
-
-Configuration
-`````````````
-
-How to configure a LDAP source ?
---------------------------------
-
-See :ref:`LDAP`.
-
-How to import LDAP users in |cubicweb| ?
-----------------------------------------
-
-  Here is a useful script which enables you to import LDAP users
-  into your *CubicWeb* instance by running the following:
-
-.. sourcecode:: python
-
-    import os
-    import pwd
-    import sys
-
-    from logilab.database import get_connection
-
-    def getlogin():
-        """avoid using os.getlogin() because of strange tty/stdin problems
-        (man 3 getlogin)
-        Another solution would be to use $LOGNAME, $USER or $USERNAME
-        """
-        return pwd.getpwuid(os.getuid())[0]
-
-
-    try:
-        database = sys.argv[1]
-    except IndexError:
-        print 'USAGE: python ldap2system.py <database>'
-        sys.exit(1)
-
-    if raw_input('update %s db ? [y/n]: ' % database).strip().lower().startswith('y'):
-        cnx = get_connection(user=getlogin(), database=database)
-        cursor = cnx.cursor()
-
-        insert = ('INSERT INTO euser (creation_date, eid, modification_date, login, '
-                  ' firstname, surname, last_login_time, upassword) '
-                  "VALUES (%(mtime)s, %(eid)s, %(mtime)s, %(login)s, %(firstname)s, "
-                  "%(surname)s, %(mtime)s, './fqEz5LeZnT6');")
-        update = "UPDATE entities SET source='system' WHERE eid=%(eid)s;"
-        cursor.execute("SELECT eid,type,source,extid,mtime FROM entities WHERE source!='system'")
-        for eid, type, source, extid, mtime in cursor.fetchall():
-            if type != 'CWUser':
-                print "don't know what to do with entity type", type
-                continue
-            if source != 'ldapuser':
-                print "don't know what to do with source type", source
-                continue
-            ldapinfos = dict(x.strip().split('=') for x in extid.split(','))
-            login = ldapinfos['uid']
-            firstname = ldapinfos['uid'][0].upper()
-            surname = ldapinfos['uid'][1:].capitalize()
-            if login != 'jcuissinat':
-                args = dict(eid=eid, type=type, source=source, login=login,
-                            firstname=firstname, surname=surname, mtime=mtime)
-                print args
-                cursor.execute(insert, args)
-                cursor.execute(update, args)
-
-        cnx.commit()
-        cnx.close()
-
-
-Security
-````````
-
-How to reset the password for user joe ?
-----------------------------------------
-
-If you want to reset the admin password for ``myinstance``, do::
-
-    $ cubicweb-ctl reset-admin-pwd myinstance
-
-You need to generate a new encrypted password::
-
-    $ python
-    >>> from cubicweb.server.utils import crypt_password
-    >>> crypt_password('joepass')
-    'qHO8282QN5Utg'
-    >>>
-
-and paste it in the database::
-
-    $ psql mydb
-    mydb=> update cw_cwuser set cw_upassword='qHO8282QN5Utg' where cw_login='joe';
-    UPDATE 1
-
-if you're running over SQL Server, you need to use the CONVERT
-function to convert the string to varbinary(255). The SQL query is
-therefore::
-
-    update cw_cwuser set cw_upassword=CONVERT(varbinary(255), 'qHO8282QN5Utg') where cw_login='joe';
-
-Be careful, the encryption algorithm is different on Windows and on
-Unix. You cannot therefore use a hash generated on Unix to fill in a
-Windows database, nor the other way round.
-
-
-You can prefer use a migration script similar to this shell invocation instead::
-
-    $ cubicweb-ctl shell <instance>
-    >>> from cubicweb import Binary
-    >>> from cubicweb.server.utils import crypt_password
-    >>> crypted = crypt_password('joepass')
-    >>> rset = rql('Any U WHERE U is CWUser, U login "joe"')
-    >>> joe = rset.get_entity(0,0)
-    >>> joe.cw_set(upassword=Binary(crypted))
-
-Please, refer to the script example is provided in the `misc/examples/chpasswd.py` file.
-
-The more experimented people would use RQL request directly::
-
-    >>> rql('SET X upassword %(a)s WHERE X is CWUser, X login "joe"',
-    ...     {'a': crypted})
-
-I've just created a user in a group and it doesn't work !
----------------------------------------------------------
-
-You are probably getting errors such as ::
-
-  remove {'PR': 'Project', 'C': 'CWUser'} from solutions since your_user has no read access to cost
-
-This is because you have to put your user in the "users" group. The user has to
-be in both groups.
-
-How is security implemented ?
-------------------------------
-
-The basis for security is a mapping from operations to groups or
-arbitrary RQL expressions. These mappings are scoped to entities and
-relations.
-
-This is an example for an Entity Type definition:
-
-.. sourcecode:: python
-
-    class Version(EntityType):
-        """a version is defining the content of a particular project's
-        release"""
-        # definition of attributes is voluntarily missing
-        __permissions__ = {'read': ('managers', 'users', 'guests',),
-                           'update': ('managers', 'logilab', 'owners'),
-                           'delete': ('managers',),
-                           'add': ('managers', 'logilab',
-                                   ERQLExpression('X version_of PROJ, U in_group G, '
-                                                  'PROJ require_permission P, '
-                                                  'P name "add_version", P require_group G'),)}
-
-The above means that permission to read a Version is granted to any
-user that is part of one of the groups 'managers', 'users', 'guests'.
-The 'add' permission is granted to users in group 'managers' or
-'logilab' or to users in group G, if G is linked by a permission
-entity named "add_version" to the version's project.
-
-An example for a Relation Definition (RelationType both defines a
-relation type and implicitly one relation definition, on which the
-permissions actually apply):
-
-.. sourcecode:: python
-
-    class version_of(RelationType):
-        """link a version to its project. A version is necessarily linked
-        to one and only one project. """
-        # some lines voluntarily missing
-        __permissions__ = {'read': ('managers', 'users', 'guests',),
-                           'delete': ('managers', ),
-                           'add': ('managers', 'logilab',
-                                   RRQLExpression('O require_permission P, P name "add_version", '
-                                                  'U in_group G, P require_group G'),) }
-
-The main difference lies in the basic available operations (there is
-no 'update' operation) and the usage of an RRQLExpression (rql
-expression for a relation) instead of an ERQLExpression (rql
-expression for an entity).
-
-You can find additional information in the section :ref:`securitymodel`.
-
-Is it possible to bypass security from the UI (web front) part ?
-----------------------------------------------------------------
-
-No. Only Hooks/Operations can do that.
-
-Can PostgreSQL and CubicWeb authentication work with kerberos ?
-----------------------------------------------------------------
-
-If you have PostgreSQL set up to accept kerberos authentication, you can set
-the db-host, db-name and db-user parameters in the `sources` configuration
-file while leaving the password blank. It should be enough for your
-instance to connect to postgresql with a kerberos ticket.
-
-
--- a/doc/book/en/annexes/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _Part4:
-
-----------
-Appendixes
-----------
-
-The following chapters are reference material.
-
-.. toctree::
-   :maxdepth: 1
-   :numbered:
-
-   faq
-   rql/index
-   mercurial
-   depends
-   docstrings-conventions
--- a/doc/book/en/annexes/mercurial.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _MercurialPresentation:
-
-Introducing Mercurial
-=====================
-
-Introduction
-````````````
-Mercurial_ manages a distributed repository containing revisions
-trees (each revision indicates the changes required to obtain the
-next, and so on). Locally, we have a repository containing revisions
-tree, and a working directory. It is possible
-to put in its working directory, one of the versions of its local repository,
-modify and then push it in its repository.
-It is also possible to get revisions from another repository or to export
-its own revisions from the local repository to another repository.
-
-.. _Mercurial: http://www.selenic.com/mercurial/
-
-In contrast to CVS/Subversion, we usually create a repository per
-project to manage.
-
-In a collaborative development, we usually create a central repository
-accessible to all developers of the project. These central repository is used
-as a reference. According to their needs, everyone can have a local repository,
-that they will have to synchronize with the central repository from time to time.
-
-
-Major commands
-``````````````
-* Create a local repository::
-
-     hg clone ssh://myhost//home/src/repo
-
-* See the contents of the local repository (graphical tool in Qt)::
-
-     hgview
-
-* Add a sub-directory or file in the current directory::
-
-     hg add subdir
-
-* Move to the working directory a specific revision (or last
-  revision) from the local repository::
-
-     hg update [identifier-revision]
-     hg up [identifier-revision]
-
-* Get in its local repository, the tree of revisions contained in a
-  remote repository (this does not change the local directory)::
-
-     hg pull ssh://myhost//home/src/repo
-     hg pull -u ssh://myhost//home/src/repo # equivalent to pull + update
-
-* See what are the heads of branches of the local repository if a `pull`
-  returned a new branch::
-
-     hg heads
-
-* Submit the working directory in the local repository (and create a new
-  revision)::
-
-     hg commit
-     hg ci
-
-* Merge with the mother revision of local directory, another revision from
-  the local respository (the new revision will be then two mothers
-  revisions)::
-
-     hg merge identifier-revision
-
-* Export to a remote repository, the tree of revisions in its content
-  local respository (this does not change the local directory)::
-
-     hg push ssh://myhost//home/src/repo
-
-* See what local revisions are not in another repository::
-
-     hg outgoing ssh://myhost//home/src/repo
-
-* See what are the revisions of a repository not found locally::
-
-     hg incoming ssh://myhost//home/src/repo
-
-* See what is the revision of the local repository which has been taken out
-  from the working directory and amended::
-
-     hg parent
-
-* See the differences between the working directory and the mother revision
-  of the local repository, possibly to submit them in the local repository::
-
-     hg diff
-     hg commit-tool
-     hg ct
-
-
-Best Practices
-``````````````
-* Remember to `hg pull -u` regularly, and particularly before
-   a `hg commit`.
-
-* Remember to `hg push` when your repository contains a version
-  relatively stable of your changes.
-
-* If a `hg pull -u` created a new branch head:
-
-   1. find its identifier with `hg head`
-   2. merge with `hg merge`
-   3. `hg ci`
-   4. `hg push`
-
-Installation of the guestrepo extension
-```````````````````````````````````````
-
-Set up the guestrepo extension by getting a copy of the sources
-from https://bitbucket.org/selinc/guestrepo and adding the following
-lines to your ``~/.hgrc``: ::
-
-   [extensions]
-   guestrepo=/path/to/guestrepo/guestrepo
-
-
-More information
-````````````````
-
-For more information about Mercurial, please refer to the Mercurial project online documentation_.
-
-.. _documentation: http://www.selenic.com/mercurial/wiki/
-
Binary file doc/book/en/annexes/rql/Graph-ex.gif has changed
--- a/doc/book/en/annexes/rql/debugging.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _DEBUGGING:
-
-Debugging RQL
--------------
-
-Available levels
-~~~~~~~~~~~~~~~~
-
-Server debugging flags. They may be combined using binary operators.
-
-.. autodata:: cubicweb.server.DBG_NONE
-.. autodata:: cubicweb.server.DBG_RQL
-.. autodata:: cubicweb.server.DBG_SQL
-.. autodata:: cubicweb.server.DBG_REPO
-.. autodata:: cubicweb.server.DBG_MS
-.. autodata:: cubicweb.server.DBG_HOOKS
-.. autodata:: cubicweb.server.DBG_OPS
-.. autodata:: cubicweb.server.DBG_MORE
-.. autodata:: cubicweb.server.DBG_ALL
-
-
-Enable verbose output
-~~~~~~~~~~~~~~~~~~~~~
-
-To debug your RQL statements, it can be useful to enable a verbose output:
-
-.. sourcecode:: python
-
-    from cubicweb import server
-    server.set_debug(server.DBG_RQL|server.DBG_SQL|server.DBG_ALL)
-
-.. autofunction:: cubicweb.server.set_debug
-
-Another example showing how to debug hooks at a specific code site:
-
-.. sourcecode:: python
-
-    from cubicweb.server import debugged, DBG_HOOKS
-    with debugged(DBG_HOOKS):
-        person.cw_set(works_for=company)
-
-
-Detect largest RQL queries
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-See `Profiling and performance` chapter (see :ref:`PROFILING`).
-
-
-API
-~~~
-
-.. autoclass:: cubicweb.server.debugged
-
--- a/doc/book/en/annexes/rql/implementation.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-
-
-Implementation
---------------
-
-BNF grammar
-~~~~~~~~~~~
-
-The terminal elements are in capital letters, non-terminal in lowercase.
-The value of the terminal elements (between quotes) is a Python regular
-expression.
-::
-
-     statement ::= (select | delete | insert | update) ';'
-
-
-     # select specific rules
-     select      ::= 'DISTINCT'? E_TYPE selected_terms restriction? group? sort?
-
-     selected_terms ::= expression ( ',' expression)*
-
-     group       ::= 'GROUPBY' VARIABLE ( ',' VARIABLE)*
-
-     sort        ::= 'ORDERBY' sort_term ( ',' sort_term)*
-
-     sort_term   ::=  VARIABLE sort_method =?
-
-     sort_method ::= 'ASC' | 'DESC'
-
-
-     # delete specific rules
-     delete ::= 'DELETE' (variables_declaration | relations_declaration) restriction?
-
-
-     # insert specific rules
-     insert ::= 'INSERT' variables_declaration ( ':' relations_declaration)? restriction?
-
-
-     # update specific rules
-     update ::= 'SET' relations_declaration restriction
-
-
-     # common rules
-     variables_declaration ::= E_TYPE VARIABLE (',' E_TYPE VARIABLE)*
-
-     relations_declaration ::= simple_relation (',' simple_relation)*
-
-     simple_relation ::= VARIABLE R_TYPE expression
-
-     restriction ::= 'WHERE' relations
-
-     relations   ::= relation (LOGIC_OP relation)*
-                   | '(' relations')'
-
-     relation    ::= 'NOT'? VARIABLE R_TYPE COMP_OP? expression
-                   | 'NOT'? R_TYPE VARIABLE 'IN' '(' expression (',' expression)* ')'
-
-     expression  ::= var_or_func_or_const (MATH_OP var_or_func_or_const) *
-                   | '(' expression ')'
-
-     var_or_func_or_const ::= VARIABLE | function | constant
-
-     function    ::= FUNCTION '(' expression ( ',' expression) * ')'
-
-     constant    ::= KEYWORD | STRING | FLOAT | INT
-
-     # tokens
-     LOGIC_OP ::= ',' | 'OR' | 'AND'
-     MATH_OP  ::= '+' | '-' | '/' | '*'
-     COMP_OP  ::= '>' | '>=' | '=' | '<=' | '<' | '~=' | 'LIKE'
-
-     FUNCTION ::= 'MIN' | 'MAX' | 'SUM' | 'AVG' | 'COUNT' | 'UPPER' | 'LOWER'
-
-     VARIABLE ::= '[A-Z][A-Z0-9]*'
-     E_TYPE   ::= '[A-Z]\w*'
-     R_TYPE   ::= '[a-z_]+'
-
-     KEYWORD  ::= 'TRUE' | 'FALSE' | 'NULL' | 'TODAY' | 'NOW'
-     STRING   ::= "'([^'\]|\\.)*'" |'"([^\"]|\\.)*\"'
-     FLOAT    ::= '\d+\.\d*'
-     INT      ::= '\d+'
-
-
-Internal representation (syntactic tree)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The tree research does not contain the selected variables
-(e.g. there is only what follows "WHERE").
-
-The insertion tree does not contain the variables inserted or relations
-defined on these variables (e.g. there is only what follows "WHERE").
-
-The removal tree does not contain the deleted variables and relations
-(e.g. there is only what follows the "WHERE").
-
-The update tree does not contain the variables and relations updated
-(e.g. there is only what follows the "WHERE").
-
-::
-
-     Select         ((Relationship | And | Or)?, Group?, Sort?)
-     Insert         (Relations | And | Or)?
-     Delete         (Relationship | And | Or)?
-     Update         (Relations | And | Or)?
-
-     And            ((Relationship | And | Or), (Relationship | And | Or))
-     Or             ((Relationship | And | Or), (Relationship | And | Or))
-
-     Relationship   ((VariableRef, Comparison))
-
-     Comparison     ((Function | MathExpression | Keyword | Constant | VariableRef) +)
-
-     Function       (())
-     MathExpression ((MathExpression | Keyword | Constant | VariableRef), (MathExpression | Keyword | Constant | VariableRef))
-
-     Group          (VariableRef +)
-     Sort           (SortTerm +)
-     SortTerm       (VariableRef +)
-
-     VariableRef    ()
-     Variable       ()
-     Keyword        ()
-     Constant       ()
-
-
-Known limitations
-~~~~~~~~~~~~~~~~~
-
-- The current implementation does not support linking two relations of type 'is'
-  with an OR. I do not think that the negation is supported on this type of
-  relation (XXX to be confirmed).
-
-- missing COALESCE and certainly other things...
-
-- writing an rql query requires knowledge of the used schema (with real relation
-  names and entities, not those viewed in the user interface). On the other
-  hand, we cannot really bypass that, and it is the job of a user interface to
-  hide the RQL.
-
-
-Topics
-~~~~~~
-
-It would be convenient to express the schema matching
-relations (non-recursive rules)::
-
-     Document class Type <-> Document occurence_of Fiche class Type
-     Sheet class Type    <-> Form collection Collection class Type
-
-Therefore 1. becomes::
-
-     Document X where
-     X class C, C name 'Cartoon'
-     X owned_by U, U login 'syt'
-     X available true
-
-I'm not sure that we should handle this at RQL level ...
-
-There should also be a special relation 'anonymous'.
--- a/doc/book/en/annexes/rql/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-.. _RQLChapter:
-
-Relation Query Language (RQL)
-=============================
-
-This chapter describes the Relation Query Language syntax and its implementation in CubicWeb.
-
-.. toctree::
-   :maxdepth: 2
-
-   intro
-   language
-   debugging
-   implementation
--- a/doc/book/en/annexes/rql/intro.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-
-.. _rql_intro:
-
-Introduction
-------------
-
-Goals of RQL
-~~~~~~~~~~~~
-
-The goal is to have a semantic language in order to:
-
-- query relations in a clear syntax
-- empowers access to data repository manipulation
-- making attributes/relations browsing easy
-
-As such, attributes will be regarded as cases of special relations (in
-terms of usage, the user should see no syntactic difference between an
-attribute and a relation).
-
-Comparison with existing languages
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-SQL
-```
-
-RQL may remind of SQL but works at a higher abstraction level (the *CubicWeb*
-framework generates SQL from RQL to fetch data from relation databases). RQL is
-focused on browsing relations. The user needs only to know about the *CubicWeb*
-data model he is querying, but not about the underlying SQL model.
-
-Sparql
-``````
-
-The query language most similar to RQL is SPARQL_, defined by the W3C to serve
-for the semantic web.
-
-Versa
-`````
-
-We should look in more detail, but here are already some ideas for the moment
-... Versa_ is the language most similar to what we wanted to do, but the model
-underlying data being RDF, there are some things such as namespaces or
-handling of the RDF types which does not interest us. On the functionality
-level, Versa_ is very comprehensive including through many functions of
-conversion and basic types manipulation, which we may want to look at one time
-or another.  Finally, the syntax is a little esoteric.
-
-Datalog
-```````
-
-Datalog_ is a prolog derived query langage which applies to relational
-databases. It is more expressive than RQL in that it accepts either
-extensional_ and intensional_ predicates (or relations). As of now,
-RQL only deals with intensional relations.
-
-The different types of queries
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Search (`Any`)
-   Extract entities and attributes of entities.
-
-Insert entities (`INSERT`)
-   Insert new entities or relations in the database.
-   It can also directly create relationships for the newly created entities.
-
-Update entities, create relations (`SET`)
-   Update existing entities in the database,
-   or create relations between existing entities.
-
-Delete entities or relationship (`DELETE`)
-   Remove entities or relations existing in the database.
-
-
-RQL relation expressions
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-RQL expressions apply to a live database defined by a
-:ref:`datamodel_definition`. Apart from the main type, or head, of the
-expression (search, insert, etc.) the most common constituent of an
-RQL expression is a (set of) relation expression(s).
-
-An RQL relation expression contains three components:
-
-* the subject, which is an entity type
-* the predicate, which is a relation definition (an arc of the schema)
-* the object, which is either an attribute or a relation to another entity
-
-.. image:: Graph-ex.gif
-    :alt: <subject> <predicate> <object>
-    :align: center
-
-.. warning::
-
- A relation is always expressed in the order: ``subject``,
- ``predicate``, ``object``.
-
- It is important to determine if the entity type is subject or object
- to construct a valid expression. Inverting the subject/object is an
- error since the relation cannot be found in the schema.
-
- If one does not have access to the code, one can find the order by
- looking at the schema image in manager views (the subject is located
- at the beginning of the arrow).
-
-An example of two related relation expressions::
-
-  P works_for C, P name N
-
-RQL variables represent typed entities. The type of entities is
-either automatically inferred (by looking at the possible relation
-definitions, see :ref:`RelationDefinition`) or explicitely constrained
-using the ``is`` meta relation.
-
-In the example above, we barely need to look at the schema. If
-variable names (in the RQL expression) and relation type names (in the
-schema) are expresssively designed, the human reader can infer as much
-as the |cubicweb| querier.
-
-The ``P`` variable is used twice but it always represent the same set
-of entities. Hence ``P works_for C`` and ``P name N`` must be
-compatible in the sense that all the Ps (which *can* refer to
-different entity types) must accept the ``works_for`` and ``name``
-relation types. This does restrict the set of possible values of P.
-
-Adding another relation expression::
-
-  P works_for C, P name N, C name "logilab"
-
-This further restricts the possible values of P through an indirect
-constraint on the possible values of ``C``. The RQL-level unification_
-happening there is translated to one (or several) joins_ at the
-database level.
-
-.. note::
-
- In |cubicweb|, the term `relation` is often found without ambiguity
- instead of `predicate`.  This predicate is also known as the
- `property` of the triple in `RDF concepts`_
-
-
-RQL Operators
-~~~~~~~~~~~~~
-
-An RQL expression's head can be completed using various operators such
-as ``ORDERBY``, ``GROUPBY``, ``HAVING``, ``LIMIT`` etc.
-
-RQL relation expressions can be grouped with ``UNION`` or
-``WITH``. Predicate oriented keywords such as ``EXISTS``, ``OR``,
-``NOT`` are available.
-
-The complete zoo of RQL operators is described extensively in the
-following chapter (:ref:`RQL`).
-
-.. _RDF concepts: http://www.w3.org/TR/rdf-concepts/
-.. _Versa: http://wiki.xml3k.org/Versa
-.. _SPARQL: http://www.w3.org/TR/rdf-sparql-query/
-.. _unification: http://en.wikipedia.org/wiki/Unification_(computing)
-.. _joins: http://en.wikipedia.org/wiki/Join_(SQL)
-.. _Datalog: http://en.wikipedia.org/wiki/Datalog
-.. _intensional: http://en.wikipedia.org/wiki/Intensional_definition
-.. _extensional: http://en.wikipedia.org/wiki/Extension_(predicate_logic)
-
--- a/doc/book/en/annexes/rql/language.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,804 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _RQL:
-
-RQL syntax
-----------
-
-.. _RQLKeywords:
-
-Reserved keywords
-~~~~~~~~~~~~~~~~~
-
-::
-
-  AND, ASC, BEING, DELETE, DESC, DISTINCT, EXISTS, FALSE, GROUPBY,
-  HAVING, ILIKE, INSERT, LIKE, LIMIT, NOT, NOW, NULL, OFFSET,
-  OR, ORDERBY, SET, TODAY, TRUE, UNION, WHERE, WITH
-
-The keywords are not case sensitive. You should not use them when defining your
-schema, or as RQL variable names.
-
-
-.. _RQLCase:
-
-Case
-~~~~
-
-* Variables should be all upper-cased.
-
-* Relation should be all lower-cased and match exactly names of relations defined
-  in the schema.
-
-* Entity types should start with an upper cased letter and be followed by at least
-  a lower cased latter.
-
-
-.. _RQLVariables:
-
-Variables and typing
-~~~~~~~~~~~~~~~~~~~~
-
-Entities and values to browse and/or select are represented in the query by
-*variables* that must be written in capital letters.
-
-With RQL, we do not distinguish between entities and attributes. The value of an
-attribute is considered as an entity of a particular type (see below), linked to
-one (real) entity by a relation called the name of the attribute, where the
-entity is the subject and the attribute the object.
-
-The possible type(s) for each variable is derived from the schema according to
-the constraints expressed above and thanks to the relations between each
-variable.
-
-We can restrict the possible types for a variable using the special relation
-**is** in the restrictions.
-
-
-.. _VirtualRelations:
-
-Virtual relations
-~~~~~~~~~~~~~~~~~
-
-Those relations may only be used in RQL query but are not actual attributes of
-your entities.
-
-* `has_text`: relation to use to query the full text index (only for entities
-  having fulltextindexed attributes).
-
-* `identity`: relation to use to tell that a RQL variable is the same as another
-  when you've to use two different variables for querying purpose. On the
-  opposite it's also useful together with the ``NOT`` operator to tell that two
-  variables should not identify the same entity
-
-
-.. _RQLLiterals:
-
-Literal expressions
-~~~~~~~~~~~~~~~~~~~
-
-Bases types supported by RQL are those supported by yams schema. Literal values
-are expressed as explained below:
-
-* string should be between double or single quotes. If the value contains a
-  quote, it should be preceded by a backslash '\\'
-
-* floats separator is dot '.'
-
-* boolean values are ``TRUE`` and ``FALSE`` keywords
-
-* date and time should be expressed as a string with ISO notation : YYYY/MM/DD
-  [hh:mm], or using keywords ``TODAY`` and ``NOW``
-
-You may also use the ``NULL`` keyword, meaning 'unspecified'.
-
-
-.. _RQLOperators:
-
-Operators
-~~~~~~~~~
-
-.. _RQLLogicalOperators:
-
-Logical operators
-`````````````````
-::
-
-     AND, OR, NOT, ','
-
-',' is equivalent to 'AND' but with the smallest among the priority of logical
-operators (see :ref:`RQLOperatorsPriority`).
-
-.. _RQLMathematicalOperators:
-
-Mathematical operators
-``````````````````````
-
-+----------+---------------------+-----------+--------+
-| Operator |    Description      | Example   | Result |
-+==========+=====================+===========+========+
-|  `+`     | addition            | 2 + 3     | 5      |
-+----------+---------------------+-----------+--------+
-|  `-`     | subtraction         | 2 - 3     | -1     |
-+----------+---------------------+-----------+--------+
-|  `*`     | multiplication      | 2 * 3     | 6      |
-+----------+---------------------+-----------+--------+
-|  /       | division            | 4 / 2     | 2      |
-+----------+---------------------+-----------+--------+
-|  %       | modulo (remainder)  | 5 % 4     | 1      |
-+----------+---------------------+-----------+--------+
-|  ^       | exponentiation      | 2.0 ^ 3.0 | 8      |
-+----------+---------------------+-----------+--------+
-|  &       | bitwise AND         | 91 & 15   | 11     |
-+----------+---------------------+-----------+--------+
-|  `|`     | bitwise OR          | 32 | 3    | 35     |
-+----------+---------------------+-----------+--------+
-|  #       | bitwise XOR         | 17 # 5    | 20     |
-+----------+---------------------+-----------+--------+
-|  ~       | bitwise NOT         | ~1        | -2     |
-+----------+---------------------+-----------+--------+
-|  <<      | bitwise shift left  | 1 << 4    | 16     |
-+----------+---------------------+-----------+--------+
-|  >>      | bitwise shift right | 8 >> 2    | 2      |
-+----------+---------------------+-----------+--------+
-
-
-Notice integer division truncates results depending on the backend behaviour. For
-instance, postgresql does.
-
-
-.. _RQLComparisonOperators:
-
-Comparison operators
-````````````````````
- ::
-
-     =, !=, <, <=, >=, >, IN
-
-
-The syntax to use comparison operators is:
-
-    `VARIABLE attribute <operator> VALUE`
-
-The `=` operator is the default operator and can be omitted, i.e. :
-
-    `VARIABLE attribute = VALUE`
-
-is equivalent to
-
-    `VARIABLE attribute VALUE`
-
-
-The operator `IN` provides a list of possible values:
-
-.. sourcecode:: sql
-
-    Any X WHERE X name IN ('chauvat', 'fayolle', 'di mascio', 'thenault')
-
-
-.. _RQLStringOperators:
-
-String operators
-````````````````
-::
-
-  LIKE, ILIKE, ~=, REGEXP
-
-The ``LIKE`` string operator can be used with the special character `%` in
-a string as wild-card:
-
-.. sourcecode:: sql
-
-     -- match every entity whose name starts with 'Th'
-     Any X WHERE X name ~= 'Th%'
-     -- match every entity whose name endswith 'lt'
-     Any X WHERE X name LIKE '%lt'
-     -- match every entity whose name contains a 'l' and a 't'
-     Any X WHERE X name LIKE '%l%t%'
-
-``ILIKE`` is the case insensitive version of ``LIKE``. It's not
-available on all backend (e.g. sqlite doesn't support it). If not available for
-your backend, ``ILIKE`` will behave like ``LIKE``.
-
-`~=` is a shortcut version of ``ILIKE``, or of ``LIKE`` when the
-former is not available on the back-end.
-
-
-The ``REGEXP`` is an alternative to ``LIKE`` that supports POSIX
-regular expressions:
-
-.. sourcecode:: sql
-
-   -- match entities whose title starts with a digit
-   Any X WHERE X title REGEXP "^[0-9].*"
-
-
-The underlying SQL operator used is back-end-dependent :
-
-- the ``~`` operator is used for postgresql,
-- the ``REGEXP`` operator for mysql and sqlite.
-
-Other back-ends are not supported yet.
-
-
-.. _RQLOperatorsPriority:
-
-Operators priority
-``````````````````
-
-#. `(`, `)`
-#. `^`, `<<`, `>>`
-#. `*`, `/`, `%`, `&`
-#. `+`, `-`, `|`, `#`
-#. `NOT`
-#. `AND`
-#. `OR`
-#. `,`
-
-
-.. _RQLSearchQuery:
-
-Search Query
-~~~~~~~~~~~~
-
-Simplified grammar of search query: ::
-
-   [ `DISTINCT`] `Any` V1 (, V2) \*
-   [ `GROUPBY` V1 (, V2) \*] [ `ORDERBY` <orderterms>]
-   [ `LIMIT` <value>] [ `OFFSET` <value>]
-   [ `WHERE` <triplet restrictions>]
-   [ `WITH` V1 (, V2)\* BEING (<query>)]
-   [ `HAVING` <other restrictions>]
-   [ `UNION` <query>]
-
-Selection
-`````````
-
-The fist occuring clause is the selection of terms that should be in the result
-set.  Terms may be variable, literals, function calls, arithmetic, etc. and each
-term is separated by a comma.
-
-There will be as much column in the result set as term in this clause, respecting
-order.
-
-Syntax for function call is somewhat intuitive, for instance:
-
-.. sourcecode:: sql
-
-    Any UPPER(N) WHERE P firstname N
-
-
-Grouping and aggregating
-````````````````````````
-
-The ``GROUPBY`` keyword is followed by a list of terms on which results
-should be grouped. They are usually used with aggregate functions, responsible to
-aggregate values for each group (see :ref:`RQLAggregateFunctions`).
-
-For grouped queries, all selected variables must be either aggregated (i.e. used
-by an aggregate function) or grouped (i.e. listed in the ``GROUPBY``
-clause).
-
-
-Sorting
-```````
-
-The ``ORDERBY`` keyword if followed by the definition of the selection
-order: variable or column number followed by sorting method (``ASC``,
-``DESC``), ``ASC`` being the default. If the sorting method is not
-specified, then the sorting is ascendant (`ASC`).
-
-
-Pagination
-``````````
-
-The ``LIMIT`` and ``OFFSET`` keywords may be respectively used to
-limit the number of results and to tell from which result line to start (for
-instance, use `LIMIT 20` to get the first 20 results, then `LIMIT 20 OFFSET 20`
-to get the next 20.
-
-
-Restrictions
-````````````
-
-The ``WHERE`` keyword introduce one of the "main" part of the query, where
-you "define" variables and add some restrictions telling what you're interested
-in.
-
-It's a list of triplets "subject relation object", e.g. `V1 relation
-(V2 | <static value>)`. Triplets are separated using :ref:`RQLLogicalOperators`.
-
-.. note::
-
-  About the negation operator (``NOT``):
-
-  * ``NOT X relation Y`` is equivalent to ``NOT EXISTS(X relation Y)``
-
-  * ``Any X WHERE NOT X owned_by U`` means "entities that have no relation
-    ``owned_by``".
-
-  * ``Any X WHERE NOT X owned_by U, U login "syt"`` means "the entity have no
-     relation ``owned_by`` with the user syt". They may have a relation "owned_by"
-     with another user.
-
-In this clause, you can also use ``EXISTS`` when you want to know if some
-expression is true and do not need the complete set of elements that make it
-true. Testing for existence is much faster than fetching the complete set of
-results, especially when you think about using ``OR`` against several expressions. For instance
-if you want to retrieve versions which are in state "ready" or tagged by
-"priority", you should write :
-
-.. sourcecode:: sql
-
-    Any X ORDERBY PN,N
-    WHERE X num N, X version_of P, P name PN,
-          EXISTS(X in_state S, S name "ready")
-          OR EXISTS(T tags X, T name "priority")
-
-not
-
-.. sourcecode:: sql
-
-    Any X ORDERBY PN,N
-    WHERE X num N, X version_of P, P name PN,
-          (X in_state S, S name "ready")
-          OR (T tags X, T name "priority")
-
-Both queries aren't at all equivalent :
-
-* the former will retrieve all versions, then check for each one which are in the
-  matching state of or tagged by the expected tag,
-
-* the later will retrieve all versions, state and tags (cartesian product!),
-  compute join and then exclude each row which are in the matching state or
-  tagged by the expected tag. This implies that you won't get any result if the
-  in_state or tag tables are empty (ie there is no such relation in the
-  application). This is usually NOT what you want.
-
-Another common case where you may want to use ``EXISTS`` is when you
-find yourself using ``DISTINCT`` at the beginning of your query to
-remove duplicate results. The typical case is when you have a
-multivalued relation such as Version version_of Project and you want
-to retrieve projects which have a version:
-
-.. sourcecode:: sql
-
-  Any P WHERE V version_of P
-
-will return each project number of versions times. So you may be
-tempted to use:
-
-.. sourcecode:: sql
-
-  DISTINCT ANY P WHERE V version_of P
-
-This will work, but is not efficient, as it will use the ``SELECT
-DISTINCT`` SQL predicate, which needs to retrieve all projects, then
-sort them and discard duplicates, which can have a very high cost for
-large result sets. So the best way to write this is:
-
-.. sourcecode:: sql
-
-  ANY P WHERE EXISTS V version_of P
-
-
-You can also use the question mark (`?`) to mark optional relations. This allows
-you to select entities related **or not** to another. It is a similar concept
-to `Left outer join`_:
-
-    the result of a left outer join (or simply left join) for table A and B
-    always contains all records of the "left" table (A), even if the
-    join-condition does not find any matching record in the "right" table (B).
-
-You must use the `?` behind a variable to specify that the relation to
-that variable is optional. For instance:
-
-- Bugs of a project attached or not to a version
-
-   .. sourcecode:: sql
-
-       Any X, V WHERE X concerns P, P eid 42, X corrected_in V?
-
-  You will get a result set containing all the project's tickets, with either the
-  version in which it's fixed or None for tickets not related to a version.
-
-
-- All cards and the project they document if any
-
-  .. sourcecode:: sql
-
-       Any C, P WHERE C is Card, P? documented_by C
-
-Notice you may also use outer join:
-
-- on the RHS of attribute relation, e.g.
-
-  .. sourcecode:: sql
-
-       Any X WHERE X ref XR, Y name XR?
-
-  so that Y is outer joined on X by ref/name attributes comparison
-
-
-- on any side of an ``HAVING`` expression, e.g.
-
-  .. sourcecode:: sql
-
-       Any X WHERE X creation_date XC, Y creation_date YC
-       HAVING YEAR(XC)=YEAR(YC)?
-
-  so that Y is outer joined on X by comparison of the year extracted from their
-  creation date.
-
-  .. sourcecode:: sql
-
-       Any X WHERE X creation_date XC, Y creation_date YC
-       HAVING YEAR(XC)?=YEAR(YC)
-
-  would outer join X on Y instead.
-
-
-Having restrictions
-```````````````````
-
-The ``HAVING`` clause, as in SQL, may be used to restrict a query
-according to value returned by an aggregate function, e.g.
-
-.. sourcecode:: sql
-
-    Any X GROUPBY X WHERE X relation Y HAVING COUNT(Y) > 10
-
-It may however be used for something else: In the ``WHERE`` clause, we are
-limited to triplet expressions, so some things may not be expressed there. Let's
-take an example : if you want to get people whose upper-cased first name equals to
-another person upper-cased first name. There is no proper way to express this
-using triplet, so you should use something like:
-
-.. sourcecode:: sql
-
-    Any X WHERE X firstname XFN, Y firstname YFN, NOT X identity Y HAVING UPPER(XFN) = UPPER(YFN)
-
-Another example: imagine you want person born in 2000:
-
-.. sourcecode:: sql
-
-    Any X WHERE X birthday XB HAVING YEAR(XB) = 2000
-
-Notice that while we would like this to work without the HAVING clause, this
-can't be currently be done because it introduces an ambiguity in RQL's grammar
-that can't be handled by Yapps_, the parser's generator we're using.
-
-
-Sub-queries
-```````````
-
-The ``WITH`` keyword introduce sub-queries clause. Each sub-query has the
-form:
-
-  V1(,V2) BEING (rql query)
-
-Variables at the left of the ``BEING`` keyword defines into which
-variables results from the sub-query will be mapped to into the outer query.
-Sub-queries are separated from each other using a comma.
-
-Let's say we want to retrieve for each project its number of versions and its
-number of tickets. Due to the nature of relational algebra behind the scene, this
-can't be achieved using a single query. You have to write something along the
-line of:
-
-.. sourcecode:: sql
-
-  Any X, VC, TC WHERE X identity XX
-  WITH X, VC BEING (Any X, COUNT(V) GROUPBY X WHERE V version_of X),
-       XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)
-
-Notice that we can't reuse a same variable name as alias for two different
-sub-queries, hence the usage of 'X' and 'XX' in this example, which are then
-unified using the special `identity` relation (see :ref:`VirtualRelations`).
-
-.. warning::
-
-  Sub-queries define a new variable scope, so even if a variable has the same name
-  in the outer query and in the sub-query, they technically **aren't** the same
-  variable. So:
-
-  .. sourcecode:: sql
-
-     Any W, REF WITH W, REF BEING
-         (Any W, REF WHERE W is Workcase, W ref REF,
-                           W concerned_by D, D name "Logilab")
-
-  could be written:
-
-  .. sourcecode:: sql
-
-     Any W, REF WITH W, REF BEING
-        (Any W1, REF1 WHERE W1 is Workcase, W1 ref REF1,
-                            W1 concerned_by D, D name "Logilab")
-
-  Also, when a variable is coming from a sub-query, you currently can't reference
-  its attribute or inlined relations in the outer query, you've to fetch them in
-  the sub-query. For instance, let's say we want to sort by project name in our
-  first example, we would have to write:
-
-  .. sourcecode:: sql
-
-
-    Any X, VC, TC ORDERBY XN WHERE X identity XX
-    WITH X, XN, VC BEING (Any X, COUNT(V) GROUPBY X,XN WHERE V version_of X, X name XN),
-         XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)
-
-  instead of:
-
-  .. sourcecode:: sql
-
-    Any X, VC, TC ORDERBY XN WHERE X identity XX, X name XN,
-    WITH X, XN, VC BEING (Any X, COUNT(V) GROUPBY X WHERE V version_of X),
-         XX, TC BEING (Any X, COUNT(T) GROUPBY X WHERE T ticket_of X)
-
-  which would result in a SQL execution error.
-
-
-Union
-`````
-
-You may get a result set containing the concatenation of several queries using
-the ``UNION``. The selection of each query should have the same number of
-columns.
-
-.. sourcecode:: sql
-
-    (Any X, XN WHERE X is Person, X surname XN) UNION (Any X,XN WHERE X is Company, X name XN)
-
-
-.. _RQLFunctions:
-
-Available functions
-~~~~~~~~~~~~~~~~~~~
-
-Below is the list of aggregate and transformation functions that are supported
-nativly by the framework. Notice that cubes may define additional functions.
-
-.. _RQLAggregateFunctions:
-
-Aggregate functions
-```````````````````
-+------------------------+----------------------------------------------------------+
-| ``COUNT(Any)``         | return the number of rows                                |
-+------------------------+----------------------------------------------------------+
-| ``MIN(Any)``           | return the minimum value                                 |
-+------------------------+----------------------------------------------------------+
-| ``MAX(Any)``           | return the maximum value                                 |
-+------------------------+----------------------------------------------------------+
-| ``AVG(Any)``           | return the average value                                 |
-+------------------------+----------------------------------------------------------+
-| ``SUM(Any)``           | return the sum of values                                 |
-+------------------------+----------------------------------------------------------+
-| ``COMMA_JOIN(String)`` | return each value separated by a comma (for string only) |
-+------------------------+----------------------------------------------------------+
-
-All aggregate functions above take a single argument. Take care some aggregate
-functions (e.g. ``MAX``, ``MIN``) may return `None` if there is no
-result row.
-
-.. _RQLStringFunctions:
-
-String transformation functions
-```````````````````````````````
-
-+-----------------------------------------------+-----------------------------------------------------------------+
-| ``UPPER(String)``                             | upper case the string                                           |
-+-----------------------------------------------+-----------------------------------------------------------------+
-| ``LOWER(String)``                             | lower case the string                                           |
-+-----------------------------------------------+-----------------------------------------------------------------+
-| ``LENGTH(String)``                            | return the length of the string                                 |
-+-----------------------------------------------+-----------------------------------------------------------------+
-| ``SUBSTRING(String, start, length)``          | extract from the string a string starting at given index and of |
-|                                               | given length                                                    |
-+-----------------------------------------------+-----------------------------------------------------------------+
-| ``LIMIT_SIZE(String, max size)``              | if the length of the string is greater than given max size,     |
-|                                               | strip it and add ellipsis ("..."). The resulting string will    |
-|                                               | hence have max size + 3 characters                              |
-+-----------------------------------------------+-----------------------------------------------------------------+
-| ``TEXT_LIMIT_SIZE(String, format, max size)`` | similar to the above, but allow to specify the MIME type of the |
-|                                               | text contained by the string. Supported formats are text/html,  |
-|                                               | text/xhtml and text/xml. All others will be considered as plain |
-|                                               | text. For non plain text format, sgml tags will be first removed|
-|                                               | before limiting the string.                                     |
-+-----------------------------------------------+-----------------------------------------------------------------+
-
-.. _RQLDateFunctions:
-
-Date extraction functions
-`````````````````````````
-
-+----------------------+----------------------------------------+
-| ``YEAR(Date)``       | return the year of a date or datetime  |
-+----------------------+----------------------------------------+
-| ``MONTH(Date)``      | return the month of a date or datetime |
-+----------------------+----------------------------------------+
-| ``DAY(Date)``        | return the day of a date or datetime   |
-+----------------------+----------------------------------------+
-| ``HOUR(Datetime)``   | return the hours of a datetime         |
-+----------------------+----------------------------------------+
-| ``MINUTE(Datetime)`` | return the minutes of a datetime       |
-+----------------------+----------------------------------------+
-| ``SECOND(Datetime)`` | return the seconds of a datetime       |
-+----------------------+----------------------------------------+
-| ``WEEKDAY(Date)``    | return the day of week of a date or    |
-|                      | datetime.  Sunday == 1, Saturday == 7. |
-+----------------------+----------------------------------------+
-
-.. _RQLOtherFunctions:
-
-Other functions
-```````````````
-+-------------------+--------------------------------------------------------------------+
-| ``ABS(num)``      |  return the absolute value of a number                             |
-+-------------------+--------------------------------------------------------------------+
-| ``RANDOM()``      | return a pseudo-random value from 0.0 to 1.0                       |
-+-------------------+--------------------------------------------------------------------+
-| ``FSPATH(X)``     | expect X to be an attribute whose value is stored in a             |
-|                   | :class:`BFSStorage` and return its path on the file system         |
-+-------------------+--------------------------------------------------------------------+
-| ``FTIRANK(X)``    | expect X to be an entity used in a has_text relation, and return a |
-|                   | number corresponding to the rank order of each resulting entity    |
-+-------------------+--------------------------------------------------------------------+
-| ``CAST(Type, X)`` | expect X to be an attribute and return it casted into the given    |
-|                   | final type                                                         |
-+-------------------+--------------------------------------------------------------------+
-
-
-.. _RQLExamples:
-
-Examples
-~~~~~~~~
-
-- *Search for the object of identifier 53*
-
-  .. sourcecode:: sql
-
-        Any X WHERE X eid 53
-
-- *Search material such as comics, owned by syt and available*
-
-  .. sourcecode:: sql
-
-        Any X WHERE X is Document,
-                    X occurence_of F, F class C, C name 'Comics',
-                    X owned_by U, U login 'syt',
-                    X available TRUE
-
-- *Looking for people working for eurocopter interested in training*
-
-  .. sourcecode:: sql
-
-        Any P WHERE P is Person, P work_for S, S name 'Eurocopter',
-                    P interested_by T, T name 'training'
-
-- *Search note less than 10 days old written by jphc or ocy*
-
-  .. sourcecode:: sql
-
-        Any N WHERE N is Note, N written_on D, D day> (today -10),
-                    N written_by P, P name 'jphc' or P name 'ocy'
-
-- *Looking for people interested in training or living in Paris*
-
-  .. sourcecode:: sql
-
-        Any P WHERE P is Person, EXISTS(P interested_by T, T name 'training') OR
-                    (P city 'Paris')
-
-- *The surname and firstname of all people*
-
-  .. sourcecode:: sql
-
-        Any N, P WHERE X is Person, X name N, X firstname P
-
-  Note that the selection of several entities generally force
-  the use of "Any" because the type specification applies otherwise
-  to all the selected variables. We could write here
-
-  .. sourcecode:: sql
-
-        String N, P WHERE X is Person, X name N, X first_name P
-
-
-  Note: You can not specify several types with * ... where X is FirstType or X is SecondType*.
-  To specify several types explicitly, you have to do
-
-
-  .. sourcecode:: sql
-
-        Any X WHERE X is IN (FirstType, SecondType)
-
-
-.. _RQLInsertQuery:
-
-Insertion query
-~~~~~~~~~~~~~~~
-
-    `INSERT` <entity type> V1 (, <entity type> V2) \ * `:` <assignments>
-    [ `WHERE` <restriction>]
-
-:assignments:
-   list of relations to assign in the form `V1 relationship V2 | <static value>`
-
-The restriction can define variables used in assignments.
-
-Caution, if a restriction is specified, the insertion is done for
-*each line result returned by the restriction*.
-
-- *Insert a new person named 'foo'*
-
-  .. sourcecode:: sql
-
-        INSERT Person X: X name 'foo'
-
-- *Insert a new person named 'foo', another called 'nice' and a 'friend' relation
-  between them*
-
-  .. sourcecode:: sql
-
-        INSERT Person X, Person Y: X name 'foo', Y name 'nice', X friend Y
-
-- *Insert a new person named 'foo' and a 'friend' relation with an existing
-  person called 'nice'*
-
-  .. sourcecode:: sql
-
-        INSERT Person X: X name 'foo', X friend  Y WHERE Y name 'nice'
-
-.. _RQLSetQuery:
-
-Update and relation creation queries
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    `SET` <assignements>
-    [ `WHERE` <restriction>]
-
-Caution, if a restriction is specified, the update is done *for
-each result line returned by the restriction*.
-
-- *Renaming of the person named 'foo' to 'bar' with the first name changed*
-
-  .. sourcecode:: sql
-
-        SET X name 'bar', X firstname 'original' WHERE X is Person, X name 'foo'
-
-- *Insert a relation of type 'know' between objects linked by
-  the relation of type 'friend'*
-
-  .. sourcecode:: sql
-
-        SET X know Y  WHERE X friend Y
-
-
-.. _RQLDeleteQuery:
-
-Deletion query
-~~~~~~~~~~~~~~
-
-    `DELETE` (<entity type> V) | (V1 relation v2 ),...
-    [ `WHERE` <restriction>]
-
-Caution, if a restriction is specified, the deletion is made *for
-each line result returned by the restriction*.
-
-- *Deletion of the person named 'foo'*
-
-  .. sourcecode:: sql
-
-        DELETE Person X WHERE X name 'foo'
-
-- *Removal of all relations of type 'friend' from the person named 'foo'*
-
-  .. sourcecode:: sql
-
-        DELETE X friend Y WHERE X is Person, X name 'foo'
-
-
-.. _Yapps: http://theory.stanford.edu/~amitp/yapps/
-.. _Left outer join: http://en.wikipedia.org/wiki/Join_(SQL)#Left_outer_join
-
--- a/doc/book/en/conf.py	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-"""
-#
-# Cubicweb documentation build configuration file, created by
-# sphinx-quickstart on Fri Oct 31 09:10:36 2008.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# The contents of this file are pickled, so don't put values in the namespace
-# that aren't pickleable (module imports are okay, they're removed automatically).
-#
-# All configuration values have a default value; values that are commented out
-# serve to show the default value.
-
-from os import path as osp
-
-path = __file__
-path = osp.dirname(path) #./doc/book/en
-path = osp.dirname(path) #./doc/book/
-path = osp.dirname(path) #./doc/
-path = osp.dirname(path) #./
-path = osp.join(path,'__pkginfo__.py') #./__pkginfo__.py
-cw = {}
-execfile(path,{},cw)
-
-# If your extensions are in another directory, add it here. If the directory
-# is relative to the documentation root, use os.path.abspath to make it
-# absolute, like shown here.
-#sys.path.append(os.path.abspath('some/directory'))
-
-# General configuration
-# ---------------------
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = [
-  'sphinx.ext.autodoc', 
-  'sphinx.ext.viewcode',
-  'logilab.common.sphinx_ext',
-  ]
-
-autoclass_content = 'both'
-
-# Add any paths that contain templates here, relative to this directory.
-#templates_path = []
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General substitutions.
-project = 'CubicWeb'
-copyright = '2001-2014, Logilab'
-
-# The default replacements for |version| and |release|, also used in various
-# other places throughout the built documents.
-#
-# The short X.Y version.
-version = '.'.join(str(n) for n in cw['numversion'][:2])
-# The full version, including alpha/beta/rc tags.
-release = cw['version']
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-today_fmt = '%B %d, %Y'
-
-# List of documents that shouldn't be included in the build.
-unused_docs = []
-
-# List of directories, relative to source directories, that shouldn't be searched
-# for source files.
-#exclude_dirs = []
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-
-# Options for HTML output
-# -----------------------
-
-# The style sheet to use for HTML and HTML Help pages. A file of that name
-# must exist either in Sphinx' static/ path, or in one of the custom paths
-# given in html_static_path.
-#html_style = 'sphinx-default.css'
-
-# The name for this set of Sphinx documents.  If None, it defaults to
-# "<project> v<release> documentation".
-html_title = '%s %s' % (project, release)
-
-html_theme_path = ['_themes']
-html_theme = 'cubicweb'
-
-# A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (within the static path) to place at the top of
-# the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['.static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-html_use_modindex = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it.  The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
-html_file_suffix = '.html'
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'Cubicwebdoc'
-
-
-# Options for LaTeX output
-# ------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, document class [howto/manual]).
-latex_documents = [
-  ('index', 'Cubicweb.tex', 'Cubicweb Documentation',
-   'Logilab', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_use_modindex = True
-
-#aafig_format = dict(latex='pdf', html='svg', text=None)
-
-rst_epilog = """
-.. |cubicweb| replace:: *CubicWeb*
-.. |yams| replace:: *Yams*
-.. |rql| replace:: *RQL*
-"""
--- a/doc/book/en/devrepo/cubes/available-cubes.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-.. _AvailableCubes:
-
-Available cubes
----------------
-
-An instance is made of several basic cubes. In the set of available
-basic cubes we can find for example:
-
-Base entity types
-~~~~~~~~~~~~~~~~~
-* addressbook_: PhoneNumber and PostalAddress
-* card_: Card, generic documenting card
-* event_: Event (define events, display them in calendars)
-* file_: File (to allow users to upload and store binary or text files)
-* link_: Link (to collect links to web resources)
-* mailinglist_: MailingList (to reference a mailing-list and the URLs
-  for its archives and its admin interface)
-* person_: Person (easily mixed with addressbook)
-* task_: Task (something to be done between start and stop date)
-* zone_: Zone (to define places within larger places, for example a
-  city in a state in a country)
-
-
-Classification
-~~~~~~~~~~~~~~
-* folder_: Folder (to organize things by grouping them in folders)
-* keyword_: Keyword (to define classification schemes)
-* tag_: Tag (to tag anything)
-
-Other features
-~~~~~~~~~~~~~~
-* basket_: Basket (like a shopping cart)
-* blog_: a blogging system using Blog and BlogEntry entity types
-* comment_: system to attach comment threads to entities)
-* email_: archiving management for emails (`Email`, `Emailpart`,
-  `Emailthread`), trigger action in cubicweb through email
-
-
-
-
-
-.. _addressbook: http://www.cubicweb.org/project/cubicweb-addressbook
-.. _basket: http://www.cubicweb.org/project/cubicweb-basket
-.. _card: http://www.cubicweb.org/project/cubicweb-card
-.. _blog: http://www.cubicweb.org/project/cubicweb-blog
-.. _comment: http://www.cubicweb.org/project/cubicweb-comment
-.. _email: http://www.cubicweb.org/project/cubicweb-email
-.. _event: http://www.cubicweb.org/project/cubicweb-event
-.. _file: http://www.cubicweb.org/project/cubicweb-file
-.. _folder: http://www.cubicweb.org/project/cubicweb-folder
-.. _keyword: http://www.cubicweb.org/project/cubicweb-keyword
-.. _link: http://www.cubicweb.org/project/cubicweb-link
-.. _mailinglist: http://www.cubicweb.org/project/cubicweb-mailinglist
-.. _person: http://www.cubicweb.org/project/cubicweb-person
-.. _tag: http://www.cubicweb.org/project/cubicweb-tag
-.. _task: http://www.cubicweb.org/project/cubicweb-task
-.. _zone: http://www.cubicweb.org/project/cubicweb-zone
-
-To declare the use of a cube, once installed, add the name of the cube
-and its dependency relation in the `__depends_cubes__` dictionary
-defined in the file `__pkginfo__.py` of your own component.
-
-.. note::
-  The listed cubes above are available as debian-packages on `CubicWeb's forge`_.
-
-.. _`CubicWeb's forge`: http://www.cubicweb.org/project?vtitle=All%20cubicweb%20projects
--- a/doc/book/en/devrepo/cubes/cc-newcube.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-Creating a new cube from scratch
---------------------------------
-
-Let's start by creating the cube environment in which we will develop ::
-
-  cd ~/cubes
-  # use cubicweb-ctl to generate a template for the cube
-  # will ask some questions, most with nice default
-  cubicweb-ctl newcube mycube
-  # makes the cube source code managed by mercurial
-  cd mycube
-  hg init
-  hg add .
-  hg ci
-
-If all went well, you should see the cube you just created in the list
-returned by ``cubicweb-ctl list`` in the  *Available cubes* section.
-If not, please refer to :ref:`ConfigurationEnv`.
-
-To reuse an existing cube, add it to the list named
-``__depends_cubes__`` which is defined in :file:`__pkginfo__.py`.
-This variable is used for the instance packaging (dependencies handled
-by system utility tools such as APT) and to find used cubes when the
-database for the instance is created (import_erschema('MyCube') will
-not properly work otherwise).
-
-On a Unix system, the available cubes are usually stored in the
-directory :file:`/usr/share/cubicweb/cubes`. If you are using the
-cubicweb mercurial repository (:ref:`SourceInstallation`), the cubes
-are searched in the directory
-:file:`/path/to/cubicweb_toplevel/cubes`. In this configuration
-cubicweb itself ought to be located at
-:file:`/path/to/cubicweb_toplevel/cubicweb`.
-
-.. note::
-
-    Please note that if you do not wish to use default directory for your cubes
-    library, you should set the :envvar:`CW_CUBES_PATH` environment variable to
-    add extra directories where cubes will be search, and you'll then have to use
-    the option `--directory` to specify where you would like to place the source
-    code of your cube:
-
-    ``cubicweb-ctl newcube --directory=/path/to/cubes/library mycube``
-
-
-.. XXX resurrect once live-server is back
-.. Usage of :command:`cubicweb-ctl liveserver`
-.. -------------------------------------------
-
-.. To quickly test a new cube, you can also use the `liveserver` command for cubicweb-ctl
-.. which allows to create an instance in memory (using an SQLite database by
-.. default) and make it accessible through a web server ::
-
-..   cubicweb-ctl live-server mycube
-
-.. or by using an existing database (SQLite or Postgres)::
-
-..   cubicweb-ctl live-server -s myfile_sources mycube
--- a/doc/book/en/devrepo/cubes/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-Cubes
-=====
-
-This chapter describes how to define your own cubes and reuse already available cubes.
-
-.. toctree::
-   :maxdepth: 1
-
-   layout.rst
-   cc-newcube.rst
-   available-cubes.rst
--- a/doc/book/en/devrepo/cubes/layout.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-
-.. _foundationsCube:
-
-.. _cubelayout:
-
-Standard structure for a cube
------------------------------
-
-A cube is structured as follows:
-
-::
-
-  mycube/
-  |
-  |-- data/
-  |   |-- cubes.mycube.css
-  |   |-- cubes.mycube.js
-  |   `-- external_resources
-  |
-  |-- debian/
-  |   |-- changelog
-  |   |-- compat
-  |   |-- control
-  |   |-- copyright
-  |   |-- cubicweb-mycube.prerm
-  |   `-- rules
-  |
-  |-- entities.py
-  |
-  |-- i18n/
-  |   |-- en.po
-  |   |-- es.po
-  |   `-- fr.po
-  |
-  |-- __init__.py
-  |
-  |-- MANIFEST.in
-  |
-  |-- migration/
-  |   |-- postcreate.py
-  |   `-- precreate.py
-  |
-  |-- __pkginfo__.py
-  |
-  |-- schema.py
-  |
-  |-- setup.py
-  |
-  |-- site_cubicweb.py
-  |
-  |-- hooks.py
-  |
-  |-- test/
-  |   |-- data/
-  |   |   `-- bootstrap_cubes
-  |   |-- pytestconf.py
-  |   |-- realdb_test_mycube.py
-  |   `-- test_mycube.py
-  |
-  `-- views.py
-
-
-We can use subpackages instead of python modules for ``views.py``, ``entities.py``,
-``schema.py`` or ``hooks.py``. For example, we could have:
-
-::
-
-  mycube/
-  |
-  |-- entities.py
-  |-- hooks.py
-  `-- views/
-      |-- __init__.py
-      |-- forms.py
-      |-- primary.py
-      `-- widgets.py
-
-
-where :
-
-* ``schema`` contains the schema definition (server side only)
-* ``entities`` contains the entity definitions (server side and web interface)
-* ``hooks`` contains hooks and/or views notifications (server side only)
-* ``views`` contains the web interface components (web interface only)
-* ``test`` contains tests related to the cube (not installed)
-* ``i18n`` contains message catalogs for supported languages (server side and
-  web interface)
-* ``data`` contains data files for static content (images, css,
-  javascript code)...(web interface only)
-* ``migration`` contains initialization files for new instances (``postcreate.py``)
-  and a file containing dependencies of the component depending on the version
-  (``depends.map``)
-* ``debian`` contains all the files managing debian packaging (you will find
-  the usual files ``control``, ``rules``, ``changelog``... not installed)
-* file ``__pkginfo__.py`` provides component meta-data, especially the distribution
-  and the current version (server side and web interface) or sub-cubes used by
-  the cube.
-
-
-At least you should have the file ``__pkginfo__.py``.
-
-
-The :file:`__init__.py` and :file:`site_cubicweb.py` files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. XXX WRITEME
-
-The :file:`__pkginfo__.py` file
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-It contains metadata describing your cube, mostly useful for packaging.
-
-Two important attributes of this module are __depends__ and __recommends__
-dictionaries that indicates what should be installed (and each version if
-necessary) for the cube to work.
-
-Dependency on other cubes are expected to be of the form 'cubicweb-<cubename>'.
-
-When an instance is created, dependencies are automatically installed, while
-recommends are not.
-
-Recommends may be seen as a kind of 'weak dependency'. Eg, the most important
-effect of recommending a cube is that, if cube A recommends cube B, the cube B
-will be loaded before the cube A (same thing happend when A depends on B).
-
-Having this behaviour is sometime desired: on schema creation, you may rely on
-something defined in the other's schema; on database creation, on something
-created by the other's postcreate, and so on.
-
-
-:file:`migration/precreate.py` and :file:`migration/postcreate.py`
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. XXX detail steps of instance creation
-
-
-External resources such as image, javascript and css files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. XXX naming convention external_resources file
-
-
-Out-of the box testing
-~~~~~~~~~~~~~~~~~~~~~~
-
-.. XXX MANIFEST.in, __pkginfo__.include_dirs, debian
-
-
-Packaging and distribution
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. XXX MANIFEST.in, __pkginfo__.include_dirs, debian
-
--- a/doc/book/en/devrepo/dataimport.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _dataimport:
-
-Dataimport
-==========
-
-*CubicWeb* is designed to manipulate huge of amount of data, and provides utilities to do so.
-
-The main entry point is :mod:`cubicweb.dataimport.importer` which defines an
-:class:`ExtEntitiesImporter` class responsible for importing data from an external source in the
-form :class:`ExtEntity` objects. An :class:`ExtEntity` is a transitional representation of an
-entity to be imported in the CubicWeb instance; building this representation is usually
-domain-specific -- e.g. dependent of the kind of data source (RDF, CSV, etc.) -- and is thus the
-responsibility of the end-user.
-
-Along with the importer, a *store* must be selected, which is responsible for insertion of data into
-the database. There exists different kind of stores_, allowing to insert data within different
-levels of the *CubicWeb* API and with different speed/security tradeoffs. Those keeping all the
-*CubicWeb* hooks and security will be slower but the possible errors in insertion (bad data types,
-integrity error, ...) will be handled.
-
-
-Example
--------
-
-Consider the following schema snippet.
-
-.. code-block:: python
-
-    class Person(EntityType):
-        name = String(required=True)
-
-    class knows(RelationDefinition):
-        subject = 'Person'
-        object = 'Person'
-
-along with some data in a ``people.csv`` file::
-
-    # uri,name,knows
-    http://www.example.org/alice,Alice,
-    http://www.example.org/bob,Bob,http://www.example.org/alice
-
-The following code (using a shell context) defines a function `extentities_from_csv` to read
-`Person` external entities coming from a CSV file and calls the :class:`ExtEntitiesImporter` to
-insert corresponding entities and relations into the CubicWeb instance.
-
-.. code-block:: python
-
-    from cubicweb.dataimport import ucsvreader, RQLObjectStore
-    from cubicweb.dataimport.importer import ExtEntity, ExtEntitiesImporter
-
-    def extentities_from_csv(fpath):
-        """Yield Person ExtEntities read from `fpath` CSV file."""
-        with open(fpath) as f:
-            for uri, name, knows in ucsvreader(f, skipfirst=True, skip_empty=False):
-                yield ExtEntity('Personne', uri,
-                                {'nom': set([name]), 'connait': set([knows])})
-
-    extenties = extentities_from_csv('people.csv')
-    store = RQLObjectStore(cnx)
-    importer = ExtEntitiesImporter(schema, store)
-    importer.import_entities(extenties)
-    commit()
-    rset = cnx.execute('String N WHERE X nom N, X connait Y, Y nom "Alice"')
-    assert rset[0][0] == u'Bob', rset
-
-Importer API
-------------
-
-.. automodule:: cubicweb.dataimport.importer
-
-
-Stores
-~~~~~~
-
-Stores are responsible to insert properly formatted entities and relations into the database. They
-have the following API::
-
-    >>> user_eid = store.prepare_insert_entity('CWUser', login=u'johndoe')
-    >>> group_eid = store.prepare_insert_entity('CWUser', name=u'unknown')
-    >>> store.relate(user_eid, 'in_group', group_eid)
-    >>> store.flush()
-    >>> store.commit()
-    >>> store.finish()
-
-Some stores **require a flush** to copy data in the database, so if you want to have store
-independent code you should explicitly call it. (There may be multiple flushes during the
-process, or only one at the end if there is no memory issue). This is different from the
-commit which validates the database transaction. At last, the `finish()` method should be called in
-case the store requires additional work once everything is done.
-
-* ``prepare_insert_entity(<entity type>, **kwargs) -> eid``: given an entity
-  type, attributes and inlined relations, return the eid of the entity to be
-  inserted, *with no guarantee that anything has been inserted in database*.
-
-* ``prepare_update_entity(<entity type>, eid, **kwargs) -> None``: given an
-  entity type and eid, promise for update given attributes and inlined
-  relations *with no guarantee that anything has been inserted in database*.
-
-* ``prepare_insert_relation(eid_from, rtype, eid_to) -> None``: indicate that a
-  relation ``rtype`` should be added between entities with eids ``eid_from``
-  and ``eid_to``. Similar to ``prepare_insert_entity()``, *there is no
-  guarantee that the relation has been inserted in database*.
-
-* ``flush() -> None``: flush any temporary data to database. May be called
-  several times during an import.
-
-* ``commit() -> None``: commit the database transaction.
-
-* ``finish() -> None``: additional stuff to do after import is terminated.
-
-ObjectStore
------------
-
-This store keeps objects in memory for *faster* validation. It may be useful in development
-mode. However, as it will not enforce the constraints of the schema nor insert anything in the
-database, so it may miss some problems.
-
-
-RQLObjectStore
---------------
-
-This store works with an actual RQL repository, and it may be used in production mode.
-
-
-NoHookRQLObjectStore
---------------------
-
-This store works similarly to the *RQLObjectStore* but bypasses some *CubicWeb* hooks to be faster.
-
-
-SQLGenObjectStore
------------------
-
-This store relies on *COPY FROM*/execute many sql commands to directly push data using SQL commands
-rather than using the whole *CubicWeb* API. For now, **it only works with PostgresSQL** as it requires
-the *COPY FROM* command.
--- a/doc/book/en/devrepo/datamodel/baseschema.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-.. _pre_defined_entity_types:
-
-Pre-defined entities in the library
------------------------------------
-
-The library defines a set of entity schemas that are required by the system
-or commonly used in *CubicWeb* instances.
-
-
-Entity types used to store the schema
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* _`CWEType`, entity type
-* _`CWRType`, relation type
-* _`CWRelation`, relation definition
-* _`CWAttribute`, attribute relation definition
-* _`CWConstraint`,  `CWConstraintType`, `RQLExpression`
-
-Entity types used to manage users and permissions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* _`CWUser`, system users
-* _`CWGroup`, users groups
-
-Entity types used to manage workflows
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* :ref:`Workflow <Workflow>`, workflow entity, linked to some entity types which may use this workflow
-* _`State`, workflow state
-* _`Transition`, workflow transition
-* _`TrInfo`, record of a transition trafic for an entity
-
-Other entity types
-~~~~~~~~~~~~~~~~~~
-* _`CWCache`, cache entities used to improve performances
-* _`CWProperty`, used to configure the instance
-
-* _`EmailAddress`, email address, used by the system to send notifications
-  to the users and also used by others optionnals schemas
-
-* _`Bookmark`, an entity type used to allow a user to customize his links within
-  the instance
-
-* _`ExternalUri`, used for semantic web site to indicate that an entity is the
-  same as another from an external site
--- a/doc/book/en/devrepo/datamodel/define-workflows.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _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.
-
-We will define a simple workflow for a blog, with only the following two states:
-`submitted` and `published`. You may want to take a look at :ref:`TutosBase` if
-you want to quickly setup an instance running a blog.
-
-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
-its state should be `submitted`. To be visible to all, it has to
-be in the state `published`. To move it from `submitted` to `published`,
-we need a transition that we can call `approve_blogentry`.
-
-A BlogEntry state should not be modifiable by every user.
-So we have to define a group of users, `moderators`, and
-this group will have appropriate permissions to publish a BlogEntry.
-
-There are two ways to create a workflow: from the user interface, or
-by defining it in ``migration/postcreate.py``. This script is executed
-each time a new ``cubicweb-ctl db-init`` is done.  We strongly
-recommend to create the workflow in ``migration/postcreate.py`` and we
-will now show you how. Read `Two bits of warning`_ to understand why.
-
-The state of an entity is managed by the `in_state` attribute which
-can be added to your entity schema by inheriting from
-`cubicweb.schema.WorkflowableEntityType`.
-
-
-About our example of BlogEntry, we must have:
-
-.. sourcecode:: python
-
-  from cubicweb.schema import WorkflowableEntityType
-
-  class BlogEntry(WorkflowableEntityType):
-      ...
-
-
-Creating states, transitions and group permissions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-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` 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
-``Transition`` which are standard *CubicWeb* entity types.
-
-To define a workflow for BlogDemo, please add the following lines
-to ``migration/postcreate.py``:
-
-.. sourcecode:: python
-
-  _ = unicode
-
-  moderators = add_entity('CWGroup', name=u"moderators")
-
-This adds the `moderators` user group.
-
-.. sourcecode:: python
-
-  wf = add_workflow(u'blog publication workflow', 'BlogEntry')
-
-At first, instanciate a new workflow object with a gentle description
-and the concerned entity types (this one can be a tuple for multiple
-value).
-
-.. sourcecode:: python
-
-  submitted = wf.add_state(_('submitted'), initial=True)
-  published = wf.add_state(_('published'))
-
-This will create two entities of type ``State``, one with name
-'submitted', and the other with name 'published'.
-
-``add_state`` expects as first argument the name of the state you want
-to create and an optional argument to say if it is supposed to be the
-initial state of the entity type.
-
-.. sourcecode:: python
-
-  wf.add_transition(_('approve_blogentry'), (submitted,), published, ('moderators', 'managers'),)
-
-This will create an entity of type ``Transition`` with name
-`approve_blogentry` which will be linked to the ``State`` entities
-created before.
-
-``add_transition`` expects
-
-  * as the first argument: the name of the transition
-  * then the list of states on which the transition can be triggered,
-  * the target state of the transition,
-  * and the permissions
-    (e.g. a list of user groups who can apply the transition; the user
-    has to belong to at least one of the listed group to perform the action).
-
-.. sourcecode:: python
-
-  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.
-
-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
-only perform the action if the two conditions are satisfied.
-
-If we use an RQL condition on a transition, we can use the following variables:
-
-* `X`, the entity on which we may pass the transition
-* `U`, the user executing that may pass the transition
-
-
-.. image:: ../../images/03-transitions-view_en.png
-
-You can notice that in the action box of a BlogEntry, the state is now
-listed as well as the possible transitions for the current state
-defined by the workflow.
-
-The transitions will only be displayed for users having the right permissions.
-In our example, the transition `approve_blogentry` will only be displayed
-for the users belonging to the group `moderators` or `managers`.
-
-
-Two bits of warning
-~~~~~~~~~~~~~~~~~~~
-
-We could perfectly use the administration interface to do these
-operations. It is a convenient thing to do at times (when doing
-development, to quick-check things). But it is not recommended beyond
-that because it is a bit complicated to do it right and it will be
-only local to your instance (or, said a bit differently, such a
-workflow only exists in an instance database). Furthermore, you cannot
-write unit tests against deployed instances, and experience shows it
-is mandatory to have tests for any mildly complicated workflow
-setup.
-
-Indeed, if you create the states and transitions through the user
-interface, next time you initialize the database you will have to
-re-create all the workflow entities. The user interface should only be
-a reference for you to view the states and transitions, but is not the
-appropriate interface to define your application workflow.
--- a/doc/book/en/devrepo/datamodel/definition.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,912 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _datamodel_definition:
-
-Yams *schema*
--------------
-
-The **schema** is the core piece of a *CubicWeb* instance as it
-defines and handles the data model. It is based on entity types that
-are either already defined in `Yams`_ and the *CubicWeb* standard
-library; or more specific types defined in cubes. The schema for a
-cube is defined in a `schema` python module or package.
-
-.. _`Yams`: http://www.logilab.org/project/yams
-
-.. _datamodel_overview:
-
-Overview
-~~~~~~~~
-
-The core idea of the yams schema is not far from the classical
-`Entity-relationship`_ model. But while an E/R model (or `logical
-model`) traditionally has to be manually translated to a lower-level
-data description language (such as the SQL `create table`
-sublanguage), also often described as the `physical model`, no such
-step is required with |yams| and |cubicweb|.
-
-.. _`Entity-relationship`: http://en.wikipedia.org/wiki/Entity-relationship_model
-
-This is because in addition to high-level, logical |yams| models, one
-uses the |rql| data manipulation language to query, insert, update and
-delete data. |rql| abstracts as much of the underlying SQL database as
-a |yams| schema abstracts from the physical layout. The vagaries of
-SQL are avoided.
-
-As a bonus point, such abstraction make it quite comfortable to build
-or use different backends to which |rql| queries apply.
-
-So, as in the E/R formalism, the building blocks are ``entities``
-(:ref:`EntityType`), ``relationships`` (:ref:`RelationType`,
-:ref:`RelationDefinition`) and ``attributes`` (handled like relation
-with |yams|).
-
-Let us detail a little the divergences between E/R and |yams|:
-
-* all relationship are binary which means that to represent a
-  non-binary relationship, one has to use an entity,
-* relationships do not support attributes (yet, see:
-  http://www.cubicweb.org/ticket/341318), hence the need to reify it
-  as an entity if need arises,
-* all entities have an `eid` attribute (an integer) that is its
-  primary key (but it is possible to declare uniqueness on other
-  attributes)
-
-Also |yams| supports the notions of:
-
-* 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)
-
-Finally |yams| has a few concepts of its own:
-
-* relationships being oriented and binary, we call the left hand
-  entity type the `subject` and the right hand entity type the
-  `object`
-
-.. note::
-
-   The |yams| schema is available at run time through the .schema
-   attribute of the `vregistry`.  It's an instance of
-   :class:`cubicweb.schema.Schema`, which extends
-   :class:`yams.schema.Schema`.
-
-.. _EntityType:
-
-Entity type
-~~~~~~~~~~~
-
-An entity type is an instance of :class:`yams.schema.EntitySchema`. Each entity type has
-a set of attributes and relations, and some permissions which define who can add, read,
-update or delete entities of this type.
-
-The following built-in types are available: ``String``,
-``Int``, ``BigInt``, ``Float``, ``Decimal``, ``Boolean``,
-``Date``, ``Datetime``, ``Time``, ``Interval``, ``Byte`` and
-``Password``. They can only be used as attributes of an other entity
-type.
-
-There is also a `RichString` kindof type:
-
- .. autoclass:: yams.buildobjs.RichString
-
-The ``__unique_together__`` class attribute is a list of tuples of names of
-attributes or inlined relations.  For each tuple, CubicWeb ensures the unicity
-of the combination.  For example:
-
-.. sourcecode:: python
-
-  class State(EntityType):
-      __unique_together__ = [('name', 'state_of')]
-
-      name = String(required=True)
-      state_of = SubjectRelation('Workflow', cardinality='1*',
-                                 composite='object', inlined=True)
-
-
-You can find more base entity types in
-:ref:`pre_defined_entity_types`.
-
-.. XXX yams inheritance
-
-.. _RelationType:
-
-Relation type
-~~~~~~~~~~~~~
-
-A relation type is an instance of
-:class:`yams.schema.RelationSchema`. A relation type is simply a
-semantic definition of a kind of relationship that may occur in an
-application.
-
-It may be referenced by zero, one or more relation definitions.
-
-It is important to choose a good name, at least to avoid conflicts
-with some semantically different relation defined in other cubes
-(since there's only a shared name space for these names).
-
-A relation type holds the following properties (which are hence shared
-between all relation definitions of that type):
-
-* `inlined`: boolean handling the physical optimization for archiving
-  the relation in the subject entity table, instead of creating a specific
-  table for the relation. This applies to relations where cardinality
-  of subject->relation->object is 0..1 (`?`) or 1..1 (`1`) for *all* its relation
-  definitions.
-
-* `symmetric`: boolean indicating that the relation is symmetrical, which
-  means that `X relation Y` implies `Y relation X`.
-
-.. _RelationDefinition:
-
-Relation definition
-~~~~~~~~~~~~~~~~~~~
-
-A relation definition is an instance of
-:class:`yams.schema.RelationDefinition`. It is a complete triplet
-"<subject entity type> <relation type> <object entity type>".
-
-When creating a new instance of that class, the corresponding
-:class:`RelationType` instance is created on the fly if necessary.
-
-Properties
-``````````
-
-The available properties for relation definitions are enumerated
-here. There are several kind of properties, as some relation
-definitions are actually attribute definitions, and other are not.
-
-Some properties may be completely optional, other may have a default
-value.
-
-Common properties for attributes and relations:
-
-* `description`: a unicode string describing an attribute or a
-  relation. By default this string will be used in the editing form of
-  the entity, which means that it is supposed to help the end-user and
-  should be flagged by the function `_` to be properly
-  internationalized.
-
-* `constraints`: a list of conditions/constraints that the relation has to
-  satisfy (c.f. `Constraints`_)
-
-* `cardinality`: a two character string specifying the cardinality of
-  the relation. The first character defines the cardinality of the
-  relation on the subject, and the second on the object. When a
-  relation can have multiple subjects or objects, the cardinality
-  applies to all, not on a one-to-one basis (so it must be
-  consistent...). Default value is '**'. The possible values are
-  inspired from regular expression syntax:
-
-    * `1`: 1..1
-    * `?`: 0..1
-    * `+`: 1..n
-    * `*`: 0..n
-
-Attributes properties:
-
-* `unique`: boolean indicating if the value of the attribute has to be
-  unique or not within all entities of the same type (false by
-  default)
-
-* `indexed`: boolean indicating if an index needs to be created for
-  this attribute in the database (false by default). This is useful
-  only if you know that you will have to run numerous searches on the
-  value of this attribute.
-
-* `default`: default value of the attribute. In case of date types, the values
-  which could be used correspond to the RQL keywords `TODAY` and `NOW`.
-
-* `metadata`: Is also accepted as an argument of the attribute contructor. It is
-  not really an attribute property. see `Metadata`_ for details.
-
-Properties for `String` attributes:
-
-* `fulltextindexed`: boolean indicating if the attribute is part of
-  the full text index (false by default) (*applicable on the type
-  `Byte` as well*)
-
-* `internationalizable`: boolean indicating if the value of the
-  attribute is internationalizable (false by default)
-
-Relation properties:
-
-* `composite`: string indicating that the subject (composite ==
-  'subject') is composed of the objects of the relations. For the
-  opposite case (when the object is composed of the subjects of the
-  relation), we just set 'object' as value. The composition implies
-  that when the relation is deleted (so when the composite is deleted,
-  at least), the composed are also deleted.
-
-* `fulltext_container`: string indicating if the value if the full
-  text indexation of the entity on one end of the relation should be
-  used to find the entity on the other end. The possible values are
-  'subject' or 'object'. For instance the use_email relation has that
-  property set to 'subject', since when performing a full text search
-  people want to find the entity using an email address, and not the
-  entity representing the email address.
-
-Constraints
-```````````
-
-By default, the available constraint types are:
-
-General Constraints
-......................
-
-* `SizeConstraint`: allows to specify a minimum and/or maximum size on
-  string (generic case of `maxsize`)
-
-* `BoundaryConstraint`: allows to specify a minimum and/or maximum value
-  on numeric types and date
-
-.. sourcecode:: python
-
-   from yams.constraints import BoundaryConstraint, TODAY, NOW, Attribute
-
-   class DatedEntity(EntityType):
-      start = Date(constraints=[BoundaryConstraint('>=', TODAY())])
-      end = Date(constraints=[BoundaryConstraint('>=', Attribute('start'))])
-
-   class Before(EntityType);
-      last_time = DateTime(constraints=[BoundaryConstraint('<=', NOW())])
-
-* `IntervalBoundConstraint`: allows to specify an interval with
-  included values
-
-.. sourcecode:: python
-
-     class Node(EntityType):
-         latitude = Float(constraints=[IntervalBoundConstraint(-90, +90)])
-
-* `UniqueConstraint`: identical to "unique=True"
-
-* `StaticVocabularyConstraint`: identical to "vocabulary=(...)"
-
-Constraints can be dependent on a fixed value (90, Date(2015,3,23)) or a variable.
-In this second case, yams can handle :
-
-* `Attribute`: compare to the value of another attribute.
-* `TODAY`: compare to the current Date.
-* `NOW`: compare to the current Datetime.
-
-RQL Based Constraints
-......................
-
-RQL based constraints may take three arguments. The first one is the ``WHERE``
-clause of a RQL query used by the constraint. The second argument ``mainvars``
-is the ``Any`` clause of the query. By default this include `S` reserved for the
-subject of the relation and `O` for the object. Additional variables could be
-specified using ``mainvars``. The argument expects a single string with all
-variable's name separated by spaces. The last one, ``msg``, is the error message
-displayed when the constraint fails. As RQLVocabularyConstraint never fails the
-third argument is not available.
-
-* `RQLConstraint`: allows to specify a RQL query that has to be satisfied
-  by the subject and/or the object of relation. In this query the variables
-  `S` and `O` are reserved for the relation subject and object entities.
-
-* `RQLVocabularyConstraint`: similar to the previous type of constraint except
-  that it does not express a "strong" constraint, which means it is only used to
-  restrict the values listed in the drop-down menu of editing form, but it does
-  not prevent another entity to be selected.
-
-* `RQLUniqueConstraint`: allows to the specify a RQL query that ensure that an
-  attribute is unique in a specific context. The Query must **never** return more
-  than a single result to be satisfied. In this query the variables `S` is
-  reserved for the relation subject entity. The other variables should be
-  specified with the second constructor argument (mainvars). This constraint type
-  should be used when __unique_together__ doesn't fit.
-
-.. XXX note about how to add new constraint
-
-.. _securitymodel:
-
-The security model
-~~~~~~~~~~~~~~~~~~
-
-The security model of `CubicWeb` is based on `Access Control List`.
-The main principles are:
-
-* users and groups of users
-* a user belongs to at least one group of user
-* permissions (`read`, `update`, `create`, `delete`)
-* permissions are assigned to groups (and not to users)
-
-For *CubicWeb* in particular:
-
-* we associate rights at the entities/relations schema level
-
-* the default groups are: `managers`, `users` and `guests`
-
-* users belong to the `users` group
-
-* there is a virtual group called `owners` to which we can associate only
-  `delete` and `update` permissions
-
-  * we can not add users to the `owners` group, they are implicitly added to it
-    according to the context of the objects they own
-
-  * the permissions of this group are only checked on `update`/`delete` actions
-    if all the other groups the user belongs to do not provide those permissions
-
-Setting permissions is done with the class attribute `__permissions__`
-of entity types and relation definitions. The value of this attribute
-is a dictionary where the keys are the access types (action), and the
-values are the authorized groups or rql expressions.
-
-For an entity type, the possible actions are `read`, `add`, `update` and
-`delete`.
-
-For a relation, the possible actions are `read`, `add`, and `delete`.
-
-For an attribute, the possible actions are `read`, `add` and `update`,
-and they are a refinement of an entity type permission.
-
-.. note::
-
-   By default, the permissions of an entity type attributes are
-   equivalent to the permissions of the entity type itself.
-
-   It is possible to provide custom attribute permissions which are
-   stronger than, or are more lenient than the entity type
-   permissions.
-
-   In a situation where all attributes were given custom permissions,
-   the entity type permissions would not be checked, except for the
-   `delete` action.
-
-For each access type, a tuple indicates the name of the authorized groups and/or
-one or multiple RQL expressions to satisfy to grant access. The access is
-provided if the user is in one of the listed groups or if one of the RQL condition
-is satisfied.
-
-Default permissions
-```````````````````
-
-The default permissions for ``EntityType`` are:
-
-.. sourcecode:: python
-
-   __permissions__ = {
-        'read': ('managers', 'users', 'guests',),
-        'update': ('managers', 'owners',),
-        'delete': ('managers', 'owners'),
-        'add': ('managers', 'users',)
-        }
-
-The default permissions for relations are:
-
-.. sourcecode:: python
-
-   __permissions__ = {'read': ('managers', 'users', 'guests',),
-                    'delete': ('managers', 'users'),
-                    'add': ('managers', 'users',)}
-
-The default permissions for attributes are:
-
-.. sourcecode:: python
-
-   __permissions__ = {'read': ('managers', 'users', 'guests',),
-                      'add': ('managers', ERQLExpression('U has_add_permission X'),
-                      'update': ('managers', ERQLExpression('U has_update_permission X')),}
-
-.. note::
-
-   The default permissions for attributes are not syntactically
-   equivalent to the default permissions of the entity types, but the
-   rql expressions work by delegating to the entity type permissions.
-
-
-The standard user groups
-````````````````````````
-
-* `guests`
-
-* `users`
-
-* `managers`
-
-* `owners`: virtual group corresponding to the entity's owner.
-  This can only be used for the actions `update` and `delete` of an entity
-  type.
-
-It is also possible to use specific groups if they are defined in the precreate
-script of the cube (``migration/precreate.py``). Defining groups in postcreate
-script or later makes them unavailable for security purposes (in this case, an
-`sync_schema_props_perms` command has to be issued in a CubicWeb shell).
-
-
-Use of RQL expression for write permissions
-```````````````````````````````````````````
-
-It is possible to define RQL expression to provide update permission (`add`,
-`delete` and `update`) on entity type / relation definitions. An rql expression
-is a piece of query (corresponds to the WHERE statement of an RQL query), and the
-expression will be considered as satisfied if it returns some results. They can
-not be used in `read` permission.
-
-To use RQL expression in entity type permission:
-
-* you have to use the class :class:`~cubicweb.schema.ERQLExpression`
-
-* in this expression, the variables `X` and `U` are pre-defined references
-  respectively on the current entity (on which the action is verified) and on the
-  user who send the request
-
-For RQL expressions on a relation type, the principles are the same except for
-the following:
-
-* you have to use the class :class:`~cubicweb.schema.RRQLExpression` instead of
-  :class:`~cubicweb.schema.ERQLExpression`
-
-* in the expression, the variables `S`, `O` and `U` are pre-defined references to
-  respectively the subject and the object of the current relation (on which the
-  action is being verified) and the user who executed the query
-
-To define security for attributes of an entity (non-final relation), you have to
-use the class :class:`~cubicweb.schema.ERQLExpression` in which `X` represents
-the entity the attribute belongs to.
-
-It is possible to use in those expression a special relation
-`has_<ACTION>_permission` where the subject is the user (eg 'U') and the object
-is any variable representing an entity (usually 'X' in
-:class:`~cubicweb.schema.ERQLExpression`, 'S' or 'O' in
-:class:`~cubicweb.schema.RRQLExpression`), meaning that the user needs to have
-permission to execute the action <ACTION> on the entities represented by this
-variable. It's recommanded to use this feature whenever possible since it
-simplify greatly complex security definition and upgrade.
-
-
-.. sourcecode:: python
-
-  class my_relation(RelationDefinition):
-    __permissions__ = {'read': ('managers', 'users'),
-                       'add': ('managers', RRQLExpression('U has_update_permission S')),
-                       'delete': ('managers', RRQLExpression('U has_update_permission S'))
-		       }
-
-In the above example, user will be allowed to add/delete `my_relation` if he has
-the `update` permission on the subject of the relation.
-
-.. note::
-
-  Potentially, the `use of an RQL expression to add an entity or a relation` can
-  cause problems for the user interface, because if the expression uses the
-  entity or the relation to create, we are not able to verify the permissions
-  before we actually added the entity (please note that this is not a problem for
-  the RQL server at all, because the permissions checks are done after the
-  creation). In such case, the permission check methods
-  (CubicWebEntitySchema.check_perm and has_perm) can indicate that the user is
-  not allowed to create this entity while it would obtain the permission.  To
-  compensate this problem, it is usually necessary in such case to use an action
-  that reflects the schema permissions but which check properly the permissions
-  so that it would show up only if possible.
-
-
-Use of RQL expression for reading rights
-````````````````````````````````````````
-
-The principles are the same but with the following restrictions:
-
-* you can not use rql expression for the `read` permission of relations and
-  attributes,
-
-* you can not use special `has_<ACTION>_permission` relation in the rql
-  expression.
-
-
-Important notes about write permissions checking
-````````````````````````````````````````````````
-
-Write permissions (e.g. 'add', 'update', 'delete') are checked in core hooks.
-
-When a permission is checked slightly vary according to if it's an entity or
-relation, and if the relation is an attribute relation or not). It's important to
-understand that since according to when a permission is checked, values returned
-by rql expressions may changes, hence the permission being granted or not.
-
-Here are the current rules:
-
-1. permission to add/update entity and its attributes are checked on
-   commit
-
-2. permission to delete an entity is checked in 'before_delete_entity' hook
-
-3. permission to add a relation is checked either:
-
-   - in 'before_add_relation' hook if the relation type is in the
-     `BEFORE_ADD_RELATIONS` set
-
-   - else at commit time if the relation type is in the `ON_COMMIT_ADD_RELATIONS`
-     set
-
-   - else in 'after_add_relation' hook (the default)
-
-4. permission to delete a relation is checked in 'before_delete_relation' hook
-
-Last but not least, remember queries issued from hooks and operation are by
-default 'unsafe', eg there are no read or write security checks.
-
-See :mod:`cubicweb.hooks.security` for more details.
-
-
-.. _yams_example:
-
-
-Derived attributes and relations
---------------------------------
-
-.. note:: **TODO** Check organisation of the whole chapter of the documentation
-
-Cubicweb offers the possibility to *query* data using so called
-*computed* relations and attributes. Those are *seen* by RQL requests
-as normal attributes and relations but are actually derived from other
-attributes and relations. In a first section we'll informally review
-two typical use cases. Then we see how to use computed attributes and
-relations in your schema. Last we will consider various significant
-aspects of their implementation and the impact on their usage.
-
-Motivating use cases
-~~~~~~~~~~~~~~~~~~~~
-
-Computed (or reified) relations
-```````````````````````````````
-
-It often arises that one must represent a ternary relation, or a
-family of relations. For example, in the context of an exhibition
-catalog you might want to link all *contributors* to the *work* they
-contributed to, but this contribution can be as *illustrator*,
-*author*, *performer*, ...
-
-The classical way to describe this kind of information within an
-entity-relationship schema is to *reify* the relation, that is turn
-the relation into a entity. In our example the schema will have a
-*Contribution* entity type used to represent the family of the
-contribution relations.
-
-
-.. sourcecode:: python
-
-    class ArtWork(EntityType):
-        name = String()
-        ...
-
-    class Person(EntityType):
-        name = String()
-        ...
-
-    class Contribution(EntityType):
-        contributor = SubjectRelation('Person', cardinality='1*', inlined=True)
-        manifestation = SubjectRelation('ArtWork')
-        role = SubjectRelation('Role')
-
-    class Role(EntityType):
-        name = String()
-
-But then, in order to query the illustrator(s) ``I`` of a work ``W``,
-one has to write::
-
-    Any I, W WHERE C is Contribution, C contributor I, C manifestation W,
-                   C role R, R name 'illustrator'
-
-whereas we would like to be able to simply write::
-
-    Any I, W WHERE I illustrator_of W
-
-This is precisely what the computed relations allow.
-
-
-Computed (or synthesized) attribute
-```````````````````````````````````
-
-Assuming a trivial schema for describing employees in companies, one
-can be interested in the total of salaries payed by a company for
-all its employees. One has to write::
-
-    Any C, SUM(SA) GROUPBY S WHERE E works_for C, E salary SA
-
-whereas it would be most convenient to simply write::
-
-    Any C, TS WHERE C total_salary TS
-
-And this is again what computed attributes provide.
-
-
-Using computed attributes and relations
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Computed (or reified) relations
-```````````````````````````````
-
-In the above case we would define the *computed relation*
-``illustrator_of`` in the schema by:
-
-.. sourcecode:: python
-
-    class illustrator_of(ComputedRelation):
-        rule  = ('C is Contribution, C contributor S, C manifestation O,'
-                 'C role R, R name "illustrator"')
-
-You will note that:
-
-* the ``S`` and ``O`` RQL variables implicitly identify the subject and
-  object of the defined computed relation, akin to what happens in
-  RRQLExpression
-* the possible subject and object entity types are inferred from the rule;
-* computed relation definitions always have empty *add* and *delete* permissions
-* *read* permissions can be defined, permissions from the relations used in the
-  rewrite rule **are not considered** ;
-* nothing else may be defined on the `ComputedRelation` subclass beside
-  description, permissions and rule (e.g. no cardinality, composite, etc.,).
-  `BadSchemaDefinition` is raised on attempt to specify other attributes;
-* computed relations can not be used in 'SET' and 'DELETE' rql queries
-  (`BadQuery` exception raised).
-
-
-NB: The fact that the *add* and *delete* permissions are *empty* even
-for managers is expected to make the automatic UI not attempt to edit
-them.
-
-Computed (or synthesized) attributes
-````````````````````````````````````
-
-In the above case we would define the *computed attribute*
-``total_salary`` on the ``Company`` entity type in the schema by:
-
-.. sourcecode:: python
-
-    class Company(EntityType):
-        name = String()
-        total_salary = Int(formula='Any SUM(SA) GROUPBY E WHERE P works_for X, E salary SA')
-
-* the ``X`` RQL variable implicitly identifies the entity holding the
-  computed attribute, akin to what happens in ERQLExpression;
-* the type inferred from the formula is checked against the declared type, and
-  `BadSchemaDefinition` is raised if they don't match;
-* the computed attributes always have empty *update* permissions
-* `BadSchemaDefinition` is raised on attempt to set 'update' permissions;
-* 'read' permissions can be defined, permissions regarding the formula
-  **are not considered**;
-* other attribute's property (inlined, ...) can be defined as for normal attributes;
-* Similarly to computed relation, computed attribute can't be used in 'SET' and
-  'DELETE' rql queries (`BadQuery` exception raised).
-
-
-API and implementation
-~~~~~~~~~~~~~~~~~~~~~~
-
-Representation in the data backend
-``````````````````````````````````
-
-Computed relations have no direct representation at the SQL table
-level.  Instead, each time a query is issued the query is rewritten to
-replace the computed relation by its equivalent definition and the
-resulting rewritten query is performed in the usual way.
-
-On the contrary, computed attributes are represented as a column in the
-table for their host entity type, just like normal attributes. Their
-value is kept up-to-date with respect to their defintion by a system
-of hooks (also called triggers in most RDBMS) which recomputes them
-when the relations and attributes they depend on are modified.
-
-Yams API
-````````
-
-When accessing the schema through the *yams API* (not when defining a
-schema in a ``schema.py`` file) the computed attributes and relations
-are represented as follows:
-
-relations
-    The ``yams.RelationSchema`` class has a new ``rule`` attribute
-    holding the rule as a string. If this attribute is set all others
-    must not be set.
-attributes
-    A new property ``formula`` is added on class
-    ``yams.RelationDefinitionSchema`` alomng with a new keyword
-    argument ``formula`` on the initializer.
-
-Migration
-`````````
-
-The migrations are to be handled as summarized in the array below.
-
-+------------+---------------------------------------------------+---------------------------------------+
-|            | Computed rtype                                    | Computed attribute                    |
-+============+===================================================+=======================================+
-| add        | * add_relation_type                               | * add_attribute                       |
-|            | * add_relation_definition should trigger an error | * add_relation_definition             |
-+------------+---------------------------------------------------+---------------------------------------+
-| modify     | * sync_schema_prop_perms:                         | * sync_schema_prop_perms:             |
-|            |   checks the rule is                              |                                       |
-| (rule or   |   synchronized with the database                  |   - empty the cache,                  |
-| formula)   |                                                   |   - check formula,                    |
-|            |                                                   |   - make sure all the values get      |
-|            |                                                   |     updated                           |
-+------------+---------------------------------------------------+---------------------------------------+
-| del        | * drop_relation_type                              | * drop_attribute                      |
-|            | * drop_relation_definition should trigger an error| * drop_relation_definition            |
-+------------+---------------------------------------------------+---------------------------------------+
-
-
-Defining your schema using yams
--------------------------------
-
-Entity type definition
-~~~~~~~~~~~~~~~~~~~~~~
-
-An entity type is defined by a Python class which inherits from
-:class:`yams.buildobjs.EntityType`.  The class definition contains the
-description of attributes and relations for the defined entity type.
-The class name corresponds to the entity type name. It is expected to
-be defined in the module ``mycube.schema``.
-
-:Note on schema definition:
-
- The code in ``mycube.schema`` is not meant to be executed. The class
- EntityType mentioned above is different from the EntitySchema class
- described in the previous chapter. EntityType is a helper class to
- make Entity definition easier. Yams will process EntityType classes
- and create EntitySchema instances from these class definitions. Similar
- manipulation happen for relations.
-
-When defining a schema using python files, you may use the following shortcuts:
-
-- `required`: boolean indicating if the attribute is required, ed subject cardinality is '1'
-
-- `vocabulary`: specify static possible values of an attribute
-
-- `maxsize`: integer providing the maximum size of a string (no limit by default)
-
-For example:
-
-.. sourcecode:: python
-
-  class Person(EntityType):
-    """A person with the properties and the relations necessary for my
-    application"""
-
-    last_name = String(required=True, fulltextindexed=True)
-    first_name = String(required=True, fulltextindexed=True)
-    title = String(vocabulary=('Mr', 'Mrs', 'Miss'))
-    date_of_birth = Date()
-    works_for = SubjectRelation('Company', cardinality='?*')
-
-
-The entity described above defines three attributes of type String,
-last_name, first_name and title, an attribute of type Date for the date of
-birth and a relation that connects a `Person` to another entity of type
-`Company` through the semantic `works_for`.
-
-
-
-:Naming convention:
-
- Entity class names must start with an uppercase letter. The common
- usage is to use ``CamelCase`` names.
-
- Attribute and relation names must start with a lowercase letter. The
- common usage is to use ``underscore_separated_words``. Attribute and
- relation names starting with a single underscore are permitted, to
- denote a somewhat "protected" or "private" attribute.
-
- In any case, identifiers starting with "CW" or "cw" are reserved for
- internal use by the framework.
-
- .. _Metadata:
-
- Some attribute using the name of another attribute as prefix are considered
- metadata.  For example, if an EntityType have both a ``data`` and
- ``data_format`` attribute, ``data_format`` is view as the ``format`` metadata
- of ``data``. Later the :meth:`cw_attr_metadata` method will allow you to fetch
- metadata related to an attribute. There are only three valid metadata names:
- ``format``, ``encoding`` and ``name``.
-
-
-The name of the Python attribute corresponds to the name of the attribute
-or the relation in *CubicWeb* application.
-
-An attribute is defined in the schema as follows::
-
-    attr_name = AttrType(*properties, metadata={})
-
-where
-
-* `AttrType`: is one of the type listed in EntityType_,
-
-* `properties`: is a list of the attribute needs to satisfy (see `Properties`_
-  for more details),
-
-* `metadata`: is a dictionary of meta attributes related to ``attr_name``.
-  Dictionary keys are the name of the meta attribute. Dictionary values
-  attributes objects (like the content of ``AttrType``). For each entry of the
-  metadata dictionary a ``<attr_name>_<key> = <value>`` attribute is
-  automaticaly added to the EntityType.  see `Metadata`_ section for details
-  about valid key.
-
-
- ---
-
-While building your schema
-
-* it is possible to use the attribute `meta` to flag an entity type as a `meta`
-  (e.g. used to describe/categorize other entities)
-
-.. XXX the paragraph below needs clarification and / or moving out in
-.. another place
-
-*Note*: if you end up with an `if` in the definition of your entity, this probably
-means that you need two separate entities that implement the `ITree` interface and
-get the result from `.children()` which ever entity is concerned.
-
-.. Inheritance
-.. ```````````
-.. XXX feed me
-
-
-Definition of relations
-~~~~~~~~~~~~~~~~~~~~~~~
-
-.. XXX add note about defining relation type / definition
-
-A relation is defined by a Python class heriting `RelationType`. The name
-of the class corresponds to the name of the type. The class then contains
-a description of the properties of this type of relation, and could as well
-contain a string for the subject and a string for the object. This allows to create
-new definition of associated relations, (so that the class can have the
-definition properties from the relation) for example ::
-
-  class locked_by(RelationType):
-    """relation on all entities indicating that they are locked"""
-    inlined = True
-    cardinality = '?*'
-    subject = '*'
-    object = 'CWUser'
-
-If provided, the `subject` and `object` attributes denote the subject
-and object of the various relation definitions related to the relation
-type. Allowed values for these attributes are:
-
-* a string corresponding to an entity type
-* a tuple of string corresponding to multiple entity types
-* the '*' special string, meaning all types of entities
-
-When a relation is not inlined and not symmetrical, and it does not require
-specific permissions, it can be defined using a `SubjectRelation`
-attribute in the EntityType class. The first argument of `SubjectRelation` gives
-the entity type for the object of the relation.
-
-:Naming convention:
-
- Although this way of defining relations uses a Python class, the
- naming convention defined earlier prevails over the PEP8 conventions
- used in the framework: relation type class names use
- ``underscore_separated_words``.
-
-:Historical note:
-
-   It has been historically possible to use `ObjectRelation` which
-   defines a relation in the opposite direction. This feature is
-   deprecated and therefore should not be used in newly written code.
-
-:Future deprecation note:
-
-  In an even more remote future, it is quite possible that the
-  SubjectRelation shortcut will become deprecated, in favor of the
-  RelationType declaration which offers some advantages in the context
-  of reusable cubes.
-
-
-
-
-Handling schema changes
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Also, it should be clear that to properly handle data migration, an
-instance's schema is stored in the database, so the python schema file
-used to defined it is only read when the instance is created or
-upgraded.
-
-.. XXX complete me
--- a/doc/book/en/devrepo/datamodel/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-Data model
-==========
-
-This chapter describes how you define a schema and how to make it evolves as the time goes.
-
-.. toctree::
-   :maxdepth: 1
-
-   definition
-   metadata
-   baseschema
-   define-workflows
--- a/doc/book/en/devrepo/datamodel/metadata.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-
-Metadata
---------
-
-.. index::
-   schema: meta-data;
-   schema: eid; creation_date; modification_data; cwuri
-   schema: created_by; owned_by; is; is_instance;
-
-Each entity type in |cubicweb| has at least the following meta-data attributes and relations:
-
-`eid`
-  entity's identifier which is unique in an instance. We usually call this identifier `eid` for historical reason.
-
-`creation_date`
-  Date and time of the creation of the entity.
-
-`modification_date`
-  Date and time of the latest modification of an entity.
-
-`cwuri`
-  Reference URL of the entity, which is not expected to change.
-
-`created_by`
-  Relation to the :ref:`users <CWUser>` who has created the entity
-
-`owned_by`
-  Relation to :ref:`users <CWUser>` whom the entity belongs; usually the creator but not
-  necessary, and it could have multiple owners notably for permission control
-
-`is`
-  Relation to the :ref:`entity type <CWEType>` of which type the entity is.
-
-`is_instance`
-  Relation to the :ref:`entity types <CWEType>` of which type the
-  entity is an instance of.
-
--- a/doc/book/en/devrepo/devcore/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-Core APIs
-=========
-
-.. toctree::
-   :maxdepth: 1
-
-   reqbase.rst
-
--- a/doc/book/en/devrepo/devcore/reqbase.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-Request and ResultSet methods
------------------------------
-
-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 :).
-
-`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
-
-`And more...`:
-
-* `tal_render(template, variables)`, renders a precompiled page template with
-  variables in the given dictionary as context
-
-
-Result set methods
-~~~~~~~~~~~~~~~~~~
-
-* `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
-
-
--- a/doc/book/en/devrepo/entityclasses/adapters.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-.. _adapters:
-
-Interfaces and Adapters
------------------------
-
-Interfaces are the same thing as object-oriented programming `interfaces`_.
-Adapter refers to a well-known `adapter`_ design pattern that helps separating
-concerns in object oriented applications.
-
-.. _`interfaces`: http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
-.. _`adapter`: http://en.wikipedia.org/wiki/Adapter_pattern
-
-In |cubicweb| adapters provide logical functionalities to entity types.
-
-Definition of an adapter is quite trivial. An excerpt from cubicweb
-itself (found in :mod:`cubicweb.entities.adapters`):
-
-.. sourcecode:: python
-
-
-    class ITreeAdapter(EntityAdapter):
-        """This adapter has to be overriden to be configured using the
-        tree_relation, child_role and parent_role class attributes to
-        benefit from this default implementation
-        """
-        __regid__ = 'ITree'
-
-        child_role = 'subject'
-        parent_role = 'object'
-
-        def children_rql(self):
-            """returns RQL to get children """
-            return self.entity.cw_related_rql(self.tree_relation, self.parent_role)
-
-The adapter object has ``self.entity`` attribute which represents the
-entity being adapted.
-
-.. Note::
-
-   Adapters came with the notion of service identified by the registry identifier
-   of an adapters, hence dropping the need for explicit interface and the
-   :class:`cubicweb.predicates.implements` selector. You should instead use
-   :class:`cubicweb.predicates.is_instance` when you want to select on an entity
-   type, or :class:`cubicweb.predicates.adaptable` when you want to select on a
-   service.
-
-
-Specializing and binding an adapter
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. sourcecode:: python
-
-  from cubicweb.entities.adapters import ITreeAdapter
-
-  class MyEntityITreeAdapter(ITreeAdapter):
-      __select__ = is_instance('MyEntity')
-      tree_relation = 'filed_under'
-
-The ITreeAdapter here provides a default implementation. The
-tree_relation class attribute is actually used by this implementation
-to help implement correct behaviour.
-
-Here we provide a specific implementation which will be bound for
-``MyEntity`` entity type (the `adaptee`).
-
-
-.. _interfaces_to_adapters:
-
-Converting code from Interfaces/Mixins to Adapters
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Here we go with a small example. Before:
-
-.. sourcecode:: python
-
-    from cubicweb.predicates import implements
-    from cubicweb.interfaces import ITree
-    from cubicweb.mixins import ITreeMixIn
-
-    class MyEntity(ITreeMixIn, AnyEntity):
-        __implements__ = AnyEntity.__implements__ + (ITree,)
-
-
-    class ITreeView(EntityView):
-        __select__ = implements('ITree')
-        def cell_call(self, row, col):
-            entity = self.cw_rset.get_entity(row, col)
-            children = entity.children()
-
-After:
-
-.. sourcecode:: python
-
-    from cubicweb.predicates import adaptable, is_instance
-    from cubicweb.entities.adapters import ITreeAdapter
-
-    class MyEntityITreeAdapter(ITreeAdapter):
-        __select__ = is_instance('MyEntity')
-
-    class ITreeView(EntityView):
-        __select__ = adaptable('ITree')
-        def cell_call(self, row, col):
-            entity = self.cw_rset.get_entity(row, col)
-            itree = entity.cw_adapt_to('ITree')
-            children = itree.children()
-
-As we can see, the interface/mixin duality disappears and the entity
-class itself is completely freed from these concerns. When you want
-to use the ITree interface of an entity, call its `cw_adapt_to` method
-to get an adapter for this interface, then access to members of the
-interface on the adapter
-
-Let's look at an example where we defined everything ourselves. We
-start from:
-
-.. sourcecode:: python
-
-    class IFoo(Interface):
-        def bar(self, *args):
-            raise NotImplementedError
-
-    class MyEntity(AnyEntity):
-        __regid__ = 'MyEntity'
-        __implements__ = AnyEntity.__implements__ + (IFoo,)
-
-        def bar(self, *args):
-            return sum(captain.age for captain in self.captains)
-
-    class FooView(EntityView):
-        __regid__ = 'mycube.fooview'
-        __select__ = implements('IFoo')
-
-        def cell_call(self, row, col):
-            entity = self.cw_rset.get_entity(row, col)
-            self.w('bar: %s' % entity.bar())
-
-Converting to:
-
-.. sourcecode:: python
-
-   class IFooAdapter(EntityAdapter):
-       __regid__ = 'IFoo'
-       __select__ = is_instance('MyEntity')
-
-       def bar(self, *args):
-           return sum(captain.age for captain in self.entity.captains)
-
-   class FooView(EntityView):
-        __regid__ = 'mycube.fooview'
-        __select__ = adaptable('IFoo')
-
-        def cell_call(self, row, col):
-            entity = self.cw_rset.get_entity(row, col)
-            self.w('bar: %s' % entity.cw_adapt_to('IFoo').bar())
-
-.. note::
-
-   When migrating an entity method to an adapter, the code can be moved as is
-   except for the `self` of the entity class, which in the adapter must become `self.entity`.
-
-Adapters defined in the library
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. automodule:: cubicweb.entities.adapters
-   :members:
-
-More are defined in web/views.
--- a/doc/book/en/devrepo/entityclasses/application-logic.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-How to use entities objects and adapters
-----------------------------------------
-
-The previous chapters detailed the classes and methods available to
-the developer at the so-called `ORM`_ level. However they say little
-about the common patterns of usage of these objects.
-
-.. _`ORM`: http://en.wikipedia.org/wiki/Object-relational_mapping
-
-Entities objects (and their adapters) are used in the repository and
-web sides of CubicWeb. On the repository side of things, one should
-manipulate them in Hooks and Operations.
-
-Hooks and Operations provide support for the implementation of rules
-such as computed attributes, coherency invariants, etc (they play the
-same role as database triggers, but in a way that is independent of
-the actual data sources).
-
-So a lot of an application's business rules will be written in Hooks
-(or Operations).
-
-On the web side, views also typically operate using entity
-objects. Obvious entity methods for use in views are the Dublin Core
-methods like ``dc_title``. For separation of concerns reasons, one
-should ensure no ui logic pervades the entities level, and also no
-business logic should creep into the views.
-
-In the duration of a transaction, entities objects can be instantiated
-many times, in views and hooks, even for the same database entity. For
-instance, in a classic CubicWeb deployment setup, the repository and
-the web front-end are separated process communicating over the
-wire. There is no way state can be shared between these processes
-(there is a specific API for that). Hence, it is not possible to use
-entity objects as messengers between these components of an
-application. It means that an attribute set as in ``obj.x = 42``,
-whether or not x is actually an entity schema attribute, has a short
-life span, limited to the hook, operation or view within which the
-object was built.
-
-Setting an attribute or relation value can be done in the context of a
-Hook/Operation, using the ``obj.cw_set(x=42)`` notation or a plain
-RQL ``SET`` expression.
-
-In views, it would be preferable to encapsulate the necessary logic in
-a method of an adapter for the concerned entity class(es). But of
-course, this advice is also reasonable for Hooks/Operations, though
-the separation of concerns here is less stringent than in the case of
-views.
-
-This leads to the practical role of objects adapters: it's where an
-important part of the application logic lies (the other part being
-located in the Hook/Operations).
-
-Anatomy of an entity class
---------------------------
-
-We can look now at a real life example coming from the `tracker`_
-cube. Let us begin to study the ``entities/project.py`` content.
-
-.. sourcecode:: python
-
-    from cubicweb.entities.adapters import ITreeAdapter
-
-    class ProjectAdapter(ITreeAdapter):
-        __select__ = is_instance('Project')
-        tree_relation = 'subproject_of'
-
-    class Project(AnyEntity):
-        __regid__ = 'Project'
-        fetch_attrs, cw_fetch_order = fetch_config(('name', 'description',
-                                                    'description_format', 'summary'))
-
-        TICKET_DEFAULT_STATE_RESTR = 'S name IN ("created","identified","released","scheduled")'
-
-        def dc_title(self):
-            return self.name
-
-The fact that the `Project` entity type implements an ``ITree``
-interface is materialized by the ``ProjectAdapter`` class (inheriting
-the pre-defined ``ITreeAdapter`` whose ``__regid__`` is of course
-``ITree``), which will be selected on `Project` entity types because
-of its selector. On this adapter, we redefine the ``tree_relation``
-attribute of the ``ITreeAdapter`` class.
-
-This is typically used in views concerned with the representation of
-tree-like structures (CubicWeb provides several such views).
-
-It is important that the views themselves try not to implement this
-logic, not only because such views would be hardly applyable to other
-tree-like relations, but also because it is perfectly fine and useful
-to use such an interface in Hooks.
-
-In fact, Tree nature is a property of the data model that cannot be
-fully and portably expressed at the level of database entities (think
-about the transitive closure of the child relation). This is a further
-argument to implement it at entity class level.
-
-``fetch_attrs`` configures which attributes should be pre-fetched when using ORM
-methods retrieving entity of this type. In a same manner, the ``cw_fetch_order`` is
-a class method allowing to control sort order. More on this in :ref:`FetchAttrs`.
-
-We can observe the big ``TICKET_DEFAULT_STATE_RESTR`` is a pure
-application domain piece of data. There is, of course, no limitation
-to the amount of class attributes of this kind.
-
-The ``dc_title`` method provides a (unicode string) value likely to be
-consumed by views, but note that here we do not care about output
-encodings. We care about providing data in the most universal format
-possible, because the data could be used by a web view (which would be
-responsible of ensuring XHTML compliance), or a console or file
-oriented output (which would have the necessary context about the
-needed byte stream encoding).
-
-.. note::
-
-  The Dublin Core `dc_xxx` methods are not moved to an adapter as they
-  are extremely prevalent in CubicWeb and assorted cubes and should be
-  available for all entity types.
-
-Let us now dig into more substantial pieces of code, continuing the
-Project class.
-
-.. sourcecode:: python
-
-    def latest_version(self, states=('published',), reverse=None):
-        """returns the latest version(s) for the project in one of the given
-        states.
-
-        when no states specified, returns the latest published version.
-        """
-        order = 'DESC'
-        if reverse is not None:
-            warn('reverse argument is deprecated',
-                 DeprecationWarning, stacklevel=1)
-            if reverse:
-                order = 'ASC'
-        rset = self.versions_in_state(states, order, True)
-        if rset:
-            return rset.get_entity(0, 0)
-        return None
-
-    def versions_in_state(self, states, order='ASC', limit=False):
-        """returns version(s) for the project in one of the given states, sorted
-        by version number.
-
-        If limit is true, limit result to one version.
-        If reverse, versions are returned from the smallest to the greatest.
-        """
-        if limit:
-            order += ' LIMIT 1'
-        rql = 'Any V,N ORDERBY version_sort_value(N) %s ' \
-              'WHERE V num N, V in_state S, S name IN (%s), ' \
-              'V version_of P, P eid %%(p)s' % (order, ','.join(repr(s) for s in states))
-        return self._cw.execute(rql, {'p': self.eid})
-
-.. _`tracker`: http://www.cubicweb.org/project/cubicweb-tracker/
-
-These few lines exhibit the important properties we want to outline:
-
-* entity code is concerned with the application domain
-
-* it is NOT concerned with database consistency (this is the realm of
-  Hooks/Operations); in other words, it assumes a consistent world
-
-* it is NOT (directly) concerned with end-user interfaces
-
-* however it can be used in both contexts
-
-* it does not create or manipulate the internal object's state
-
-* it plays freely with RQL expression as needed
-
-* it is not concerned with internationalization
-
-* it does not raise exceptions
-
-
--- a/doc/book/en/devrepo/entityclasses/data-as-objects.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-Access to persistent data
---------------------------
-
-Python-level access to persistent data is provided by the
-:class:`Entity <cubicweb.entity>` class.
-
-.. XXX this part is not clear. refactor it.
-
-An entity class is bound to a schema entity type. Descriptors are added when
-classes are registered in order to initialize the class according to its schema:
-
-* the attributes defined in the schema appear as attributes of these classes
-
-* the relations defined in the schema appear as attributes of these classes,
-  but are lists of instances
-
-`Formatting and output generation`:
-
-* :meth:`view(__vid, __registry='views', **kwargs)`, applies the given view to the entity
-  (and returns a unicode string)
-
-* :meth:`absolute_url(*args, **kwargs)`, returns an absolute URL including the base-url
-
-* :meth:`rest_path()`, returns a relative REST URL to get the entity
-
-* :meth:`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`:
-
-* :meth:`as_rset()`, converts the entity into an equivalent result set simulating the
-  request `Any X WHERE X eid _eid_`
-
-* :meth:`complete(skip_bytes=True)`, executes a request that recovers at
-  once all the missing attributes of an entity
-
-* :meth:`get_value(name)`, returns the value associated to the attribute name given
-  in parameter
-
-* :meth:`related(rtype, role='subject', limit=None, entities=False)`,
-  returns a list of entities related to the current entity by the
-  relation given in parameter
-
-* :meth:`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
-
-* :meth:`cw_set(**kwargs)`, updates entity's attributes and/or relation with the
-  corresponding values given named parameters. 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).
-
-* :meth:`copy_relations(ceid)`, copies the relations of the entities having the eid
-  given in the parameters on the current entity
-
-* :meth:`cw_delete()` allows to delete the entity
-
-
-The :class:`AnyEntity` class
-----------------------------
-
-To provide a specific behavior for each entity, we can define a class
-inheriting from `cubicweb.entities.AnyEntity`. In general, we define this class
-in `mycube.entities` module (or in a submodule if we want to split code among
-multiple files) so that it will be available on both server and client side.
-
-The class `AnyEntity` is a sub-class of Entity that add methods to it,
-and helps specializing (by further subclassing) the handling of a
-given entity type.
-
-Most methods defined for `AnyEntity`, in addition to `Entity`, add
-support for the `Dublin Core`_ metadata.
-
-.. _`Dublin Core`: http://dublincore.org/
-
-`Standard meta-data (Dublin Core)`:
-
-* :meth:`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)
-
-* :meth:`dc_long_title()`, same as dc_title but can return a more
-  detailed title
-
-* :meth:`dc_description(format='text/plain')`, returns a unicode string
-  corresponding to the meta-data `Description` (looks for a
-  description attribute by default)
-
-* :meth:`dc_authors()`, returns a unicode string corresponding to the meta-data
-  `Authors` (owners by default)
-
-* :meth:`dc_creator()`, returns a unicode string corresponding to the
-  creator of the entity
-
-* :meth:`dc_date(date_format=None)`, returns a unicode string corresponding to
-  the meta-data `Date` (update date by default)
-
-* :meth:`dc_type(form='')`, returns a string to display the entity type by
-  specifying the preferred form (`plural` for a plural form)
-
-* :meth:`dc_language()`, returns the language used by the entity
-
-Inheritance
------------
-
-When describing a data model, entities can inherit from other entities as is
-common in object-oriented programming.
-
-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, which is an
-experimental undocumented feature.
-
-
-Application logic
------------------
-
-While a lot of custom behaviour and application logic can be
-implemented using entity classes, the programmer must be aware that
-adding new attributes and method on an entity class adds may shadow
-schema-level attribute or relation definitions.
-
-To keep entities clean (mostly data structures plus a few universal
-methods such as listed above), one should use `adapters` (see
-:ref:`adapters`).
--- a/doc/book/en/devrepo/entityclasses/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-Data as objects
-===============
-
-In this chapter, we will introduce the objects that are used to handle
-the logic associated to the data stored in the database.
-
-.. toctree::
-   :maxdepth: 1
-
-   data-as-objects
-   load-sort
-   adapters
-   application-logic
--- a/doc/book/en/devrepo/entityclasses/load-sort.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-
-.. _FetchAttrs:
-
-Loaded attributes and default sorting management
-````````````````````````````````````````````````
-
-* The class attribute `fetch_attrs` allows to define in an entity class a list of
-  names of attributes that should be automatically loaded when entities of this
-  type are fetched from the database using ORM methods retrieving entity of this
-  type (such as :meth:`related` and :meth:`unrelated`). You can also put relation
-  names in there, but we are limited to *subject relations of cardinality `?` or
-  `1`*.
-
-* The :meth:`cw_fetch_order` and :meth:`cw_fetch_unrelated_order` class methods
-  are respectively responsible to control how entities will be sorted when:
-
-  - retrieving all entities of a given type, or entities related to another
-
-  - retrieving a list of entities for use in drop-down lists enabling relations
-    creation in the editing view of an entity
-
-By default entities will be listed on their modification date descending,
-i.e. you'll get entities recently modified first. While this is usually a good
-default in drop-down list, you'll probably want to change `cw_fetch_order`.
-
-This may easily be done using the :func:`~cubicweb.entities.fetch_config`
-function, which simplifies the definition of attributes to load and sorting by
-returning a list of attributes to pre-load (considering automatically the
-attributes of `AnyEntity`) and a sorting function as described below:
-
-.. autofunction:: cubicweb.entities.fetch_config
-
-In you want something else (such as sorting on the result of a registered
-procedure), here is the prototype of those methods:
-
-
-.. automethod:: cubicweb.entity.Entity.cw_fetch_order
-
-.. automethod:: cubicweb.entity.Entity.cw_fetch_unrelated_order
-
--- a/doc/book/en/devrepo/fti.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-.. _fti:
-
-Full Text Indexing in CubicWeb
-------------------------------
-
-When an attribute is tagged as *fulltext-indexable* in the datamodel,
-CubicWeb will automatically trigger hooks to update the internal
-fulltext index (i.e the ``appears`` SQL table) each time this attribute
-is modified.
-
-CubicWeb also provides a ``db-rebuild-fti`` command to rebuild the whole
-fulltext on demand:
-
-.. sourcecode:: bash
-
-   cubicweb@esope~$ cubicweb db-rebuild-fti my_tracker_instance
-
-You can also rebuild the fulltext index for a given set of entity types:
-
-.. sourcecode:: bash
-
-   cubicweb@esope~$ cubicweb db-rebuild-fti my_tracker_instance Ticket Version
-
-In the above example, only fulltext index of entity types ``Ticket`` and ``Version``
-will be rebuilt.
-
-
-Standard FTI process
-~~~~~~~~~~~~~~~~~~~~
-
-Considering an entity type ``ET``, the default *fti* process is to :
-
-1. fetch all entities of type ``ET``
-
-2. for each entity, adapt it to ``IFTIndexable`` (see
-   :class:`~cubicweb.entities.adapters.IFTIndexableAdapter`)
-
-3. call
-   :meth:`~cubicweb.entities.adapters.IFTIndexableAdapter.get_words` on
-   the adapter which is supposed to return a dictionary *weight* ->
-   *list of words* as expected by
-   :meth:`~logilab.database.fti.FTIndexerMixIn.index_object`. The
-   tokenization of each attribute value is done by
-   :meth:`~logilab.database.fti.tokenize`.
-
-
-See :class:`~cubicweb.entities.adapters.IFTIndexableAdapter` for more documentation.
-
-
-Yams and ``fulltext_container``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-It is possible in the datamodel to indicate that fulltext-indexed
-attributes defined for an entity type will be used to index not the
-entity itself but a related entity. This is especially useful for
-composite entities. Let's take a look at (a simplified version of)
-the base schema defined in CubicWeb (see :mod:`cubicweb.schemas.base`):
-
-.. sourcecode:: python
-
-  class CWUser(WorkflowableEntityType):
-      login     = String(required=True, unique=True, maxsize=64)
-      upassword = Password(required=True)
-
-  class EmailAddress(EntityType):
-      address = String(required=True,  fulltextindexed=True,
-                       indexed=True, unique=True, maxsize=128)
-
-
-  class use_email_relation(RelationDefinition):
-      name = 'use_email'
-      subject = 'CWUser'
-      object = 'EmailAddress'
-      cardinality = '*?'
-      composite = 'subject'
-
-
-The schema above states that there is a relation between ``CWUser`` and ``EmailAddress``
-and that the ``address`` field of ``EmailAddress`` is fulltext indexed. Therefore,
-in your application, if you use fulltext search to look for an email address, CubicWeb
-will return the ``EmailAddress`` itself. But the objects we'd like to index
-are more likely to be the associated ``CWUser`` than the ``EmailAddress`` itself.
-
-The simplest way to achieve that is to tag the ``use_email`` relation in
-the datamodel:
-
-.. sourcecode:: python
-
-  class use_email(RelationType):
-      fulltext_container = 'subject'
-
-
-Customizing how entities are fetched during ``db-rebuild-fti``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-``db-rebuild-fti`` will call the
-:meth:`~cubicweb.entities.AnyEntity.cw_fti_index_rql_queries` class
-method on your entity type.
-
-.. automethod:: cubicweb.entities.AnyEntity.cw_fti_index_rql_queries
-
-Now, suppose you've got a _huge_ table to index, you probably don't want to
-get all entities at once. So here's a simple customized example that will
-process block of 10000 entities:
-
-.. sourcecode:: python
-
-
-    class MyEntityClass(AnyEntity):
-        __regid__ = 'MyEntityClass'
-
-    @classmethod
-    def cw_fti_index_rql_queries(cls, req):
-        # get the default RQL method and insert LIMIT / OFFSET instructions
-        base_rql = super(SearchIndex, cls).cw_fti_index_rql_queries(req)[0]
-        selected, restrictions = base_rql.split(' WHERE ')
-        rql_template = '%s ORDERBY X LIMIT %%(limit)s OFFSET %%(offset)s WHERE %s' % (
-            selected, restrictions)
-        # count how many entities you'll have to index
-        count = req.execute('Any COUNT(X) WHERE X is MyEntityClass')[0][0]
-        # iterate by blocks of 10000 entities
-        chunksize = 10000
-        for offset in xrange(0, count, chunksize):
-            print 'SENDING', rql_template % {'limit': chunksize, 'offset': offset}
-            yield rql_template % {'limit': chunksize, 'offset': offset}
-
-Since you have access to ``req``, you can more or less fetch whatever you want.
-
-
-Customizing :meth:`~cubicweb.entities.adapters.IFTIndexableAdapter.get_words`
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You can also customize the FTI process by providing your own ``get_words()``
-implementation:
-
-.. sourcecode:: python
-
-    from cubicweb.entities.adapters import IFTIndexableAdapter
-
-    class SearchIndexAdapter(IFTIndexableAdapter):
-        __regid__ = 'IFTIndexable'
-        __select__ = is_instance('MyEntityClass')
-
-        def fti_containers(self, _done=None):
-            """this should yield any entity that must be considered to
-            fulltext-index self.entity
-
-            CubicWeb's default implementation will look for yams'
-            ``fulltex_container`` property.
-            """
-            yield self.entity
-            yield self.entity.some_related_entity
-
-
-        def get_words(self):
-            # implement any logic here
-            # see http://www.postgresql.org/docs/9.1/static/textsearch-controls.html
-            # for the actual signification of 'C'
-            return {'C': ['any', 'word', 'I', 'want']}
--- a/doc/book/en/devrepo/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-.. _Part2:
-
-----------------------
-Repository development
-----------------------
-
-This part is about developing applications with the *CubicWeb*
-framework. It is not concerned with the web system, which is a
-separate layer and has its own whole chapter.
-
-.. toctree::
-   :maxdepth: 2
-   :numbered:
-
-   cubes/index
-   vreg.rst
-   datamodel/index
-   entityclasses/index
-   devcore/index
-   repo/index
-   testing.rst
-   migration.rst
-   profiling.rst
-   fti.rst
-   dataimport
--- a/doc/book/en/devrepo/migration.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _migration:
-
-Migration
-=========
-
-One of the main design goals of *CubicWeb* was to support iterative and agile
-development. For this purpose, multiple actions are provided to facilitate the
-improvement of an instance, and in particular to handle the changes to be
-applied to the data model, without loosing existing data.
-
-The current version of a cube (and of cubicweb itself) is provided in the file
-`__pkginfo__.py` as a tuple of 3 integers.
-
-Migration scripts management
-----------------------------
-
-Migration scripts has to be located in the directory `migration` of your
-cube and named accordingly:
-
-::
-
-  <version n° X.Y.Z>[_<description>]_<mode>.py
-
-in which :
-
-* X.Y.Z is the model version number to which the script enables to migrate.
-
-* *mode* (between the last "_" and the extension ".py") is used for
-  distributed installation. It indicates to which part
-  of the application (RQL server, web server) the script applies.
-  Its value could be :
-
-  * `common`, applies to the RQL server as well as the web server and updates
-    files on the hard drive (configuration files migration for example).
-
-  * `web`, applies only to the web server and updates files on the hard drive.
-
-  * `repository`, applies only to the RQL server and updates files on the
-    hard drive.
-
-  * `Any`, applies only to the RQL server and updates data in the database
-    (schema and data migration for example).
-
-Again in the directory `migration`, the file `depends.map` allows to indicate
-that for the migration to a particular model version, you always have to first
-migrate to a particular *CubicWeb* version. This file can contain comments (lines
-starting with `#`) and a dependency is listed as follows: ::
-
-  <model version n° X.Y.Z> : <cubicweb version n° X.Y.Z>
-
-For example: ::
-
-  0.12.0: 2.26.0
-  0.13.0: 2.27.0
-  # 0.14 works with 2.27 <= cubicweb <= 2.28 at least
-  0.15.0: 2.28.0
-
-Base context
-------------
-
-The following identifiers are pre-defined in migration scripts:
-
-* `config`, instance configuration
-
-* `interactive_mode`, boolean indicating that the script is executed in
-  an interactive mode or not
-
-* `versions_map`, dictionary of migrated versions  (key are cubes
-  names, including 'cubicweb', values are (from version, to version)
-
-* `confirm(question)`, function asking the user and returning true
-  if the user answers yes, false otherwise (always returns true in
-  non-interactive mode)
-
-* `_()` is equivalent to `unicode` allowing to flag the strings to
-  internationalize in the migration scripts.
-
-In the `repository` scripts, the following identifiers are also defined:
-
-* `commit(ask_confirm=True)`, request confirming and executing a "commit"
-
-* `schema`, instance schema (readen from the database)
-
-* `fsschema`, installed schema on the file system (e.g. schema of
-  the updated model and cubicweb)
-
-* `repo`, repository object
-
-* `session`, repository session object
-
-
-New cube dependencies
----------------------
-
-If your code depends on some new cubes, you have to add them in a migration
-script by using:
-
-* `add_cube(cube, update_database=True)`, add a cube.
-* `add_cubes(cubes, update_database=True)`, add a list of cubes.
-
-The `update_database` parameter is telling if the database schema
-should be updated or if only the relevant persistent property should be
-inserted (for the case where a new cube has been extracted from an
-existing one, so the new cube schema is actually already in there).
-
-If some of the added cubes are already used by an instance, they'll simply be
-silently skipped.
-
-
-Schema migration
-----------------
-The following functions for schema migration are available in `repository`
-scripts:
-
-* `add_attribute(etype, attrname, attrtype=None, commit=True)`, adds a new
-  attribute to an existing entity type. If the attribute type is not specified,
-  then it is extracted from the updated schema.
-
-* `drop_attribute(etype, attrname, commit=True)`, removes an attribute from an
-  existing entity type.
-
-* `rename_attribute(etype, oldname, newname, commit=True)`, renames an attribute
-
-* `add_entity_type(etype, auto=True, commit=True)`, adds a new entity type.
-  If `auto` is True, all the relations using this entity type and having a known
-  entity type on the other hand will automatically be added.
-
-* `drop_entity_type(etype, commit=True)`, removes an entity type and all the
-  relations using it.
-
-* `rename_entity_type(oldname, newname, commit=True)`, renames an entity type
-
-* `add_relation_type(rtype, addrdef=True, commit=True)`, adds a new relation
-  type. If `addrdef` is True, all the relations definitions of this type will
-  be added.
-
-* `drop_relation_type(rtype, commit=True)`, removes a relation type and all the
-  definitions of this type.
-
-* `rename_relation_type(oldname, newname, commit=True)`, renames a relation type.
-
-* `add_relation_definition(subjtype, rtype, objtype, commit=True)`, adds a new
-  relation definition.
-
-* `drop_relation_definition(subjtype, rtype, objtype, commit=True)`, removes
-  a relation definition.
-
-* `sync_schema_props_perms(ertype=None, syncperms=True, syncprops=True, syncrdefs=True, commit=True)`,
-  synchronizes properties and/or permissions on:
-  - the whole schema if ertype is None
-  - an entity or relation type schema if ertype is a string
-  - a relation definition  if ertype is a 3-uple (subject, relation, object)
-
-* `change_relation_props(subjtype, rtype, objtype, commit=True, **kwargs)`, changes
-  properties of a relation definition by using the named parameters of the properties
-  to change.
-
-* `set_widget(etype, rtype, widget, commit=True)`, changes the widget used for the
-  relation <rtype> of entity type <etype>.
-
-* `set_size_constraint(etype, rtype, size, commit=True)`, changes the size constraints
-  for the relation <rtype> of entity type <etype>.
-
-Data migration
---------------
-The following functions for data migration are available in `repository` scripts:
-
-* `rql(rql, kwargs=None, cachekey=None, ask_confirm=True)`, executes an arbitrary RQL
-  query, either to interrogate or update. A result set object is returned.
-
-* `add_entity(etype, *args, **kwargs)`, adds a new entity of the given type.
-  The attribute and relation values are specified as named positional
-  arguments.
-
-Workflow creation
------------------
-
-The following functions for workflow creation are available in `repository`
-scripts:
-
-* `add_workflow(label, workflowof, initial=False, commit=False, **kwargs)`, adds a new workflow
-  for a given type(s)
-
-You can find more details about workflows in the chapter :ref:`Workflow` .
-
-Configuration migration
------------------------
-
-The following functions for configuration migration are available in all
-scripts:
-
-* `option_renamed(oldname, newname)`, indicates that an option has been renamed
-
-* `option_group_change(option, oldgroup, newgroup)`, indicates that an option does not
-  belong anymore to the same group.
-
-* `option_added(oldname, newname)`, indicates that an option has been added.
-
-* `option_removed(oldname, newname)`, indicates that an option has been deleted.
-
-The `config` variable is an object which can be used to access the
-configuration values, for reading and updating, with a dictionary-like
-syntax. 
-
-Example 1: migration script changing the variable 'sender-addr' in
-all-in-one.conf. The script also checks that in that the instance is
-configured with a known value for that variable, and only updates the
-value in that case.
-
-.. sourcecode:: python
-
- wrong_addr = 'cubicweb@loiglab.fr' # known wrong address
- fixed_addr = 'cubicweb@logilab.fr'
- configured_addr = config.get('sender-addr')
- # check that the address has not been hand fixed by a sysadmin
- if configured_addr == wrong_addr: 
-     config['sender-addr'] = fixed-addr
-     config.save()
-
-Example 2: checking the value of the database backend driver, which
-can be useful in case you need to issue backend-dependent raw SQL
-queries in a migration script.
-
-.. sourcecode:: python
-
- dbdriver  = config.sources()['system']['db-driver']
- if dbdriver == "sqlserver2005":
-     # this is now correctly handled by CW :-)
-     sql('ALTER TABLE cw_Xxxx ALTER COLUMN cw_name varchar(64) NOT NULL;')
-     commit()
- else: # postgresql
-     sync_schema_props_perms(ertype=('Xxxx', 'name', 'String'),
-     syncperms=False)
-
-
-Others migration functions
---------------------------
-Those functions are only used for low level operations that could not be
-accomplished otherwise or to repair damaged databases during interactive
-session. They are available in `repository` scripts:
-
-* `sql(sql, args=None, ask_confirm=True)`, executes an arbitrary SQL query on the system source
-* `add_entity_type_table(etype, commit=True)`
-* `add_relation_type_table(rtype, commit=True)`
-* `uninline_relation(rtype, commit=True)`
-
-
-[FIXME] Add explanation on how to use cubicweb-ctl shell
--- a/doc/book/en/devrepo/profiling.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-.. _PROFILING:
-
-Profiling and performance
-=========================
-
-If you feel that one of your pages takes more time than it should to be
-generated, chances are that you're making too many RQL queries.  Obviously,
-there are other reasons but experience tends to show this is the first thing to
-track down. Luckily, CubicWeb provides a configuration option to log RQL
-queries. In your ``all-in-one.conf`` file, set the **query-log-file** option::
-
-    # web application query log file
-    query-log-file=/home/user/myapp-rql.log
-
-Then restart your application, reload your page and stop your application.
-The file ``myapp-rql.log`` now contains the list of RQL queries that were
-executed during your test. It's a simple text file containing lines such as::
-
-    Any A WHERE X eid %(x)s, X lastname A {'x': 448} -- (0.002 sec, 0.010 CPU sec)
-    Any A WHERE X eid %(x)s, X firstname A {'x': 447} -- (0.002 sec, 0.000 CPU sec)
-
-The structure of each line is::
-
-    <RQL QUERY> <QUERY ARGS IF ANY> -- <TIME SPENT>
-
-CubicWeb also provides the **exlog** command to examine and summarize data found
-in such a file:
-
-.. sourcecode:: sh
-
-    $ cubicweb-ctl exlog /home/user/myapp-rql.log
-    0.07 50 Any A WHERE X eid %(x)s, X firstname A {}
-    0.05 50 Any A WHERE X eid %(x)s, X lastname A {}
-    0.01 1 Any X,AA ORDERBY AA DESC WHERE E eid %(x)s, E employees X, X modification_date AA {}
-    0.01 1 Any X WHERE X eid %(x)s, X owned_by U, U eid %(u)s {, }
-    0.01 1 Any B,T,P ORDERBY lower(T) WHERE B is Bookmark,B title T, B path P, B bookmarked_by U, U eid %(x)s {}
-    0.01 1 Any A,B,C,D WHERE A eid %(x)s,A name B,A creation_date C,A modification_date D {}
-
-This command sorts and uniquifies queries so that it's easy to see where
-is the hot spot that needs optimization.
-
-Do not neglect to set the **fetch_attrs** attribute you can define in your
-entity classes because it can greatly reduce the number of queries executed (see
-:ref:`FetchAttrs`).
-
-You should also know about the **profile** option in the ``all-in-on.conf``. If
-set, this option will make your application run in an `hotshot`_ session and
-store the results in the specified file.
-
-.. _hotshot: http://docs.python.org/library/hotshot.html#module-hotshot
-
-Last but no least, if you're using the PostgreSQL database backend, VACUUMing
-your database can significantly improve the performance of the queries (by
-updating the statistics used by the query optimizer). Nowadays, this is done
-automatically from time to time, but if you've just imported a large amount of
-data in your db, you will want to vacuum it (with the analyse option on). Read
-the documentation of your database for more information.
--- a/doc/book/en/devrepo/repo/hooks.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-.. -*- coding: utf-8 -*-
-.. _hooks:
-
-Hooks and Operations
-====================
-
-.. autodocstring:: cubicweb.server.hook
-
-
-Example using dataflow hooks
-----------------------------
-
-We will use a very simple example to show hooks usage. Let us start with the
-following schema.
-
-.. sourcecode:: python
-
-   class Person(EntityType):
-       age = Int(required=True)
-
-We would like to add a range constraint over a person's age. Let's write an hook
-(supposing yams can not handle this nativly, which is wrong). It shall be placed
-into `mycube/hooks.py`. If this file were to grow too much, we can easily have a
-`mycube/hooks/... package` containing hooks in various modules.
-
-.. sourcecode:: python
-
-   from cubicweb import ValidationError
-   from cubicweb.predicates import is_instance
-   from cubicweb.server.hook import Hook
-
-   class PersonAgeRange(Hook):
-        __regid__ = 'person_age_range'
-        __select__ = Hook.__select__ & is_instance('Person')
-        events = ('before_add_entity', 'before_update_entity')
-
-        def __call__(self):
-	    if 'age' in self.entity.cw_edited:
-                if 0 <= self.entity.age <= 120:
-                   return
-		msg = self._cw._('age must be between 0 and 120')
-		raise ValidationError(self.entity.eid, {'age': msg})
-
-In our example the base `__select__` is augmented with an `is_instance` selector
-matching the desired entity type.
-
-The `events` tuple is used specify that our hook should be called before the
-entity is added or updated.
-
-Then in the hook's `__call__` method, we:
-
-* check if the 'age' attribute is edited
-* if so, check the value is in the range
-* if not, raise a validation error properly
-
-Now Let's augment our schema with new `Company` entity type with some relation to
-`Person` (in 'mycube/schema.py').
-
-.. sourcecode:: python
-
-   class Company(EntityType):
-        name = String(required=True)
-        boss = SubjectRelation('Person', cardinality='1*')
-        subsidiary_of = SubjectRelation('Company', cardinality='*?')
-
-
-We would like to constrain the company's bosses to have a minimum (legal)
-age. Let's write an hook for this, which will be fired when the `boss` relation
-is established (still supposing we could not specify that kind of thing in the
-schema).
-
-.. sourcecode:: python
-
-   class CompanyBossLegalAge(Hook):
-        __regid__ = 'company_boss_legal_age'
-        __select__ = Hook.__select__ & match_rtype('boss')
-        events = ('before_add_relation',)
-
-        def __call__(self):
-            boss = self._cw.entity_from_eid(self.eidto)
-            if boss.age < 18:
-                msg = self._cw._('the minimum age for a boss is 18')
-                raise ValidationError(self.eidfrom, {'boss': msg})
-
-.. Note::
-
-    We use the :class:`~cubicweb.server.hook.match_rtype` selector to select the
-    proper relation type.
-
-    The essential difference with respect to an entity hook is that there is no
-    self.entity, but `self.eidfrom` and `self.eidto` hook attributes which
-    represent the subject and object **eid** of the relation.
-
-Suppose we want to check that there is no cycle by the `subsidiary_of`
-relation. This is best achieved in an operation since all relations are likely to
-be set at commit time.
-
-.. sourcecode:: python
-
-    from cubicweb.server.hook import Hook, DataOperationMixIn, Operation, match_rtype
-
-    def check_cycle(self, session, eid, rtype, role='subject'):
-        parents = set([eid])
-        parent = session.entity_from_eid(eid)
-        while parent.related(rtype, role):
-            parent = parent.related(rtype, role)[0]
-            if parent.eid in parents:
-                msg = session._('detected %s cycle' % rtype)
-                raise ValidationError(eid, {rtype: msg})
-            parents.add(parent.eid)
-
-
-    class CheckSubsidiaryCycleOp(Operation):
-
-        def precommit_event(self):
-            check_cycle(self.session, self.eidto, 'subsidiary_of')
-
-
-    class CheckSubsidiaryCycleHook(Hook):
-        __regid__ = 'check_no_subsidiary_cycle'
-        __select__ = Hook.__select__ & match_rtype('subsidiary_of')
-        events = ('after_add_relation',)
-
-        def __call__(self):
-            CheckSubsidiaryCycleOp(self._cw, eidto=self.eidto)
-
-
-Like in hooks, :exc:`~cubicweb.ValidationError` can be raised in operations. Other
-exceptions are usually programming errors.
-
-In the above example, our hook will instantiate an operation each time the hook
-is called, i.e. each time the `subsidiary_of` relation is set. There is an
-alternative method to schedule an operation from a hook, using the
-:func:`get_instance` class method.
-
-.. sourcecode:: python
-
-   from cubicweb.server.hook import set_operation
-
-   class CheckSubsidiaryCycleHook(Hook):
-       __regid__ = 'check_no_subsidiary_cycle'
-       events = ('after_add_relation',)
-       __select__ = Hook.__select__ & match_rtype('subsidiary_of')
-
-       def __call__(self):
-           CheckSubsidiaryCycleOp.get_instance(self._cw).add_data(self.eidto)
-
-   class CheckSubsidiaryCycleOp(DataOperationMixIn, Operation):
-
-       def precommit_event(self):
-           for eid in self.get_data():
-               check_cycle(self.session, eid, self.rtype)
-
-
-Here, we call :func:`set_operation` so that we will simply accumulate eids of
-entities to check at the end in a single `CheckSubsidiaryCycleOp`
-operation. Value are stored in a set associated to the
-'subsidiary_cycle_detection' transaction data key. The set initialization and
-operation creation are handled nicely by :func:`set_operation`.
-
-A more realistic example can be found in the advanced tutorial chapter
-:ref:`adv_tuto_security_propagation`.
-
-
-Inter-instance communication
-----------------------------
-
-If your application consists of several instances, you may need some means to
-communicate between them.  Cubicweb provides a publish/subscribe mechanism
-using ØMQ_.  In order to use it, use
-:meth:`~cubicweb.server.cwzmq.ZMQComm.add_subscription` on the
-`repo.app_instances_bus` object.  The `callback` will get the message (as a
-list).  A message can be sent by calling
-:meth:`~cubicweb.server.cwzmq.ZMQComm.publish` on `repo.app_instances_bus`.
-The first element of the message is the topic which is used for filtering and
-dispatching messages.
-
-.. _ØMQ: http://www.zeromq.org/
-
-.. sourcecode:: python
-
-  class FooHook(hook.Hook):
-      events = ('server_startup',)
-      __regid__ = 'foo_startup'
-
-      def __call__(self):
-          def callback(msg):
-              self.info('received message: %s', ' '.join(msg))
-          self.repo.app_instances_bus.add_subscription('hello', callback)
-
-.. sourcecode:: python
-
-  def do_foo(self):
-      actually_do_foo()
-      self._cw.repo.app_instances_bus.publish(['hello', 'world'])
-
-The `zmq-address-pub` configuration variable contains the address used
-by the instance for sending messages, e.g. `tcp://*:1234`.  The
-`zmq-address-sub` variable contains a comma-separated list of addresses
-to listen on, e.g. `tcp://localhost:1234, tcp://192.168.1.1:2345`.
-
-
-Hooks writing tips
-------------------
-
-Reminder
-~~~~~~~~
-
-You should never use the `entity.foo = 42` notation to update an entity. It will
-not do what you expect (updating the database). Instead, use the
-:meth:`~cubicweb.entity.Entity.cw_set` method or direct access to entity's
-:attr:`cw_edited` attribute if you're writing a hook for 'before_add_entity' or
-'before_update_entity' event.
-
-
-How to choose between a before and an after event ?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-`before_*` hooks give you access to the old attribute (or relation)
-values. You can also intercept and update edited values in the case of
-entity modification before they reach the database.
-
-Else the question is: should I need to do things before or after the actual
-modification ? If the answer is "it doesn't matter", use an 'after' event.
-
-
-Validation Errors
-~~~~~~~~~~~~~~~~~
-
-When a hook which is responsible to maintain the consistency of the
-data model detects an error, it must use a specific exception named
-:exc:`~cubicweb.ValidationError`. Raising anything but a (subclass of)
-:exc:`~cubicweb.ValidationError` is a programming error. Raising it
-entails aborting the current transaction.
-
-This exception is used to convey enough information up to the user
-interface. Hence its constructor is different from the default Exception
-constructor. It accepts, positionally:
-
-* an entity eid (**not the entity itself**),
-
-* a dict whose keys represent attribute (or relation) names and values
-  an end-user facing message (hence properly translated) relating the
-  problem.
-
-.. sourcecode:: python
-
-  raise ValidationError(earth.eid, {'sea_level': self._cw._('too high'),
-                                    'temperature': self._cw._('too hot')})
-
-
-Checking for object created/deleted in the current transaction
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In hooks, you can use the
-:meth:`~cubicweb.server.session.Session.added_in_transaction` or
-:meth:`~cubicweb.server.session.Session.deleted_in_transaction` of the session
-object to check if an eid has been created or deleted during the hook's
-transaction.
-
-This is useful to enable or disable some stuff if some entity is being added or
-deleted.
-
-.. sourcecode:: python
-
-   if self._cw.deleted_in_transaction(self.eidto):
-      return
-
-
-Peculiarities of inlined relations
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Relations which are defined in the schema as `inlined` (see :ref:`RelationType`
-for details) are inserted in the database at the same time as entity attributes.
-
-This may have some side effect, for instance when creating an entity
-and setting an inlined relation in the same rql query, then at
-`before_add_relation` time, the relation will already exist in the
-database (it is otherwise not the case).
--- a/doc/book/en/devrepo/repo/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Repository customization
-++++++++++++++++++++++++
-.. toctree::
-   :maxdepth: 1
-
-   sessions
-   hooks
-   notifications
-   tasks
-
-
--- a/doc/book/en/devrepo/repo/notifications.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Notifications management
-========================
-
-CubicWeb provides a machinery to ease notifications handling. To use it for a
-notification:
-
-* write a view inheriting from
-  :class:`~cubicweb.sobjects.notification.NotificationView`.  The usual view api
-  is used to generated the email (plain text) content, and additional
-  :meth:`~cubicweb.sobjects.notification.NotificationView.subject` and
-  :meth:`~cubicweb.sobjects.notification.NotificationView.recipients` methods
-  are used to build the email's subject and
-  recipients. :class:`NotificationView` provides default implementation for both
-  methods.
-
-* write a hook for event that should trigger this notification, select the view
-  (without rendering it), and give it to
-  :func:`cubicweb.hooks.notification.notify_on_commit` so that the notification
-  will be sent if the transaction succeed.
-
-
-.. XXX explain recipient finder and provide example
-
-API details
-~~~~~~~~~~~
-.. autoclass:: cubicweb.sobjects.notification.NotificationView
-.. autofunction:: cubicweb.hooks.notification.notify_on_commit
--- a/doc/book/en/devrepo/repo/sessions.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,318 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Sessions
-========
-
-Sessions are objects linked to an authenticated user.  The `Session.new_cnx`
-method returns a new Connection linked to that session.
-
-Connections
-===========
-
-Connections provide the `.execute` method to query the data sources, along with
-`.commit` and `.rollback` methods for transaction management.
-
-Kinds of connections
---------------------
-
-There are two kinds of connections.
-
-* `normal connections` are the most common: they are related to users and
-  carry security checks coming with user credentials
-
-* `internal connections` have all the powers; they are also used in only a
-  few situations where you don't already have an adequate session at
-  hand, like: user authentication, data synchronisation in
-  multi-source contexts
-
-Normal connections are typically named `_cw` in most appobjects or
-sometimes just `session`.
-
-Internal connections are available from the `Repository` object and are
-to be used like this:
-
-.. sourcecode:: python
-
-   with self.repo.internal_cnx() as cnx:
-       do_stuff_with(cnx)
-       cnx.commit()
-
-Connections should always be used as context managers, to avoid leaks.
-
-
-Python/RQL API
-~~~~~~~~~~~~~~
-
-The Python API developped to interface with RQL is inspired from the standard db-api,
-but since `execute` returns its results directly, there is no `cursor` concept.
-
-.. sourcecode:: python
-
-   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
-
-The `Connection` object owns the methods `commit` and `rollback`. You
-*should never need to use them* during the development of the web
-interface based on the *CubicWeb* framework as it determines the end
-of the transaction depending on the query execution success. They are
-however useful in other contexts such as tests or custom controllers.
-
-.. note::
-
-  If a query generates an error related to security (:exc:`Unauthorized`) or to
-  integrity (:exc:`ValidationError`), the transaction can still continue but you
-  won't be able to commit it, a rollback will be necessary to start a new
-  transaction.
-
-  Also, a rollback is automatically done if an error occurs during commit.
-
-.. note::
-
-   A :exc:`ValidationError` has a `entity` attribute. In CubicWeb,
-   this atttribute is set to the entity's eid (not a reference to the
-   entity itself).
-
-Executing RQL queries from a view or a hook
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When you're within code of the web interface, the Connection is 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 request object (since
-you're directly inside the data-server), so you'll have to use the execute method
-of the Connection object.
-
-Proper usage of `.execute`
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Let's say you want to get T which is in configuration C, this translates to:
-
-.. sourcecode:: python
-
-   self._cw.execute('Any T WHERE T in_conf C, C eid %s' % entity.eid)
-
-But it must be written in a syntax that will benefit from the use
-of a cache on the RQL server side:
-
-.. sourcecode:: python
-
-   self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid})
-
-The syntax tree is built once for the "generic" RQL and can be re-used
-with a number of different eids.  The rql IN operator is an exception
-to this rule.
-
-.. sourcecode:: python
-
-   self._cw.execute('Any T WHERE T in_conf C, C name IN (%s)'
-                    % ','.join(['foo', 'bar']))
-
-Alternatively, some of the common data related to an entity can be
-obtained from the `entity.related()` method (which is used under the
-hood by the ORM when you use attribute access notation on an entity to
-get a relation. The initial request would then be translated to:
-
-.. sourcecode:: python
-
-   entity.related('in_conf', 'object')
-
-Additionally this benefits from the fetch_attrs policy (see :ref:`FetchAttrs`)
-optionally defined on the class element, which says which attributes must be
-also loaded when the entity is loaded through the ORM.
-
-.. _resultset:
-
-The `ResultSet` API
-~~~~~~~~~~~~~~~~~~~
-
-ResultSet instances are a very commonly manipulated object. They have
-a rich API as seen below, but we would like to highlight a bunch of
-methods that are quite useful in day-to-day practice:
-
-* `__str__()` (applied by `print`) gives a very useful overview of both
-  the underlying RQL expression and the data inside; unavoidable for
-  debugging purposes
-
-* `printable_rql()` returns a well formed RQL expression as a
-  string; it is very useful to build views
-
-* `entities()` returns a generator on all entities of the result set
-
-* `get_entity(row, col)` gets the entity at row, col coordinates; one
-  of the most used result set methods
-
-.. autoclass:: cubicweb.rset.ResultSet
-   :members:
-
-
-Authentication and management of sessions
------------------------------------------
-
-The authentication process is a ballet involving a few dancers:
-
-* through its `get_session` method the top-level application object (the
-  `CubicWebPublisher`) will open a session whenever a web request
-  comes in; it asks the `session manager` to open a session (giving
-  the web request object as context) using `open_session`
-
-  * the session manager asks its authentication manager (which is a
-    `component`) to authenticate the request (using `authenticate`)
-
-    * the authentication manager asks, in order, to its authentication
-      information retrievers, a login and an opaque object containing
-      other credentials elements (calling `authentication_information`),
-      giving the request object each time
-
-      * the default retriever (named `LoginPasswordRetriever`)
-        will in turn defer login and password fetching to the request
-        object (which, depending on the authentication mode (`cookie`
-        or `http`), will do the appropriate things and return a login
-        and a password)
-
-    * the authentication manager, on success, asks the `Repository`
-      object to connect with the found credentials (using `connect`)
-
-      * the repository object asks authentication to all of its
-        sources which support the `CWUser` entity with the given
-        credentials; when successful it can build the cwuser entity,
-        from which a regular `Session` object is made; it returns the
-        session id
-
-        * the source in turn will delegate work to an authentifier
-          class that defines the ultimate `authenticate` method (for
-          instance the native source will query the database against
-          the provided credentials)
-
-    * the authentication manager, on success, will call back _all_
-      retrievers with `authenticated` and return its authentication
-      data (on failure, it will try the anonymous login or, if the
-      configuration forbids it, raise an `AuthenticationError`)
-
-Writing authentication plugins
-------------------------------
-
-Sometimes CubicWeb's out-of-the-box authentication schemes (cookie and
-http) are not sufficient. Nowadays there is a plethora of such schemes
-and the framework cannot provide them all, but as the sequence above
-shows, it is extensible.
-
-Two levels have to be considered when writing an authentication
-plugin: the web client and the repository.
-
-We invented a scenario where it makes sense to have a new plugin in
-each side: some middleware will do pre-authentication and under the
-right circumstances add a new HTTP `x-foo-user` header to the query
-before it reaches the CubicWeb instance. For a concrete example of
-this, see the `trustedauth`_ cube.
-
-.. _`trustedauth`: http://www.cubicweb.org/project/cubicweb-trustedauth
-
-Repository authentication plugins
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-On the repository side, it is possible to register a source
-authentifier using the following kind of code:
-
-.. sourcecode:: python
-
- from cubicweb.server.sources import native
-
- class FooAuthentifier(native.LoginPasswordAuthentifier):
-     """ a source authentifier plugin
-     if 'foo' in authentication information, no need to check
-     password
-     """
-     auth_rql = 'Any X WHERE X is CWUser, X login %(login)s'
-
-     def authenticate(self, session, login, **kwargs):
-         """return CWUser eid for the given login
-         if this account is defined in this source,
-         else raise `AuthenticationError`
-         """
-         session.debug('authentication by %s', self.__class__.__name__)
-         if 'foo' not in kwargs:
-             return super(FooAuthentifier, self).authenticate(session, login, **kwargs)
-         try:
-             rset = session.execute(self.auth_rql, {'login': login})
-             return rset[0][0]
-         except Exception, exc:
-             session.debug('authentication failure (%s)', exc)
-         raise AuthenticationError('foo user is unknown to us')
-
-Since repository authentifiers are not appobjects, we have to register
-them through a `server_startup` hook.
-
-.. sourcecode:: python
-
- class ServerStartupHook(hook.Hook):
-     """ register the foo authenticator """
-     __regid__ = 'fooauthenticatorregisterer'
-     events = ('server_startup',)
-
-     def __call__(self):
-         self.debug('registering foo authentifier')
-         self.repo.system_source.add_authentifier(FooAuthentifier())
-
-Web authentication plugins
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. sourcecode:: python
-
- class XFooUserRetriever(authentication.LoginPasswordRetriever):
-     """ authenticate by the x-foo-user http header
-     or just do normal login/password authentication
-     """
-     __regid__ = 'x-foo-user'
-     order = 0
-
-     def authentication_information(self, req):
-         """retrieve authentication information from the given request, raise
-         NoAuthInfo if expected information is not found
-         """
-         self.debug('web authenticator building auth info')
-         try:
-            login = req.get_header('x-foo-user')
-            if login:
-                return login, {'foo': True}
-            else:
-                return super(XFooUserRetriever, self).authentication_information(self, req)
-         except Exception, exc:
-            self.debug('web authenticator failed (%s)', exc)
-         raise authentication.NoAuthInfo()
-
-     def authenticated(self, retriever, req, cnx, login, authinfo):
-         """callback when return authentication information have opened a
-         repository connection successfully. Take care req has no session
-         attached yet, hence req.execute isn't available.
-
-         Here we set a flag on the request to indicate that the user is
-         foo-authenticated. Can be used by a selector
-         """
-         self.debug('web authenticator running post authentication callback')
-         cnx.foo_user = authinfo.get('foo')
-
-In the `authenticated` method we add (in an admitedly slightly hackish
-way) an attribute to the connection object. This, in turn, can be used
-to build a selector dispatching on the fact that the user was
-preauthenticated or not.
-
-.. sourcecode:: python
-
- @objectify_selector
- def foo_authenticated(cls, req, rset=None, **kwargs):
-     if hasattr(req.cnx, 'foo_user') and req.foo_user:
-         return 1
-     return 0
-
-Full Session and Connection API
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. autoclass:: cubicweb.server.session.Session
-.. autoclass:: cubicweb.server.session.Connection
--- a/doc/book/en/devrepo/repo/tasks.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Tasks
-=========
-
-[WRITE ME]
-
-* repository tasks
-
--- a/doc/book/en/devrepo/testing.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,559 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Tests
-=====
-
-Unit tests
-----------
-
-The *CubicWeb* framework provides the
-:class:`cubicweb.devtools.testlib.CubicWebTC` test base class .
-
-Tests shall be put into the mycube/test directory. Additional test
-data shall go into mycube/test/data.
-
-It is much advised to write tests concerning entities methods,
-actions, hooks and operations, security. The
-:class:`~cubicweb.devtools.testlib.CubicWebTC` base class has
-convenience methods to help test all of this.
-
-In the realm of views, automatic tests check that views are valid
-XHTML. See :ref:`automatic_views_tests` for details.
-
-Most unit tests need a live database to work against. This is achieved
-by CubicWeb using automatically sqlite (bundled with Python, see
-http://docs.python.org/library/sqlite3.html) as a backend.
-
-The database is stored in the mycube/test/tmpdb,
-mycube/test/tmpdb-template files. If it does not (yet) exist, it will
-be built automatically when the test suite starts.
-
-.. warning::
-
-  Whenever the schema changes (new entities, attributes, relations)
-  one must delete these two files. Changes concerned only with entity
-  or relation type properties (constraints, cardinalities,
-  permissions) and generally dealt with using the
-  `sync_schema_props_perms()` function of the migration environment do
-  not need a database regeneration step.
-
-.. _hook_test:
-
-Unit test by example
-````````````````````
-
-We start with an example extracted from the keyword cube (available
-from http://www.cubicweb.org/project/cubicweb-keyword).
-
-.. sourcecode:: python
-
-    from cubicweb.devtools.testlib import CubicWebTC
-    from cubicweb import ValidationError
-
-    class ClassificationHooksTC(CubicWebTC):
-
-        def setup_database(self):
-            with self.admin_access.repo_cnx() as cnx:
-                group_etype = cnx.find('CWEType', name='CWGroup').one()
-                c1 = cnx.create_entity('Classification', name=u'classif1',
-                                       classifies=group_etype)
-                user_etype = cnx.find('CWEType', name='CWUser').one()
-                c2 = cnx.create_entity('Classification', name=u'classif2',
-                                       classifies=user_etype)
-                self.kw1eid = cnx.create_entity('Keyword', name=u'kwgroup', included_in=c1).eid
-                cnx.commit()
-
-        def test_cannot_create_cycles(self):
-            with self.admin_access.repo_cnx() as cnx:
-                kw1 = cnx.entity_from_eid(self.kw1eid)
-                # direct obvious cycle
-                with self.assertRaises(ValidationError):
-                    kw1.cw_set(subkeyword_of=kw1)
-                cnx.rollback()
-                # testing indirect cycles
-                kw3 = cnx.execute('INSERT Keyword SK: SK name "kwgroup2", SK included_in C, '
-                                  'SK subkeyword_of K WHERE C name "classif1", K eid %(k)s'
-                                  {'k': kw1}).get_entity(0,0)
-                kw3.cw_set(reverse_subkeyword_of=kw1)
-                self.assertRaises(ValidationError, cnx.commit)
-
-The test class defines a :meth:`setup_database` method which populates the
-database with initial data. Each test of the class runs with this
-pre-populated database.
-
-The test case itself checks that an Operation does its job of
-preventing cycles amongst Keyword entities.
-
-The `create_entity` method of connection (or request) objects allows
-to create an entity. You can link this entity to other entities, by
-specifying as argument, the relation name, and the entity to link, as
-value. In the above example, the `Classification` entity is linked to
-a `CWEtype` via the relation `classifies`. Conversely, if you are
-creating a `CWEtype` entity, you can link it to a `Classification`
-entity, by adding `reverse_classifies` as argument.
-
-.. note::
-
-   the :meth:`commit` method is not called automatically. You have to
-   call it explicitly if needed (notably to test operations). It is a
-   good practice to regenerate entities with :meth:`entity_from_eid`
-   after a commit to avoid request cache effects.
-
-You can see an example of security tests in the
-:ref:`adv_tuto_security`.
-
-It is possible to have these tests run continuously using `apycot`_.
-
-.. _apycot: http://www.cubicweb.org/project/apycot
-
-.. _securitytest:
-
-Managing connections or users
-+++++++++++++++++++++++++++++
-
-Since unit tests are done with the SQLITE backend and this does not
-support multiple connections at a time, you must be careful when
-simulating security, changing users.
-
-By default, tests run with a user with admin privileges. Connections
-using these credentials are accessible through the `admin_access` object
-of the test classes.
-
-The `repo_cnx()` method returns a connection object that can be used as a
-context manager:
-
-.. sourcecode:: python
-
-   # admin_access is a pre-cooked session wrapping object
-   # it is built with:
-   # self.admin_access = self.new_access('admin')
-   with self.admin_access.repo_cnx() as cnx:
-       cnx.execute(...)
-       self.create_user(cnx, login='user1')
-       cnx.commit()
-
-   user1access = self.new_access('user1')
-   with user1access.web_request() as req:
-       req.execute(...)
-       req.cnx.commit()
-
-On exit of the context manager, a rollback is issued, which releases
-the connection. Don't forget to issue the `cnx.commit()` calls!
-
-.. warning::
-
-   Do not use references kept to the entities created with a
-   connection from another one!
-
-Email notifications tests
-`````````````````````````
-
-When running tests, potentially generated e-mails are not really sent
-but are found in the list `MAILBOX` of module
-:mod:`cubicweb.devtools.testlib`.
-
-You can test your notifications by analyzing the contents of this list, which
-contains objects with two attributes:
-
-* `recipients`, the list of recipients
-* `msg`, email.Message object
-
-Let us look at a simple example from the ``blog`` cube.
-
-.. sourcecode:: python
-
-    from cubicweb.devtools.testlib import CubicWebTC, MAILBOX
-
-    class BlogTestsCubicWebTC(CubicWebTC):
-        """test blog specific behaviours"""
-
-        def test_notifications(self):
-            with self.admin_access.web_request() as req:
-                cubicweb_blog = req.create_entity('Blog', title=u'cubicweb',
-                                    description=u'cubicweb is beautiful')
-                blog_entry_1 = req.create_entity('BlogEntry', title=u'hop',
-                                                 content=u'cubicweb hop')
-                blog_entry_1.cw_set(entry_of=cubicweb_blog)
-                blog_entry_2 = req.create_entity('BlogEntry', title=u'yes',
-                                                 content=u'cubicweb yes')
-                blog_entry_2.cw_set(entry_of=cubicweb_blog)
-                self.assertEqual(len(MAILBOX), 0)
-                req.cnx.commit()
-                self.assertEqual(len(MAILBOX), 2)
-                mail = MAILBOX[0]
-                self.assertEqual(mail.subject, '[data] hop')
-                mail = MAILBOX[1]
-                self.assertEqual(mail.subject, '[data] yes')
-
-Visible actions tests
-`````````````````````
-
-It is easy to write unit tests to test actions which are visible to
-a user or to a category of users. Let's take an example in the
-`conference cube`_.
-
-.. _`conference cube`: http://www.cubicweb.org/project/cubicweb-conference
-.. sourcecode:: python
-
-    class ConferenceActionsTC(CubicWebTC):
-
-        def setup_database(self):
-            with self.admin_access.repo_cnx() as cnx:
-                self.confeid = cnx.create_entity('Conference',
-                                                 title=u'my conf',
-                                                 url_id=u'conf',
-                                                 start_on=date(2010, 1, 27),
-                                                 end_on = date(2010, 1, 29),
-                                                 call_open=True,
-                                                 reverse_is_chair_at=chair,
-                                                 reverse_is_reviewer_at=reviewer).eid
-
-        def test_admin(self):
-            with self.admin_access.web_request() as req:
-                rset = req.find('Conference').one()
-                self.assertListEqual(self.pactions(req, rset),
-                                      [('workflow', workflow.WorkflowActions),
-                                       ('edit', confactions.ModifyAction),
-                                       ('managepermission', actions.ManagePermissionsAction),
-                                       ('addrelated', actions.AddRelatedActions),
-                                       ('delete', actions.DeleteAction),
-                                       ('generate_badge_action', badges.GenerateBadgeAction),
-                                       ('addtalkinconf', confactions.AddTalkInConferenceAction)
-                                       ])
-                self.assertListEqual(self.action_submenu(req, rset, 'addrelated'),
-                                      [(u'add Track in_conf Conference object',
-                                        u'http://testing.fr/cubicweb/add/Track'
-                                        u'?__linkto=in_conf%%3A%(conf)s%%3Asubject&'
-                                        u'__redirectpath=conference%%2Fconf&'
-                                        u'__redirectvid=' % {'conf': self.confeid}),
-                                       ])
-
-You just have to execute a rql query corresponding to the view you want to test,
-and to compare the result of
-:meth:`~cubicweb.devtools.testlib.CubicWebTC.pactions` with the list of actions
-that must be visible in the interface. This is a list of tuples. The first
-element is the action's `__regid__`, the second the action's class.
-
-To test actions in a submenu, you just have to test the result of
-:meth:`~cubicweb.devtools.testlib.CubicWebTC.action_submenu` method. The last
-parameter of the method is the action's category. The result is a list of
-tuples. The first element is the action's title, and the second element the
-action's url.
-
-
-.. _automatic_views_tests:
-
-Automatic views testing
------------------------
-
-This is done automatically with the :class:`cubicweb.devtools.testlib.AutomaticWebTest`
-class. At cube creation time, the mycube/test/test_mycube.py file
-contains such a test. The code here has to be uncommented to be
-usable, without further modification.
-
-The ``auto_populate`` method uses a smart algorithm to create
-pseudo-random data in the database, thus enabling the views to be
-invoked and tested.
-
-Depending on the schema, hooks and operations constraints, it is not
-always possible for the automatic auto_populate to proceed.
-
-It is possible of course to completely redefine auto_populate. A
-lighter solution is to give hints (fill some class attributes) about
-what entities and relations have to be skipped by the auto_populate
-mechanism. These are:
-
-* `no_auto_populate`, may contain a list of entity types to skip
-* `ignored_relations`, may contain a list of relation types to skip
-* `application_rql`, may contain a list of rql expressions that
-  auto_populate cannot guess by itself; these must yield resultsets
-  against which views may be selected.
-
-.. warning::
-
-  Take care to not let the imported `AutomaticWebTest` in your test module
-  namespace, else both your subclass *and* this parent class will be run.
-
-Cache heavy database setup
--------------------------------
-
-Some test suites require a complex setup of the database that takes
-seconds (or even minutes) to complete. Doing the whole setup for each
-individual test makes the whole run very slow. The ``CubicWebTC``
-class offer a simple way to prepare a specific database once for
-multiple tests. The `test_db_id` class attribute of your
-``CubicWebTC`` subclass must be set to a unique identifier and the
-:meth:`pre_setup_database` class method must build the cached content. As
-the :meth:`pre_setup_database` method is not garanteed to be called
-every time a test method is run, you must not set any class attribute
-to be used during test *there*. Databases for each `test_db_id` are
-automatically created if not already in cache. Clearing the cache is
-up to the user. Cache files are found in the :file:`data/database`
-subdirectory of your test directory.
-
-.. warning::
-
-  Take care to always have the same :meth:`pre_setup_database`
-  function for all classes with a given `test_db_id` otherwise your
-  tests will have unpredictable results depending on the first
-  encountered one.
-
-
-Testing on a real-life database
--------------------------------
-
-The ``CubicWebTC`` class uses the `cubicweb.devtools.ApptestConfiguration`
-configuration class to setup its testing environment (database driver,
-user password, application home, and so on). The `cubicweb.devtools`
-module also provides a `RealDatabaseConfiguration`
-class that will read a regular cubicweb sources file to fetch all
-this information but will also prevent the database to be initalized
-and reset between tests.
-
-For a test class to use a specific configuration, you have to set
-the `_config` class attribute on the class as in:
-
-.. sourcecode:: python
-
-    from cubicweb.devtools import RealDatabaseConfiguration
-    from cubicweb.devtools.testlib import CubicWebTC
-
-    class BlogRealDatabaseTC(CubicWebTC):
-        _config = RealDatabaseConfiguration('blog',
-                                            sourcefile='/path/to/realdb_sources')
-
-        def test_blog_rss(self):
-            with self.admin_access.web_request() as req:
-            rset = req.execute('Any B ORDERBY D DESC WHERE B is BlogEntry, '
-                               'B created_by U, U login "logilab", B creation_date D')
-            self.view('rss', rset, req=req)
-
-
-Testing with other cubes
-------------------------
-
-Sometimes a small component cannot be tested all by itself, so one
-needs to specify other cubes to be used as part of the the unit test
-suite. This is handled by the ``bootstrap_cubes`` file located under
-``mycube/test/data``. One example from the `preview` cube::
-
- card, file, preview
-
-The format is:
-
-* possibly several empy lines or lines starting with ``#`` (comment lines)
-* one line containing a comma-separated list of cube names.
-
-It is also possible to add a ``schema.py`` file in
-``mycube/test/data``, which will be used by the testing framework,
-therefore making new entity types and relations available to the
-tests. 
-
-Literate programming
---------------------
-
-CubicWeb provides some literate programming capabilities. The :ref:`cubicweb-ctl`
-`shell` command accepts different file formats. If your file ends with `.txt`
-or `.rst`, the file will be parsed by :mod:`doctest.testfile` with CubicWeb's
-:ref:`migration` API enabled in it.
-
-Create a `scenario.txt` file in the `test/` directory and fill with some content.
-Refer to the :mod:`doctest.testfile` `documentation`_.
-
-.. _documentation: http://docs.python.org/library/doctest.html
-
-Then, you can run it directly by::
-
-    $ cubicweb-ctl shell <cube_instance> test/scenario.txt
-
-When your scenario file is ready, put it in a new test case to be able to run
-it automatically.
-
-.. sourcecode:: python
-
-      from os.path import dirname, join
-      from logilab.common.testlib import unittest_main
-      from cubicweb.devtools.testlib import CubicWebTC
-
-      class AcceptanceTC(CubicWebTC):
-
-              def test_scenario(self):
-                      self.assertDocTestFile(join(dirname(__file__), 'scenario.txt'))
-
-      if __name__ == '__main__':
-              unittest_main()
-
-Skipping a scenario
-```````````````````
-
-If you want to set up initial conditions that you can't put in your unit test
-case, you have to use a :exc:`KeyboardInterrupt` exception only because of the
-way :mod:`doctest` module will catch all the exceptions internally.
-
-    >>> if condition_not_met:
-    ...     raise KeyboardInterrupt('please, check your fixture.')
-
-Passing paramaters
-``````````````````
-Using extra arguments to parametrize your scenario is possible by prepending them
-by double dashes.
-
-Please refer to the `cubicweb-ctl shell --help` usage.
-
-.. important::
-    Your scenario file must be utf-8 encoded.
-
-Test APIS
----------
-
-Using Pytest
-````````````
-
-The `pytest` utility (shipping with `logilab-common`_, which is a
-mandatory dependency of CubicWeb) extends the Python unittest
-functionality and is the preferred way to run the CubicWeb test
-suites. Bare unittests also work the usual way.
-
-.. _logilab-common: http://www.logilab.org/project/logilab-common
-
-To use it, you may:
-
-* just launch `pytest` in your cube to execute all tests (it will
-  discover them automatically)
-* launch `pytest unittest_foo.py` to execute one test file
-* launch `pytest unittest_foo.py bar` to execute all test methods and
-  all test cases whose name contains `bar`
-
-Additionally, the `-x` option tells pytest to exit at the first error
-or failure. The `-i` option tells pytest to drop into pdb whenever an
-exception occurs in a test.
-
-When the `-x` option has been used and the run stopped on a test, it
-is possible, after having fixed the test, to relaunch pytest with the
-`-R` option to tell it to start testing again from where it previously
-failed.
-
-Using the `TestCase` base class
-```````````````````````````````
-
-The base class of CubicWebTC is logilab.common.testlib.TestCase, which
-provides a lot of convenient assertion methods.
-
-.. autoclass:: logilab.common.testlib.TestCase
-   :members:
-
-CubicWebTC API
-``````````````
-.. autoclass:: cubicweb.devtools.testlib.CubicWebTC
-   :members:
-
-
-What you need to know about request and session
------------------------------------------------
-
-.. image:: ../images/request_session.png
-
-First, remember to think that some code run on a client side, some
-other on the repository side. More precisely:
-
-* client side: web interface, raw repoapi connection (cubicweb-ctl shell for
-  instance);
-
-* repository side: RQL query execution, that may trigger hooks and operation.
-
-The client interacts with the repository through a repoapi connection.
-
-
-.. note::
-
-   These distinctions are going to disappear in cubicweb 3.21 (if not
-   before).
-
-A repoapi connection is tied to a session in the repository. The connection and
-request objects are inaccessible from repository code / the session object is
-inaccessible from client code (theoretically at least).
-
-The web interface provides a request class.  That `request` object provides
-access to all cubicweb resources, eg:
-
-* the registry (which itself provides access to the schema and the
-  configuration);
-
-* an underlying repoapi connection (when using req.execute, you actually call the
-  repoapi);
-
-* other specific resources depending on the client type (url generation according
-  to base url, form parameters, etc.).
-
-
-A `session` provides an api similar to a request regarding RQL execution and
-access to global resources (registry and all), but also has the following
-responsibilities:
-
-* handle transaction data, that will live during the time of a single
-  transaction. This includes the database connections that will be used to
-  execute RQL queries.
-
-* handle persistent data that may be used across different (web) requests
-
-* security and hooks control (not possible through a request)
-
-
-The `_cw` attribute
-```````````````````
-The `_cw` attribute available on every application object provides access to all
-cubicweb resources, i.e.:
-
-- For code running on the client side (eg web interface view), `_cw` is a request
-  instance.
-
-- For code running on the repository side (hooks and operation), `_cw` is a
-  Connection or Session instance.
-
-
-Beware some views may be called with a session (e.g. notifications) or with a
-request.
-
-
-Request, session and transaction
-````````````````````````````````
-
-In the web interface, an HTTP request is handled by a single request, which will
-be thrown away once the response is sent.
-
-The web publisher handles the transaction:
-
-* commit / rollback is done automatically
-
-* you should not commit / rollback explicitly, except if you really
-  need it
-
-Let's detail the process:
-
-1. an incoming RQL query comes from a client to the web stack
-
-2. the web stack opens an authenticated database connection for the
-   request, which is associated to a user session
-
-3. the query is executed (through the repository connection)
-
-4. this query may trigger hooks. Hooks and operations may execute some rql queries
-   through `cnx.execute`.
-
-5. the repository gets the result of the query in 1. If it was a RQL read query,
-   the database connection is released. If it was a write query, the connection
-   is then tied to the session until the transaction is commited or rolled back.
-
-6. results are sent back to the client
-
-This implies several things:
-
-* when using a request, or code executed in hooks, this database
-  connection handling is totally transparent
-
-* however, take care when writing tests: you are usually faking /
-  testing both the server and the client side, so you have to decide
-  when to use RepoAccess.client_cnx or RepoAccess.repo_cnx. Ask
-  yourself "where will the code I want to test be running, client or
-  repository side?". The response is usually: use a repo (since the
-  "client connection" concept is going away in a couple of releases).
--- a/doc/book/en/devrepo/vreg.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-The Registry, selectors and application objects
-===============================================
-
-This chapter deals with some of the  core concepts of the |cubicweb| framework
-which make it different from other frameworks (and maybe not easy to
-grasp at a first glance). To be able to do advanced development with
-|cubicweb| you need a good understanding of what is explained below.
-
-This chapter goes deep into details. You don't have to remember them
-all but keep it in mind so you can go back there later.
-
-An overview of AppObjects, the VRegistry and Selectors is given in the
-:ref:`VRegistryIntro` chapter.
-
-.. autodocstring:: cubicweb.cwvreg
-.. autodocstring:: cubicweb.predicates
-.. automodule:: cubicweb.appobject
-
-Base predicates
----------------
-
-Predicates are scoring functions that are called by the registry to tell whenever
-an appobject can be selected in a given context. Predicates may be chained
-together using operators to build a selector. A selector is the glue that tie
-views to the data model or whatever input context. Using them appropriately is an
-essential part of the construction of well behaved cubes.
-
-Of course you may have to write your own set of predicates as your needs grows
-and you get familiar with the framework (see :ref:`CustomPredicates`).
-
-Here is a description of generic predicates provided by CubicWeb that should suit
-most of your needs.
-
-Bare predicates
-~~~~~~~~~~~~~~~
-Those predicates are somewhat dumb, which doesn't mean they're not (very) useful.
-
-.. autoclass:: cubicweb.appobject.yes
-.. autoclass:: cubicweb.predicates.match_kwargs
-.. autoclass:: cubicweb.predicates.appobject_selectable
-.. autoclass:: cubicweb.predicates.adaptable
-.. autoclass:: cubicweb.predicates.configuration_values
-
-
-Result set predicates
-~~~~~~~~~~~~~~~~~~~~~
-Those predicates are looking for a result set in the context ('rset' argument or
-the input context) and match or not according to its shape. Some of these
-predicates have different behaviour if a particular cell of the result set is
-specified using 'row' and 'col' arguments of the input context or not.
-
-.. autoclass:: cubicweb.predicates.none_rset
-.. autoclass:: cubicweb.predicates.any_rset
-.. autoclass:: cubicweb.predicates.nonempty_rset
-.. autoclass:: cubicweb.predicates.empty_rset
-.. autoclass:: cubicweb.predicates.one_line_rset
-.. autoclass:: cubicweb.predicates.multi_lines_rset
-.. autoclass:: cubicweb.predicates.multi_columns_rset
-.. autoclass:: cubicweb.predicates.paginated_rset
-.. autoclass:: cubicweb.predicates.sorted_rset
-.. autoclass:: cubicweb.predicates.one_etype_rset
-.. autoclass:: cubicweb.predicates.multi_etypes_rset
-
-
-Entity predicates
-~~~~~~~~~~~~~~~~~
-Those predicates are looking for either an `entity` argument in the input context,
-or entity found in the result set ('rset' argument or the input context) and
-match or not according to entity's (instance or class) properties.
-
-.. autoclass:: cubicweb.predicates.non_final_entity
-.. autoclass:: cubicweb.predicates.is_instance
-.. autoclass:: cubicweb.predicates.score_entity
-.. autoclass:: cubicweb.predicates.rql_condition
-.. autoclass:: cubicweb.predicates.relation_possible
-.. autoclass:: cubicweb.predicates.partial_relation_possible
-.. autoclass:: cubicweb.predicates.has_related_entities
-.. autoclass:: cubicweb.predicates.partial_has_related_entities
-.. autoclass:: cubicweb.predicates.has_permission
-.. autoclass:: cubicweb.predicates.has_add_permission
-.. autoclass:: cubicweb.predicates.has_mimetype
-.. autoclass:: cubicweb.predicates.is_in_state
-.. autofunction:: cubicweb.predicates.on_fire_transition
-
-
-Logged user predicates
-~~~~~~~~~~~~~~~~~~~~~~
-Those predicates are looking for properties of the user issuing the request.
-
-.. autoclass:: cubicweb.predicates.match_user_groups
-
-
-Web request predicates
-~~~~~~~~~~~~~~~~~~~~~~
-Those predicates are looking for properties of *web* request, they can not be
-used on the data repository side.
-
-.. autoclass:: cubicweb.predicates.no_cnx
-.. autoclass:: cubicweb.predicates.anonymous_user
-.. autoclass:: cubicweb.predicates.authenticated_user
-.. autoclass:: cubicweb.predicates.match_form_params
-.. autoclass:: cubicweb.predicates.match_search_state
-.. autoclass:: cubicweb.predicates.match_context_prop
-.. autoclass:: cubicweb.predicates.match_context
-.. autoclass:: cubicweb.predicates.match_view
-.. autoclass:: cubicweb.predicates.primary_view
-.. autoclass:: cubicweb.predicates.contextual
-.. autoclass:: cubicweb.predicates.specified_etype_implements
-.. autoclass:: cubicweb.predicates.attribute_edited
-.. autoclass:: cubicweb.predicates.match_transition
-
-
-Other predicates
-~~~~~~~~~~~~~~~~
-.. autoclass:: cubicweb.predicates.match_exception
-.. autoclass:: cubicweb.predicates.debug_mode
-
-You'll also find some other (very) specific predicates hidden in other modules
-than :mod:`cubicweb.predicates`.
--- a/doc/book/en/devweb/ajax.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-.. _ajax:
-
-Ajax
-----
-
-CubicWeb provides a few helpers to facilitate *javascript <-> python* communications.
-
-You can, for instance, register some python functions that will become
-callable from javascript through ajax calls. All the ajax URLs are handled
-by the :class:`cubicweb.web.views.ajaxcontroller.AjaxController` controller.
-
-.. automodule:: cubicweb.web.views.ajaxcontroller
--- a/doc/book/en/devweb/controllers.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-.. _controllers:
-
-Controllers
------------
-
-Overview
-++++++++
-
-Controllers are responsible for taking action upon user requests
-(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. They are all defined in
-(:mod:`cubicweb.web.views.basecontrollers`).
-
-`Browsing`:
-
-* the View controller is associated with most browsing actions within a
-  CubicWeb application: it always instantiates a
-  :ref:`the_main_template_layout` and lets the ResultSet/Views dispatch system
-  build up the whole content; it handles :exc:`ObjectNotFound` and
-  :exc:`NoSelectableObject` errors that may bubble up to its entry point, in an
-  end-user-friendly way (but other programming errors will slip through)
-
-* the JSonpController is a wrapper around the ``ViewController`` that
-  provides jsonp_ services. Padding can be specified with the
-  ``callback`` request parameter. Only *jsonexport* / *ejsonexport*
-  views can be used. If another ``vid`` is specified, it will be
-  ignored and replaced by *jsonexport*. Request is anonymized
-  to avoid returning sensitive data and reduce the risks of CSRF attacks;
-
-* the Login/Logout controllers make effective user login or logout
-  requests
-
-
-.. _jsonp: http://en.wikipedia.org/wiki/JSONP
-
-`Edition`:
-
-* the Edit controller (see :ref:`edit_controller`) handles CRUD
-  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`` 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`:
-
-* the ``SendMail controller`` (web/views/basecontrollers.py) is reponsible
-  for outgoing email notifications
-
-* the MailBugReport controller (web/views/basecontrollers.py) allows
-  to quickly have a `reportbug` feature in one's application
-
-* the :class:`cubicweb.web.views.ajaxcontroller.AjaxController`
-  (:mod:`cubicweb.web.views.ajaxcontroller`) provides
-  services for Ajax calls, typically using JSON as a serialization format
-  for input, and sometimes using either JSON or XML for output. See
-  :ref:`ajax` chapter for more information.
-
-
-Registration
-++++++++++++
-
-All controllers (should) live in the 'controllers' namespace within
-the global registry.
-
-Concrete controllers
-++++++++++++++++++++
-
-Most API details should be resolved by source code inspection, as the
-various controllers have differing goals. See for instance the
-:ref:`edit_controller` chapter.
-
-:mod:`cubicweb.web.controller` contains the top-level abstract
-Controller class and its unimplemented entry point
-`publish(rset=None)` method.
-
-A handful of helpers are also provided there:
-
-* process_rql builds a result set from an rql query typically issued
-  from the browser (and available through _cw.form['rql'])
-
-* validate_cache will force cache validation handling with respect to
-  the HTTP Cache directives (that were typically originally issued
-  from a previous server -> client response); concrete Controller
-  implementations dealing with HTTP (thus, for instance, not the
-  SendMail controller) may very well call this in their publication
-  process.
--- a/doc/book/en/devweb/css.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-CSS Stylesheet
----------------
-Conventions
-~~~~~~~~~~~
-
-.. XXX external_resources variable
-..    naming convention
-..    request.add_css
-
-
-Extending / overriding existing styles
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-We cannot modify the order in which the application is reading the CSS. In
-the case we want to create new CSS style, the best is to define it a in a new
-CSS located under ``myapp/data/`` and use those new styles while writing
-customized views and templates.
-
-If you want to modify an existing CSS styling property, you will have to use
-``!important`` declaration to override the existing property. The application
-apply a higher priority on the default CSS and you can not change that.
-Customized CSS will not be read first.
-
-
-CubicWeb stylesheets
-~~~~~~~~~~~~~~~~~~~~
-
-.. XXX explain diffenrent files and main classes
--- a/doc/book/en/devweb/edition/dissection.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,316 +0,0 @@
-
-.. _form_dissection:
-
-Dissection of an entity form
-----------------------------
-
-This is done (again) with a vanilla instance of the `tracker`_
-cube. We will populate the database with a bunch of entities and see
-what kind of job the automatic entity form does.
-
-.. _`tracker`: http://www.cubicweb.org/project/cubicweb-tracker
-
-Populating the database
-~~~~~~~~~~~~~~~~~~~~~~~
-
-We should start by setting up a bit of context: a project with two
-unpublished versions, and a ticket linked to the project and the first
-version.
-
-.. sourcecode:: python
-
- >>> p = rql('INSERT Project P: P name "cubicweb"')
- >>> for num in ('0.1.0', '0.2.0'):
- ...  rql('INSERT Version V: V num "%s", V version_of P WHERE P eid %%(p)s' % num, {'p': p[0][0]})
- ...
- <resultset 'INSERT Version V: V num "0.1.0", V version_of P WHERE P eid %(p)s' (1 rows): [765L] (('Version',))>
- <resultset 'INSERT Version V: V num "0.2.0", V version_of P WHERE P eid %(p)s' (1 rows): [766L] (('Version',))>
- >>> t = rql('INSERT Ticket T: T title "let us write more doc", T done_in V, '
-             'T concerns P WHERE V num "0.1.0"', P eid %(p)s', {'p': p[0][0]})
- >>> commit()
-
-Now let's see what the edition form builds for us.
-
-.. sourcecode:: python
-
- >>> cnx.use_web_compatible_requests('http://fakeurl.com')
- >>> req = cnx.request()
- >>> form = req.vreg['forms'].select('edition', req, rset=rql('Ticket T'))
- >>> html = form.render()
-
-.. note::
-
-  In order to play interactively with web side application objects, we have to
-  cheat a bit to have request object that will looks like HTTP request object, by
-  calling :meth:`use_web_compatible_requests()` on the connection.
-
-This creates an automatic entity form. The ``.render()`` call yields
-an html (unicode) string. The html output is shown below (with
-internal fieldset omitted).
-
-Looking at the html output
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The form enveloppe
-''''''''''''''''''
-
-.. sourcecode:: html
-
- <div class="iformTitle"><span>main informations</span></div>
- <div class="formBody">
-  <form action="http://crater:9999/validateform" method="post" enctype="application/x-www-form-urlencoded"
-        id="entityForm" onsubmit="return freezeFormButtons(&#39;entityForm&#39;);"
-        class="entityForm" target="eformframe">
-    <div id="progress">validating...</div>
-    <fieldset>
-      <input name="__form_id" type="hidden" value="edition" />
-      <input name="__errorurl" type="hidden" value="http://perdu.com#entityForm" />
-      <input name="__domid" type="hidden" value="entityForm" />
-      <input name="__type:763" type="hidden" value="Ticket" />
-      <input name="eid" type="hidden" value="763" />
-      <input name="__maineid" type="hidden" value="763" />
-      <input name="_cw_edited_fields:763" type="hidden"
-             value="concerns-subject,done_in-subject,priority-subject,type-subject,title-subject,description-subject,__type,_cw_generic_field" />
-      ...
-    </fieldset>
-    <iframe width="0px" height="0px" name="eformframe" id="eformframe" src="javascript: void(0);"></iframe>
-   </form>
- </div>
-
-The main fieldset encloses a set of hidden fields containing various
-metadata, that will be used by the `edit controller` to process it
-back correctly.
-
-The `freezeFormButtons(...)` javascript callback defined on the
-``onlick`` event of the form element prevents accidental multiple
-clicks in a row.
-
-The ``action`` of the form is mapped to the ``validateform`` controller
-(situated in :mod:`cubicweb.web.views.basecontrollers`).
-
-A full explanation of the validation loop is given in
-:ref:`validation_process`.
-
-.. _attributes_section:
-
-The attributes section
-''''''''''''''''''''''
-
-We can have a look at some of the inner nodes of the form. Some fields
-are omitted as they are redundant for our purposes.
-
-.. sourcecode:: html
-
-      <fieldset class="default">
-        <table class="attributeForm">
-          <tr class="title_subject_row">
-            <th class="labelCol"><label class="required" for="title-subject:763">title</label></th>
-            <td>
-              <input id="title-subject:763" maxlength="128" name="title-subject:763" size="45"
-                     tabindex="1" type="text" value="let us write more doc" />
-            </td>
-          </tr>
-          ... (description field omitted) ...
-          <tr class="priority_subject_row">
-            <th class="labelCol"><label class="required" for="priority-subject:763">priority</label></th>
-            <td>
-              <select id="priority-subject:763" name="priority-subject:763" size="1" tabindex="4">
-                <option value="important">important</option>
-                <option selected="selected" value="normal">normal</option>
-                <option value="minor">minor</option>
-              </select>
-              <div class="helper">importance</div>
-            </td>
-          </tr>
-          ... (type field omitted) ...
-          <tr class="concerns_subject_row">
-            <th class="labelCol"><label class="required" for="concerns-subject:763">concerns</label></th>
-            <td>
-              <select id="concerns-subject:763" name="concerns-subject:763" size="1" tabindex="6">
-                <option selected="selected" value="760">Foo</option>
-              </select>
-            </td>
-          </tr>
-          <tr class="done_in_subject_row">
-            <th class="labelCol"><label for="done_in-subject:763">done in</label></th>
-            <td>
-              <select id="done_in-subject:763" name="done_in-subject:763" size="1" tabindex="7">
-                <option value="__cubicweb_internal_field__"></option>
-                <option selected="selected" value="761">Foo 0.1.0</option>
-                <option value="762">Foo 0.2.0</option>
-              </select>
-              <div class="helper">version in which this ticket will be / has been  done</div>
-            </td>
-          </tr>
-        </table>
-      </fieldset>
-
-
-Note that the whole form layout has been computed by the form
-renderer. It is the renderer which produces the table
-structure. Otherwise, the fields html structure is emitted by their
-associated widget.
-
-While it is called the `attributes` section of the form, it actually
-contains attributes and *mandatory relations*. For each field, we
-observe:
-
-* a dedicated row with a specific class, such as ``title_subject_row``
-  (responsability of the form renderer)
-
-* an html widget (input, select, ...) with:
-
-  * an id built from the ``rtype-role:eid`` pattern
-
-  * a name built from the same pattern
-
-  * possible values or preselected options
-
-The relations section
-'''''''''''''''''''''
-
-.. sourcecode:: html
-
-      <fieldset class="This ticket :">
-        <legend>This ticket :</legend>
-        <table class="attributeForm">
-          <tr class="_cw_generic_field_None_row">
-            <td colspan="2">
-              <table id="relatedEntities">
-                <tr><th>&#160;</th><td>&#160;</td></tr>
-                <tr id="relationSelectorRow_763" class="separator">
-                  <th class="labelCol">
-                    <select id="relationSelector_763" tabindex="8"
-                            onchange="javascript:showMatchingSelect(this.options[this.selectedIndex].value,763);">
-                      <option value="">select a relation</option>
-                      <option value="appeared_in_subject">appeared in</option>
-                      <option value="custom_workflow_subject">custom workflow</option>
-                      <option value="depends_on_object">dependency of</option>
-                      <option value="depends_on_subject">depends on</option>
-                      <option value="identical_to_subject">identical to</option>
-                      <option value="see_also_subject">see also</option>
-                    </select>
-                  </th>
-                  <td id="unrelatedDivs_763"></td>
-                </tr>
-              </table>
-            </td>
-          </tr>
-        </table>
-      </fieldset>
-
-The optional relations are grouped into a drop-down combo
-box. Selection of an item triggers a javascript function which will:
-
-* show already related entities in the div of id `relatedentities`
-  using a two-colown layout, with an action to allow deletion of
-  individual relations (there are none in this example)
-
-* provide a relation selector in the div of id `relationSelector_EID`
-  to allow the user to set up relations and trigger dynamic action on
-  the last div
-
-* fill the div of id `unrelatedDivs_EID` with a dynamically computed
-  selection widget allowing direct selection of an unrelated (but
-  relatable) entity or a switch towards the `search mode` of
-  |cubicweb| which allows full browsing and selection of an entity
-  using a dedicated action situated in the left column boxes.
-
-
-The buttons zone
-''''''''''''''''
-
-Finally comes the buttons zone.
-
-.. sourcecode:: html
-
-      <table width="100%">
-        <tbody>
-          <tr>
-            <td align="center">
-              <button class="validateButton" tabindex="9" type="submit" value="validate">
-                <img alt="OK_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/ok.png" />
-                validate
-              </button>
-            </td>
-            <td style="align: right; width: 50%;">
-              <button class="validateButton"
-                      onclick="postForm(&#39;__action_apply&#39;, &#39;button_apply&#39;, &#39;entityForm&#39;)"
-                      tabindex="10" type="button" value="apply">
-                <img alt="APPLY_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/plus.png" />
-                apply
-              </button>
-              <button class="validateButton"
-                      onclick="postForm(&#39;__action_cancel&#39;, &#39;button_cancel&#39;, &#39;entityForm&#39;)"
-                      tabindex="11" type="button" value="cancel">
-                <img alt="CANCEL_ICON" src="http://myapp/datafd8b5d92771209ede1018a8d5da46a37/cancel.png" />
-                cancel
-              </button>
-            </td>
-          </tr>
-        </tbody>
-      </table>
-
-The most notable artifacts here are the ``postForm(...)`` calls
-defined on click events on these buttons. This function basically
-submits the form.
-
-.. _validation_process:
-
-The form validation process
----------------------------
-
-Validation loop
-~~~~~~~~~~~~~~~
-
-On form submission, the form.action is invoked. Basically, the
-``validateform`` controller is called and its output lands in the
-specified ``target``, an invisible ``<iframe>`` at the end of the
-form.
-
-Hence, the main page is not replaced, only the iframe contents. The
-``validateform`` controller only outputs a tiny javascript fragment
-which is then immediately executed.
-
-.. sourcecode:: html
-
- <iframe width="0px" height="0px" name="eformframe" id="eformframe" src="javascript: void(0);">
-   <script type="text/javascript">
-     window.parent.handleFormValidationResponse('entityForm', null, null,
-                                                [false, [2164, {"name-subject": "required field"}], null],
-                                                null);
-   </script>
- </iframe>
-
-The ``window.parent`` part ensures the javascript function is called
-on the right context (that is: the form element). We will describe its
-parameters:
-
-* first comes the form id (`entityForm`)
-
-* then two optional callbacks for the success and failure case
-
-* an array containing:
-
-  * a boolean which indicates status (success or failure), and then, on error:
-
-    * an array structured as ``[eid, {'rtype-role': 'error msg'}, ...]``
-
-  * on success:
-
-    * a url (string) representing the next thing to jump to
-
-Given the array structure described above, it is quite simple to
-manipulate the DOM to show the errors at appropriate places.
-
-Explanation
-~~~~~~~~~~~
-
-This mecanism may seem a bit overcomplicated but we have to deal with
-two realities:
-
-* in the (strict) XHTML world, there are no iframes (hence the dynamic
-  inclusion, tolerated by Firefox)
-
-* no (or not all) browser(s) support file input field handling through
-  ajax.
--- a/doc/book/en/devweb/edition/editcontroller.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-.. _edit_controller:
-
-The `edit controller`
----------------------
-
-It can be found in (:mod:`cubicweb.web.views.editcontroller`). This
-controller processes data received from an html form to create or
-update entities.
-
-Edition handling
-~~~~~~~~~~~~~~~~
-
-The parameters related to entities to edit are specified as follows
-(first seen in :ref:`attributes_section`)::
-
-  <rtype-role>:<entity eid>
-
-where entity eid could be a letter in case of an entity to create. We
-name those parameters as *qualified*.
-
-* Retrieval of entities to edit is done by using the forms parameters
-  `eid` and `__type`
-
-* For all the attributes and the relations of an entity to edit
-  (attributes and relations are handled a bit differently but these
-  details are not much relevant here) :
-
-   * using the ``rtype``, ``role`` and ``__type`` information, fetch
-     an appropriate field instance
-
-   * check if the field has been modified (if not, proceed to the next
-     relation)
-
-   * build an rql expression to update the entity
-
-At the end, all rql expressions are executed.
-
-* For each entity to edit:
-
-   * if a qualified parameter `__linkto` is specified, its value has
-     to be a string (or a list of strings) such as: ::
-
-        <relation type>:<eids>:<target>
-
-     where <target> is either `subject` or `object` and each eid could
-     be separated from the others by a `_`. Target specifies if the
-     *edited entity* is subject or object of the relation and each
-     relation specified will be inserted.
-
-    * if a qualified parameter `__clone_eid` is specified for an entity, the
-      relations of the specified entity passed as value of this parameter are
-      copied on the edited entity.
-
-    * if a qualified parameter `__delete` is specified, its value must be
-      a string or a list of string such as follows: ::
-
-          <subjects eids>:<relation type>:<objects eids>
-
-      where each eid subject or object can be seperated from the other
-      by `_`. Each specified relation will be deleted.
-
-
-* If no entity is edited but the form contains the parameters `__linkto`
-  and `eid`, this one is interpreted by using the value specified for `eid`
-  to designate the entity on which to add the relations.
-
-.. note::
-
-   * if the parameter `__action_delete` is found, all the entities specified
-     as to be edited will be deleted.
-
-   * if the parameter `__action_cancel` is found, no action is completed.
-
-   * if the parameter `__action_apply` is found, the editing is
-     applied normally but the redirection is done on the form (see
-     :ref:`RedirectionControl`).
-
-   * if no entity is found to be edited and if there is no parameter
-     `__action_delete`, `__action_cancel`, `__linkto`, `__delete` or
-     `__insert`, an error is raised.
-
-   * using the parameter `__message` in the form will allow to use its value
-     as a message to provide the user once the editing is completed.
-
-
-.. _RedirectionControl:
-
-Redirection control
-~~~~~~~~~~~~~~~~~~~
-Once editing is completed, there is still an issue left: where should we go
-now? If nothing is specified, the controller will do his job but it does not
-mean we will be happy with the result. We can control that by using the
-following parameters:
-
-* `__redirectpath`: path of the URL (relative to the root URL of the site,
-  no form parameters
-
-* `__redirectparams`: forms parameters to add to the path
-
-* `__redirectrql`: redirection RQL request
-
-* `__redirectvid`: redirection view identifier
-
-* `__errorurl`: initial form URL, used for redirecting in case a validation
-  error is raised during editing. If this one is not specified, an error page
-  is displayed instead of going back to the form (which is, if necessary,
-  responsible for displaying the errors)
-
-* `__form_id`: initial view form identifier, used if `__action_apply` is
-  found
-
-In general we use either `__redirectpath` and `__redirectparams` or
-`__redirectrql` and `__redirectvid`.
--- a/doc/book/en/devweb/edition/examples.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-Examples
---------
-
-(Automatic) Entity form
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Looking at some cubes available on the `cubicweb forge`_ we find some
-with form manipulation. The following example comes from the the
-`conference`_ cube. It extends the change state form for the case
-where a ``Talk`` entity is getting into ``submitted`` state. The goal
-is to select reviewers for the submitted talk.
-
-.. _`cubicweb forge`: http://www.cubicweb.org/view?rql=Any+P+ORDERBY+N+WHERE+P+name+LIKE+%22cubicweb-%25%22%2C+P+is+Project%2C+P+name+N
-.. _`conference`: http://www.cubicweb.org/project/cubicweb-conference
-
-.. sourcecode:: python
-
- from cubicweb.web import formfields as ff, formwidgets as fwdgs
- class SendToReviewerStatusChangeView(ChangeStateFormView):
-     __select__ = (ChangeStateFormView.__select__ &
-                   is_instance('Talk') &
-                   rql_condition('X in_state S, S name "submitted"'))
-
-     def get_form(self, entity, transition, **kwargs):
-         form = super(SendToReviewerStatusChangeView, self).get_form(entity, transition, **kwargs)
-         relation = ff.RelationField(name='reviews', role='object',
-                                     eidparam=True,
-                                     label=_('select reviewers'),
-                                     widget=fwdgs.Select(multiple=True))
-         form.append_field(relation)
-         return form
-
-Simple extension of a form can be done from within the `FormView`
-wrapping the form. FormView instances have a handy ``get_form`` method
-that returns the form to be rendered. Here we add a ``RelationField``
-to the base state change form.
-
-One notable point is the ``eidparam`` argument: it tells both the
-field and the ``edit controller`` that the field is linked to a
-specific entity.
-
-It is hence entirely possible to add ad-hoc fields that will be
-processed by some specialized instance of the edit controller.
-
-
-Ad-hoc fields form
-~~~~~~~~~~~~~~~~~~
-
-We want to define a form doing something else than editing an entity. The idea is
-to propose a form to send an email to entities in a resultset which implements
-:class:`IEmailable`.  Let's take a simplified version of what you'll find in
-:mod:`cubicweb.web.views.massmailing`.
-
-Here is the source code:
-
-.. sourcecode:: python
-
-    def sender_value(form, field):
-	return '%s <%s>' % (form._cw.user.dc_title(), form._cw.user.get_email())
-
-    def recipient_choices(form, field):
-	return [(e.get_email(), e.eid)
-                 for e in form.cw_rset.entities()
-		 if e.get_email()]
-
-    def recipient_value(form, field):
-	return [e.eid for e in form.cw_rset.entities()
-                if e.get_email()]
-
-    class MassMailingForm(forms.FieldsForm):
-	__regid__ = 'massmailing'
-
-	needs_js = ('cubicweb.widgets.js',)
-	domid = 'sendmail'
-	action = 'sendmail'
-
-	sender = ff.StringField(widget=TextInput({'disabled': 'disabled'}),
-				label=_('From:'),
-				value=sender_value)
-
-	recipient = ff.StringField(widget=CheckBox(),
-	                           label=_('Recipients:'),
-				   choices=recipient_choices,
-				   value=recipients_value)
-
-	subject = ff.StringField(label=_('Subject:'), max_length=256)
-
-	mailbody = ff.StringField(widget=AjaxWidget(wdgtype='TemplateTextField',
-						    inputid='mailbody'))
-
-	form_buttons = [ImgButton('sendbutton', "javascript: $('#sendmail').submit()",
-				  _('send email'), 'SEND_EMAIL_ICON'),
-			ImgButton('cancelbutton', "javascript: history.back()",
-				  stdmsgs.BUTTON_CANCEL, 'CANCEL_EMAIL_ICON')]
-
-Let's detail what's going on up there. Our form will hold four fields:
-
-* a sender field, which is disabled and will simply contains the user's name and
-  email
-
-* a recipients field, which will be displayed as a list of users in the context
-  result set with checkboxes so user can still choose who will receive his mailing
-  by checking or not the checkboxes. By default all of them will be checked since
-  field's value return a list containing same eids as those returned by the
-  vocabulary function.
-
-* a subject field, limited to 256 characters (hence we know a
-  :class:`~cubicweb.web.formwidgets.TextInput` will be used, as explained in
-  :class:`~cubicweb.web.formfields.StringField`)
-
-* a mailbody field. This field use an ajax widget, defined in `cubicweb.widgets.js`,
-  and whose definition won't be shown here. Notice though that we tell this form
-  need this javascript file by using `needs_js`
-
-Last but not least, we add two buttons control: one to post the form using
-javascript (`$('#sendmail')` being the jQuery call to get the element with DOM id
-set to 'sendmail', which is our form DOM id as specified by its `domid`
-attribute), another to cancel the form which will go back to the previous page
-using another javascript call. Also we specify an image to use as button icon as a
-resource identifier (see :ref:`uiprops`) given as last argument to
-:class:`cubicweb.web.formwidgets.ImgButton`.
-
-To see this form, we still have to wrap it in a view. This is pretty simple:
-
-.. sourcecode:: python
-
-    class MassMailingFormView(form.FormViewMixIn, EntityView):
-	__regid__ = 'massmailing'
-	__select__ = is_instance(IEmailable) & authenticated_user()
-
-	def call(self):
-	    form = self._cw.vreg['forms'].select('massmailing', self._cw,
-	                                         rset=self.cw_rset)
-	    form.render(w=self.w)
-
-As you see, we simply define a view with proper selector so it only apply to a
-result set containing :class:`IEmailable` entities, and so that only users in the
-managers or users group can use it. Then in the `call()` method for this view we
-simply select the above form and call its `.render()` method with our output
-stream as argument.
-
-When this form is submitted, a controller with id 'sendmail' will be called (as
-specified using `action`). This controller will be responsible to actually send
-the mail to specified recipients.
-
-Here is what it looks like:
-
-.. sourcecode:: python
-
-   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))
-
-
-The entry point of a controller is the publish method. In that case we simply get
-back post values in request's `form` attribute, get user instances according
-to eids found in the 'recipient' form value, and send email after calling
-:func:`format_mail` to get a proper email message. If we can't send email or
-if we successfully sent email, we redirect to the index page with proper message
-to inform the user.
-
-Also notice that our controller has a selector that deny access to it
-to anonymous users (we don't want our instance to be used as a spam
-relay), but also checks if the expected parameters are specified in
-forms. That avoids later defensive programming (though it's not enough
-to handle all possible error cases).
-
-To conclude our example, suppose we wish a different form layout and that existent
-renderers are not satisfying (we would check that first of course :). We would then
-have to define our own renderer:
-
-.. sourcecode:: python
-
-    class MassMailingFormRenderer(formrenderers.FormRenderer):
-        __regid__ = 'massmailing'
-
-        def _render_fields(self, fields, w, form):
-            w(u'<table class="headersform">')
-            for field in fields:
-                if field.name == 'mailbody':
-                    w(u'</table>')
-                    w(u'<div id="toolbar">')
-                    w(u'<ul>')
-                    for button in form.form_buttons:
-                        w(u'<li>%s</li>' % button.render(form))
-                    w(u'</ul>')
-                    w(u'</div>')
-                    w(u'<div>')
-                    w(field.render(form, self))
-                    w(u'</div>')
-                else:
-                    w(u'<tr>')
-                    w(u'<td class="hlabel">%s</td>' %
-                      self.render_label(form, field))
-                    w(u'<td class="hvalue">')
-                    w(field.render(form, self))
-                    w(u'</td></tr>')
-
-        def render_buttons(self, w, form):
-            pass
-
-We simply override the `_render_fields` and `render_buttons` method of the base form renderer
-to arrange fields as we desire it: here we'll have first a two columns table with label and
-value of the sender, recipients and subject field (form order respected), then form controls,
-then a div containing the textarea for the email's content.
-
-To bind this renderer to our form, we should add to our form definition above:
-
-.. sourcecode:: python
-
-    form_renderer_id = 'massmailing'
-
--- a/doc/book/en/devweb/edition/form.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,377 +0,0 @@
-.. _webform:
-
-HTML form construction
-----------------------
-
-CubicWeb provides the somewhat usual form / field / widget / renderer abstraction
-to provide generic building blocks which will greatly help you in building forms
-properly integrated with CubicWeb (coherent display, error handling, etc...),
-while keeping things as flexible as possible.
-
-A ``form`` basically only holds a set of ``fields``, and has te be bound to a
-``renderer`` which is responsible to layout them. Each field is bound to a
-``widget`` that will be used to fill in value(s) for that field (at form
-generation time) and 'decode' (fetch and give a proper Python type to) values
-sent back by the browser.
-
-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
-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.
-
-Exploring the available forms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A small excursion into a |cubicweb| shell is the quickest way to
-discover available forms (or application objects in general).
-
-.. sourcecode:: python
-
- >>> from pprint import pprint
- >>> pprint( session.vreg['forms'] )
- {'base': [<class 'cubicweb.web.views.forms.FieldsForm'>,
-           <class 'cubicweb.web.views.forms.EntityFieldsForm'>],
-  'changestate': [<class 'cubicweb.web.views.workflow.ChangeStateForm'>,
-                  <class 'cubes.tracker.views.forms.VersionChangeStateForm'>],
-  'composite': [<class 'cubicweb.web.views.forms.CompositeForm'>,
-                <class 'cubicweb.web.views.forms.CompositeEntityForm'>],
-  'deleteconf': [<class 'cubicweb.web.views.editforms.DeleteConfForm'>],
-  'edition': [<class 'cubicweb.web.views.autoform.AutomaticEntityForm'>,
-              <class 'cubicweb.web.views.workflow.TransitionEditionForm'>,
-              <class 'cubicweb.web.views.workflow.StateEditionForm'>],
-  'logform': [<class 'cubicweb.web.views.basetemplates.LogForm'>],
-  'massmailing': [<class 'cubicweb.web.views.massmailing.MassMailingForm'>],
-  'muledit': [<class 'cubicweb.web.views.editforms.TableEditForm'>],
-  'sparql': [<class 'cubicweb.web.views.sparql.SparqlForm'>]}
-
-
-The two most important form families here (for all practical purposes) are `base`
-and `edition`. Most of the time one wants alterations of the
-:class:`AutomaticEntityForm` to generate custom forms to handle edition of an
-entity.
-
-The Automatic Entity Form
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. automodule:: cubicweb.web.views.autoform
-
-Anatomy of a choices function
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Let's have a look at the `ticket_done_in_choices` function given to
-the `choices` parameter of the relation tag that is applied to the
-('Ticket', 'done_in', '*') relation definition, as it is both typical
-and sophisticated enough. This is a code snippet from the `tracker`_
-cube.
-
-.. _`tracker`: http://www.cubicweb.org/project/cubicweb-tracker
-
-The ``Ticket`` entity type can be related to a ``Project`` and a
-``Version``, respectively through the ``concerns`` and ``done_in``
-relations. When a user is about to edit a ticket, we want to fill the
-combo box for the ``done_in`` relation with values pertinent with
-respect to the context. The important context here is:
-
-* creation or modification (we cannot fetch values the same way in
-  either case)
-
-* ``__linkto`` url parameter given in a creation context
-
-.. sourcecode:: python
-
-    from cubicweb.web import formfields
-
-    def ticket_done_in_choices(form, field):
-        entity = form.edited_entity
-        # first see if its specified by __linkto form parameters
-        linkedto = form.linked_to[('done_in', 'subject')]
-        if linkedto:
-            return linkedto
-        # it isn't, get initial values
-        vocab = field.relvoc_init(form)
-        veid = None
-        # try to fetch the (already or pending) related version and project
-        if not entity.has_eid():
-            peids = form.linked_to[('concerns', 'subject')]
-            peid = peids and peids[0]
-        else:
-            peid = entity.project.eid
-            veid = entity.done_in and entity.done_in[0].eid
-        if peid:
-            # we can complete the vocabulary with relevant values
-            rschema = form._cw.vreg.schema['done_in'].rdef('Ticket', 'Version')
-            rset = form._cw.execute(
-                'Any V, VN ORDERBY version_sort_value(VN) '
-                'WHERE V version_of P, P eid %(p)s, V num VN, '
-                'V in_state ST, NOT ST name "published"', {'p': peid}, 'p')
-            vocab += [(v.view('combobox'), v.eid) for v in rset.entities()
-                      if rschema.has_perm(form._cw, 'add', toeid=v.eid)
-                      and v.eid != veid]
-        return vocab
-
-The first thing we have to do is fetch potential values from the ``__linkto`` url
-parameter that is often found in entity creation contexts (the creation action
-provides such a parameter with a predetermined value; for instance in this case,
-ticket creation could occur in the context of a `Version` entity). The
-:class:`~cubicweb.web.formfields.RelationField` field class provides a
-:meth:`~cubicweb.web.formfields.RelationField.relvoc_linkedto` method that gets a
-list suitably filled with vocabulary values.
-
-.. sourcecode:: python
-
-        linkedto = field.relvoc_linkedto(form)
-        if linkedto:
-            return linkedto
-
-Then, if no ``__linkto`` argument was given, we must prepare the vocabulary with
-an initial empty value (because `done_in` is not mandatory, we must allow the
-user to not select a verson) and already linked values. This is done with the
-:meth:`~cubicweb.web.formfields.RelationField.relvoc_init` method.
-
-.. sourcecode:: python
-
-        vocab = field.relvoc_init(form)
-
-But then, we have to give more: if the ticket is related to a project,
-we should provide all the non published versions of this project
-(`Version` and `Project` can be related through the `version_of`
-relation). Conversely, if we do not know yet the project, it would not
-make sense to propose all existing versions as it could potentially
-lead to incoherences. Even if these will be caught by some
-RQLConstraint, it is wise not to tempt the user with error-inducing
-candidate values.
-
-The "ticket is related to a project" part must be decomposed as:
-
-* this is a new ticket which is created is the context of a project
-
-* this is an already existing ticket, linked to a project (through the
-  `concerns` relation)
-
-* there is no related project (quite unlikely given the cardinality of
-  the `concerns` relation, so it can only mean that we are creating a
-  new ticket, and a project is about to be selected but there is no
-  ``__linkto`` argument)
-
-.. note::
-
-   the last situation could happen in several ways, but of course in a
-   polished application, the paths to ticket creation should be
-   controlled so as to avoid a suboptimal end-user experience
-
-Hence, we try to fetch the related project.
-
-.. sourcecode:: python
-
-        veid = None
-        if not entity.has_eid():
-            peids = form.linked_to[('concerns', 'subject')]
-            peid = peids and peids[0]
-        else:
-            peid = entity.project.eid
-            veid = entity.done_in and entity.done_in[0].eid
-
-We distinguish between entity creation and entity modification using
-the ``Entity.has_eid()`` method, which returns `False` on creation. At
-creation time the only way to get a project is through the
-``__linkto`` parameter. Notice that we fetch the version in which the
-ticket is `done_in` if any, for later.
-
-.. note::
-
-  the implementation above assumes that if there is a ``__linkto``
-  parameter, it is only about a project. While it makes sense most of
-  the time, it is not an absolute. Depending on how an entity creation
-  action action url is built, several outcomes could be possible
-  there
-
-If the ticket is already linked to a project, fetching it is
-trivial. Then we add the relevant version to the initial vocabulary.
-
-.. sourcecode:: python
-
-        if peid:
-            rschema = form._cw.vreg.schema['done_in'].rdef('Ticket', 'Version')
-            rset = form._cw.execute(
-                'Any V, VN ORDERBY version_sort_value(VN) '
-                'WHERE V version_of P, P eid %(p)s, V num VN, '
-                'V in_state ST, NOT ST name "published"', {'p': peid})
-            vocab += [(v.view('combobox'), v.eid) for v in rset.entities()
-                      if rschema.has_perm(form._cw, 'add', toeid=v.eid)
-                      and v.eid != veid]
-
-.. warning::
-
-   we have to defend ourselves against lack of a project eid. Given
-   the cardinality of the `concerns` relation, there *must* be a
-   project, but this rule can only be enforced at validation time,
-   which will happen of course only after form subsmission
-
-Here, given a project eid, we complete the vocabulary with all
-unpublished versions defined in the project (sorted by number) for
-which the current user is allowed to establish the relation.
-
-
-Building self-posted form with custom fields/widgets
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Sometimes you want a form that is not related to entity edition. For those,
-you'll have to handle form posting by yourself. Here is a complete example on how
-to achieve this (and more).
-
-Imagine you want a form that selects a month period. There are no proper
-field/widget to handle this in CubicWeb, so let's start by defining them:
-
-.. sourcecode:: python
-
-    # let's have the whole import list at the beginning, even those necessary for
-    # subsequent snippets
-    from logilab.common import date
-    from logilab.mtconverter import xml_escape
-    from cubicweb.view import View
-    from cubicweb.predicates import match_kwargs
-    from cubicweb.web import RequestError, ProcessFormError
-    from cubicweb.web import formfields as fields, formwidgets as wdgs
-    from cubicweb.web.views import forms, calendar
-
-    class MonthSelect(wdgs.Select):
-        """Custom widget to display month and year. Expect value to be given as a
-        date instance.
-        """
-
-        def format_value(self, form, field, value):
-            return u'%s/%s' % (value.year, value.month)
-
-        def process_field_data(self, form, field):
-            val = super(MonthSelect, self).process_field_data(form, field)
-            try:
-                year, month = val.split('/')
-                year = int(year)
-                month = int(month)
-                return date.date(year, month, 1)
-            except ValueError:
-                raise ProcessFormError(
-                    form._cw._('badly formated date string %s') % val)
-
-
-    class MonthPeriodField(fields.CompoundField):
-        """custom field composed of two subfields, 'begin_month' and 'end_month'.
-
-        It expects to be used on form that has 'mindate' and 'maxdate' in its
-        extra arguments, telling the range of month to display.
-        """
-
-        def __init__(self, *args, **kwargs):
-            kwargs.setdefault('widget', wdgs.IntervalWidget())
-            super(MonthPeriodField, self).__init__(
-                [fields.StringField(name='begin_month',
-                                    choices=self.get_range, sort=False,
-                                    value=self.get_mindate,
-                                    widget=MonthSelect()),
-                 fields.StringField(name='end_month',
-                                    choices=self.get_range, sort=False,
-                                    value=self.get_maxdate,
-                                    widget=MonthSelect())], *args, **kwargs)
-
-        @staticmethod
-        def get_range(form, field):
-            mindate = date.todate(form.cw_extra_kwargs['mindate'])
-            maxdate = date.todate(form.cw_extra_kwargs['maxdate'])
-            assert mindate <= maxdate
-            _ = form._cw._
-            months = []
-            while mindate <= maxdate:
-                label = '%s %s' % (_(calendar.MONTHNAMES[mindate.month - 1]),
-                                   mindate.year)
-                value = field.widget.format_value(form, field, mindate)
-                months.append( (label, value) )
-                mindate = date.next_month(mindate)
-            return months
-
-        @staticmethod
-        def get_mindate(form, field):
-            return form.cw_extra_kwargs['mindate']
-
-        @staticmethod
-        def get_maxdate(form, field):
-            return form.cw_extra_kwargs['maxdate']
-
-        def process_posted(self, form):
-            for field, value in super(MonthPeriodField, self).process_posted(form):
-                if field.name == 'end_month':
-                    value = date.last_day(value)
-                yield field, value
-
-
-Here we first define a widget that will be used to select the beginning and the
-end of the period, displaying months like '<month> YYYY' but using 'YYYY/mm' as
-actual value.
-
-We then define a field that will actually hold two fields, one for the beginning
-and another for the end of the period. Each subfield uses the widget we defined
-earlier, and the outer field itself uses the standard
-:class:`IntervalWidget`. The field adds some logic:
-
-* a vocabulary generation function `get_range`, used to populate each sub-field
-
-* two 'value' functions `get_mindate` and `get_maxdate`, used to tell to
-  subfields which value they should consider on form initialization
-
-* overriding of `process_posted`, called when the form is being posted, so that
-  the end of the period is properly set to the last day of the month.
-
-Now, we can define a very simple form:
-
-.. sourcecode:: python
-
-    class MonthPeriodSelectorForm(forms.FieldsForm):
-        __regid__ = 'myform'
-        __select__ = match_kwargs('mindate', 'maxdate')
-
-        form_buttons = [wdgs.SubmitButton()]
-        form_renderer_id = 'onerowtable'
-        period = MonthPeriodField()
-
-
-where we simply add our field, set a submit button and use a very simple renderer
-(try others!). Also we specify a selector that ensures form will have arguments
-necessary to our field.
-
-Now, we need a view that will wrap the form and handle post when it occurs,
-simply displaying posted values in the page:
-
-.. sourcecode:: python
-
-    class SelfPostingForm(View):
-        __regid__ = 'myformview'
-
-        def call(self):
-            mindate, maxdate = date.date(2010, 1, 1), date.date(2012, 1, 1)
-            form = self._cw.vreg['forms'].select(
-                'myform', self._cw, mindate=mindate, maxdate=maxdate, action='')
-            try:
-                posted = form.process_posted()
-                self.w(u'<p>posted values %s</p>' % xml_escape(repr(posted)))
-            except RequestError: # no specified period asked
-                pass
-            form.render(w=self.w, formvalues=self._cw.form)
-
-
-Notice usage of the :meth:`process_posted` method, that will return a dictionary
-of typed values (because they have been processed by the field). In our case, when
-the form is posted you should see a dictionary with 'begin_month' and 'end_month'
-as keys with the selected dates as value (as a python `date` object).
-
-
-APIs
-~~~~
-
-.. automodule:: cubicweb.web.formfields
-.. automodule:: cubicweb.web.formwidgets
-.. automodule:: cubicweb.web.views.forms
-.. automodule:: cubicweb.web.views.formrenderers
-
-
--- a/doc/book/en/devweb/edition/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-Edition control
-===============
-
-This chapter covers the editing capabilities of |cubicweb|. It
-explains html Form construction, the Edit Controller and their
-interactions.
-
-
-.. toctree::
-   :maxdepth: 2
-
-   form
-   dissection
-   editcontroller
-   examples
--- a/doc/book/en/devweb/facets.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-The facets system
------------------
-
-Facets allow to restrict searches according to some user friendly criterias.
-CubicWeb has a builtin `facet`_ system to define restrictions `filters`_ really
-as easily as possible.
-
-Here is an exemple of the facets rendering picked from our
-http://www.cubicweb.org web site:
-
-.. image:: ../images/facet_overview.png
-
-Facets will appear on each page presenting more than one entity that may be
-filtered according to some known criteria.
-
-Base classes for facets
-~~~~~~~~~~~~~~~~~~~~~~~
-.. automodule:: cubicweb.web.facet
-
-
-.. _facet: http://en.wikipedia.org/wiki/Faceted_browser
-.. _filters: http://www.cubicweb.org/blogentry/154152
-
--- a/doc/book/en/devweb/httpcaching.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-HTTP cache management
-=====================
-
-.. automodule:: cubicweb.web.httpcache
-
-Cache policies
---------------
-.. autoclass:: cubicweb.web.httpcache.NoHTTPCacheManager
-.. autoclass:: cubicweb.web.httpcache.MaxAgeHTTPCacheManager
-.. autoclass:: cubicweb.web.httpcache.EtagHTTPCacheManager
-.. autoclass:: cubicweb.web.httpcache.EntityHTTPCacheManager
-
-Exception
----------
-.. autoexception:: cubicweb.web.httpcache.NoEtag
-
-Helper functions
-----------------
-.. autofunction:: cubicweb.web.httpcache.set_http_cache_headers
-
-.. NOT YET AVAILABLE IN STABLE autofunction:: cubicweb.web.httpcache.lastmodified
--- a/doc/book/en/devweb/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-Web side development
-====================
-
-In this chapter, we will describe the core APIs for web development in
-the *CubicWeb* framework.
-
-.. toctree::
-   :maxdepth: 2
-
-   publisher
-   controllers
-   request
-   searchbar
-   views/index
-   rtags
-   ajax
-   js
-   css
-   edition/index
-   facets
-   internationalization
-   property
-   httpcaching
-   resource
--- a/doc/book/en/devweb/internationalization.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _internationalization:
-
-Internationalization
----------------------
-
-Cubicweb fully supports the internalization of its content and interface.
-
-Cubicweb's interface internationalization is based on the translation project `GNU gettext`_.
-
-.. _`GNU gettext`: http://www.gnu.org/software/gettext/
-
-Cubicweb' internalization involves two steps:
-
-* in your Python code and cubicweb-tal templates : mark translatable strings
-
-* in your instance : handle the translation catalog, edit translations
-
-String internationalization
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-User defined string
-```````````````````
-
-In the Python code and cubicweb-tal templates translatable strings can be
-marked in one of the following ways :
-
- * by using the *built-in* function `_`:
-
-   .. sourcecode:: python
-
-     class PrimaryView(EntityView):
-         """the full view of an non final entity"""
-         __regid__ = 'primary'
-         title = _('primary')
-
-  OR
-
- * by using the equivalent request's method:
-
-   .. sourcecode:: python
-
-     class NoResultView(View):
-         """default view when no result has been found"""
-         __regid__ = 'noresult'
-
-         def call(self, **kwargs):
-             self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
-                 % self._cw._('No result matching query'))
-
-The goal of the *built-in* function `_` is only **to mark the
-translatable strings**, it will only return the string to translate
-itself, but not its translation (it's actually another name for the
-`unicode` builtin).
-
-In the other hand the request's method `self._cw._` is also meant to
-retrieve the proper translation of translation strings in the
-requested language.
-
-Finally you can also use the `__` attribute of request object to get a
-translation for a string *which should not itself added to the catalog*,
-usually in case where the actual msgid is created by string interpolation ::
-
-  self._cw.__('This %s' % etype)
-
-In this example ._cw.__` is used instead of ._cw._` so we don't have 'This %s' in
-messages catalogs.
-
-Translations in cubicweb-tal template can also be done with TAL tags
-`i18n:content` and `i18n:replace`.
-
-If you need to add messages on top of those that can be found in the source,
-you can create a file named `i18n/static-messages.pot`.
-
-You could put there messages not found in the python sources or
-overrides for some messages of used cubes.
-
-Generated string
-````````````````
-
-We do not need to mark the translation strings of entities/relations used by a
-particular instance's schema as they are generated automatically. String for
-various actions are also generated.
-
-For exemple the following schema:
-
-.. sourcecode:: python
-
-
-  class EntityA(EntityType):
-      relation_a2b = SubjectRelation('EntityB')
-
-  class EntityB(EntityType):
-      pass
-
-May generate the following message ::
-
-  add EntityA relation_a2b EntityB subject
-
-This message will be used in views of ``EntityA`` for creation of a new
-``EntityB`` with a preset relation ``relation_a2b`` between the current
-``EntityA`` and the new ``EntityB``. The opposite message ::
-
-  add EntityA relation_a2b EntityB object
-
-Is used for similar creation of an ``EntityA`` from a view of ``EntityB``. The
-title of they respective creation form will be ::
-
-  creating EntityB (EntityA %(linkto)s relation_a2b EntityB)
-
-  creating EntityA (EntityA relation_a2b %(linkto)s EntityA)
-
-In the translated string you can use ``%(linkto)s`` for reference to the source
-``entity``.
-
-Handling the translation catalog
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Once the internationalization is done in your code, you need to populate and
-update the translation catalog. Cubicweb provides the following commands for this
-purpose:
-
-
-* `i18ncubicweb` updates Cubicweb framework's translation
-  catalogs. Unless you actually work on the framework itself, you
-  don't need to use this command.
-
-* `i18ncube` updates the translation catalogs of *one particular cube*
-  (or of all cubes). After this command is executed you must update
-  the translation files *.po* in the "i18n" directory of your
-  cube. This command will of course not remove existing translations
-  still in use. It will mark unused translation but not remove them.
-
-* `i18ninstance` recompiles the translation catalogs of *one particular
-  instance* (or of all instances) after the translation catalogs of
-  its cubes have been updated. This command is automatically
-  called every time you create or update your instance. The compiled
-  catalogs (*.mo*) are stored in the i18n/<lang>/LC_MESSAGES of
-  instance where `lang` is the language identifier ('en' or 'fr'
-  for exemple).
-
-
-Example
-```````
-
-You have added and/or modified some translation strings in your cube
-(after creating a new view or modifying the cube's schema for exemple).
-To update the translation catalogs you need to do:
-
-1. `cubicweb-ctl i18ncube <cube>`
-2. Edit the <cube>/i18n/xxx.po  files and add missing translations (empty `msgstr`)
-3. `hg ci -m "updated i18n catalogs"`
-4. `cubicweb-ctl i18ninstance <myinstance>`
-
-Editing po files
-~~~~~~~~~~~~~~~~
-
-Using a PO aware editor
-````````````````````````
-
-Many tools exist to help maintain .po (PO) files. Common editors or
-development environment provides modes for these. One can also find
-dedicated PO files editor, such as `poedit`_.
-
-.. _`poedit`:  http://www.poedit.net/
-
-While usage of such a tool is commendable, PO files are perfectly
-editable with a (unicode aware) plain text editor. It is also useful
-to know their structure for troubleshooting purposes.
-
-Structure of a PO file
-``````````````````````
-
-In this section, we selectively quote passages of the `GNU gettext`_
-manual chapter on PO files, available there::
-
- http://www.gnu.org/software/hello/manual/gettext/PO-Files.html
-
-One PO file entry has the following schematic structure::
-
-     white-space
-     #  translator-comments
-     #. extracted-comments
-     #: reference...
-     #, flag...
-     #| msgid previous-untranslated-string
-     msgid untranslated-string
-     msgstr translated-string
-
-
-A simple entry can look like this::
-
-     #: lib/error.c:116
-     msgid "Unknown system error"
-     msgstr "Error desconegut del sistema"
-
-It is also possible to have entries with a context specifier. They
-look like this::
-
-     white-space
-     #  translator-comments
-     #. extracted-comments
-     #: reference...
-     #, flag...
-     #| msgctxt previous-context
-     #| msgid previous-untranslated-string
-     msgctxt context
-     msgid untranslated-string
-     msgstr translated-string
-
-
-The context serves to disambiguate messages with the same
-untranslated-string. It is possible to have several entries with the
-same untranslated-string in a PO file, provided that they each have a
-different context. Note that an empty context string and an absent
-msgctxt line do not mean the same thing.
-
-Contexts and CubicWeb
-`````````````````````
-
-CubicWeb PO files have both non-contextual and contextual msgids.
-
-Contextual entries are automatically used in some cases. For instance,
-entity.dc_type(), eschema.display_name(req) or display_name(etype,
-req, form, context) methods/function calls will use them.
-
-It is also possible to explicitly use the with _cw.pgettext(context,
-msgid).
--- a/doc/book/en/devweb/js.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,394 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Javascript
-----------
-
-*CubicWeb* uses quite a bit of javascript in its user interface and
-ships with jquery (1.3.x) and parts of the jquery UI library, plus a
-number of homegrown files and also other third party libraries.
-
-All javascript files are stored in cubicweb/web/data/. There are
-around thirty js files there. In a cube it goes to data/.
-
-Obviously one does not want javascript pieces to be loaded all at
-once, hence the framework provides a number of mechanisms and
-conventions to deal with javascript resources.
-
-Conventions
-~~~~~~~~~~~
-
-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)
-
-Server-side Javascript API
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Javascript resources are typically loaded on demand, from views. The
-request object (available as self._cw from most application objects,
-for instance views and entities objects) has a few methods to do that:
-
-* `add_js(self, jsfiles, localfile=True)` which takes a sequence of
-  javascript files and writes proper entries into the HTML header
-  section. The localfile parameter allows to declare resources which
-  are not from web/data (for instance, residing on a content delivery
-  network).
-
-* `add_onload(self, jscode)` which adds one raw javascript code
-  snippet inline in the html headers. This is quite useful for setting
-  up early jQuery(document).ready(...) initialisations.
-
-Javascript events
-~~~~~~~~~~~~~~~~~
-
-* ``server-response``: this event is triggered on HTTP responses (both
-  standard and ajax). The two following extra parameters are passed
-  to callbacks :
-
-  - ``ajax``: a boolean that says if the reponse was issued by an
-    ajax request
-
-  - ``node``: the DOM node returned by the server in case of an
-    ajax request, otherwise the document itself for standard HTTP
-    requests.
-
-Important javascript AJAX APIS
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* `asyncRemoteExec` and `remoteExec` are the base building blocks for
-  doing arbitrary async (resp. sync) communications with the server
-
-* `reloadComponent` is a convenience function to replace a DOM node
-  with server supplied content coming from a specific registry (this
-  is quite handy to refresh the content of some boxes for instances)
-
-* `jQuery.fn.loadxhtml` is an important extension to jQuery which
-  allows proper loading and in-place DOM update of xhtml views. It is
-  suitably augmented to trigger necessary events, and process CubicWeb
-  specific elements such as the facet system, fckeditor, etc.
-
-
-A simple example with asyncRemoteExec
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-On the python side, we have to define an
-:class:`cubicweb.web.views.ajaxcontroller.AjaxFunction` object. The
-simplest way to do that is to use the
-:func:`cubicweb.web.views.ajaxcontroller.ajaxfunc` decorator (for more
-details on this, refer to :ref:`ajax`).
-
-.. sourcecode: python
-
-    from cubicweb.web.views.ajaxcontroller import ajaxfunc
-
-    # serialize output to json to get it back easily on the javascript side
-    @ajaxfunc(output_type='json')
-    def js_say_hello(self, name):
-        return u'hello %s' % name
-
-On the javascript side, we do the asynchronous call. Notice how it
-creates a `deferred` object. Proper treatment of the return value or
-error handling has to be done through the addCallback and addErrback
-methods.
-
-.. sourcecode: javascript
-
-    function asyncHello(name) {
-        var deferred = asyncRemoteExec('say_hello', name);
-        deferred.addCallback(function (response) {
-            alert(response);
-        });
-        deferred.addErrback(function (error) {
-            alert('something fishy happened');
-        });
-     }
-
-     function syncHello(name) {
-         alert( remoteExec('say_hello', name) );
-     }
-
-Anatomy of a reloadComponent call
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-`reloadComponent` allows to dynamically replace some DOM node with new
-elements. It has the following signature:
-
-* `compid` (mandatory) is the name of the component to be reloaded
-
-* `rql` (optional) will be used to generate a result set given as
-  argument to the selected component
-
-* `registry` (optional) defaults to 'components' but can be any other
-  valid registry name
-
-* `nodeid` (optional) defaults to compid + 'Component' but can be any
-  explicitly specified DOM node id
-
-* `extraargs` (optional) should be a dictionary of values that will be
-  given to the cell_call method of the component
-
-A simple reloadComponent example
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The server side implementation of `reloadComponent` is the
-:func:`cubicweb.web.views.ajaxcontroller.component` *AjaxFunction* appobject.
-
-The following function implements a two-steps method to delete a
-standard bookmark and refresh the UI, while keeping the UI responsive.
-
-.. sourcecode:: javascript
-
-    function removeBookmark(beid) {
-        d = asyncRemoteExec('delete_bookmark', beid);
-        d.addCallback(function(boxcontent) {
-	    reloadComponent('bookmarks_box', '', 'boxes', 'bookmarks_box');
-            document.location.hash = '#header';
-            updateMessage(_("bookmark has been removed"));
-         });
-    }
-
-`reloadComponent` is called with the id of the bookmark box as
-argument, no rql expression (because the bookmarks display is actually
-independant of any dataset context), a reference to the 'boxes'
-registry (which hosts all left, right and contextual boxes) and
-finally an explicit 'bookmarks_box' nodeid argument that stipulates
-the target DOM node.
-
-Anatomy of a loadxhtml call
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-`jQuery.fn.loadxhtml` is an important extension to jQuery which allows
-proper loading and in-place DOM update of xhtml views. The existing
-`jQuery.load`_ function does not handle xhtml, hence the addition. The
-API of loadxhtml is roughly similar to that of `jQuery.load`_.
-
-.. _`jQuery.load`: http://api.jquery.com/load/
-
-
-* `url` (mandatory) should be a complete url (typically referencing
-  the :class:`cubicweb.web.views.ajaxcontroller.AjaxController`,
-  but this is not strictly mandatory)
-
-* `data` (optional) is a dictionary of values given to the
-  controller specified through an `url` argument; some keys may have a
-  special meaning depending on the choosen controller (such as `fname`
-  for the JSonController); the `callback` key, if present, must refer
-  to a function to be called at the end of loadxhtml (more on this
-  below)
-
-* `reqtype` (optional) specifies the request method to be used (get or
-  post); if the argument is 'post', then the post method is used,
-  otherwise the get method is used
-
-* `mode` (optional) is one of `replace` (the default) which means the
-  loaded node will replace the current node content, `swap` to replace
-  the current node with the loaded node, and `append` which will
-  append the loaded node to the current node content
-
-About the `callback` option:
-
-* it is called with two parameters: the current node, and a list
-  containing the loaded (and post-processed node)
-
-* whenever it returns another function, this function is called in
-  turn with the same parameters as above
-
-This mechanism allows callback chaining.
-
-
-A simple example with loadxhtml
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Here we are concerned with the retrieval of a specific view to be
-injected in the live DOM. The view will be of course selected
-server-side using an entity eid provided by the client side.
-
-.. sourcecode:: python
-
-    from cubicweb.web.views.ajaxcontroller import ajaxfunc
-
-    @ajaxfunc(output_type='xhtml')
-    def frob_status(self, eid, frobname):
-        entity = self._cw.entity_from_eid(eid)
-        return entity.view('frob', name=frobname)
-
-.. sourcecode:: javascript
-
-    function updateSomeDiv(divid, eid, frobname) {
-        var params = {fname:'frob_status', eid: eid, frobname:frobname};
-        jQuery('#'+divid).loadxhtml(JSON_BASE_URL, params, 'post');
-     }
-
-In this example, the url argument is the base json url of a cube
-instance (it should contain something like
-`http://myinstance/ajax?`). The actual AjaxController method name is
-encoded in the `params` dictionary using the `fname` key.
-
-A more real-life example
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-A frequent need of Web 2 applications is the delayed (or demand
-driven) loading of pieces of the DOM. This is typically achieved using
-some preparation of the initial DOM nodes, jQuery event handling and
-proper use of loadxhtml.
-
-We present here a skeletal version of the mecanism used in CubicWeb
-and available in web/views/tabs.py, in the `LazyViewMixin` class.
-
-.. sourcecode:: python
-
-    def lazyview(self, vid, rql=None):
-        """ a lazy version of wview """
-        w = self.w
-        self._cw.add_js('cubicweb.lazy.js')
-        urlparams = {'vid' : vid, 'fname' : 'view'}
-        if rql is not None:
-            urlparams['rql'] = rql
-        w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % (
-            vid, xml_escape(self._cw.build_url('json', **urlparams))))
-        w(u'</div>')
-        self._cw.add_onload(u"""
-            jQuery('#lazy-%(vid)s').bind('%(event)s', function() {
-                   loadNow('#lazy-%(vid)s');});"""
-            % {'event': 'load_%s' % vid, 'vid': vid})
-
-This creates a `div` with a specific event associated to it.
-
-The full version deals with:
-
-* optional parameters such as an entity eid, an rset
-
-* the ability to further reload the fragment
-
-* the ability to display a spinning wheel while the fragment is still
-  not loaded
-
-* handling of browsers that do not support ajax (search engines,
-  text-based browsers such as lynx, etc.)
-
-The javascript side is quite simple, due to loadxhtml awesomeness.
-
-.. sourcecode:: javascript
-
-    function loadNow(eltsel) {
-        var lazydiv = jQuery(eltsel);
-        lazydiv.loadxhtml(lazydiv.attr('cubicweb:loadurl'));
-    }
-
-This is all significantly different of the previous `simple example`
-(albeit this example actually comes from real-life code).
-
-Notice how the `cubicweb:loadurl` is used to convey the url
-information. The base of this url is similar to the global javascript
-JSON_BASE_URL. According to the pattern described earlier,
-the `fname` parameter refers to the standard `js_view` method of the
-JSonController. This method renders an arbitrary view provided a view
-id (or `vid`) is provided, and most likely an rql expression yielding
-a result set against which a proper view instance will be selected.
-
-The `cubicweb:loadurl` is one of the 29 attributes extensions to XHTML
-in a specific cubicweb namespace. It is a means to pass information
-without breaking HTML nor XHTML compliance and without resorting to
-ungodly hacks.
-
-Given all this, it is easy to add a small nevertheless useful feature
-to force the loading of a lazy view (for instance, a very
-computation-intensive web page could be scinded into one fast-loading
-part and a delayed part).
-
-On the server side, a simple call to a javascript function is
-sufficient.
-
-.. sourcecode:: python
-
-    def forceview(self, vid):
-        """trigger an event that will force immediate loading of the view
-        on dom readyness
-        """
-        self._cw.add_onload("triggerLoad('%s');" % vid)
-
-The browser-side definition follows.
-
-.. sourcecode:: javascript
-
-    function triggerLoad(divid) {
-        jQuery('#lazy-' + divd).trigger('load_' + divid);
-    }
-
-
-Javascript library: overview
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* jquery.* : jquery and jquery UI library
-
-* cubicweb.ajax.js : concentrates all ajax related facilities (it
-  extends jQuery with the loahxhtml function, provides a handfull of
-  high-level ajaxy operations like asyncRemoteExec, reloadComponent,
-  replacePageChunk, getDomFromResponse)
-
-* cubicweb.python.js : adds a number of practical extension to stdanrd
-  javascript objects (on Date, Array, String, some list and dictionary
-  operations), and a pythonesque way to build classes. Defines a
-  CubicWeb namespace.
-
-* cubicweb.htmlhelpers.js : a small bag of convenience functions used
-  in various other cubicweb javascript resources (baseuri, progress
-  cursor handling, popup login box, html2dom function, etc.)
-
-* cubicweb.widgets.js : provides a widget namespace and constructors
-  and helpers for various widgets (mainly facets and timeline)
-
-* cubicweb.edition.js : used by edition forms
-
-* cubicweb.preferences.js : used by the preference form
-
-* cubicweb.facets.js : used by the facets mechanism
-
-There is also javascript support for massmailing, gmap (google maps),
-fckcwconfig (fck editor), timeline, calendar, goa (CubicWeb over
-AppEngine), flot (charts drawing), tabs and bookmarks.
-
-API
-~~~
-
-.. toctree::
-    :maxdepth: 1
-
-    js_api/index
-
-
-Testing javascript
-~~~~~~~~~~~~~~~~~~
-
-You with the ``cubicweb.qunit.QUnitTestCase`` can include standard Qunit tests
-inside the python unittest run . You simply have to define a new class that
-inherit from ``QUnitTestCase`` and register your javascript test file in the
-``all_js_tests`` lclass attribut. This  ``all_js_tests`` is a sequence a
-3-tuple (<test_file, [<dependencies> ,] [<data_files>]):
-
-The <test_file> should contains the qunit test. <dependencies> defines the list
-of javascript file that must be imported before the test script.  Dependencies
-are included their definition order. <data_files> are additional files copied in the
-test directory. both <dependencies> and <data_files> are optionnal.
-``jquery.js`` is preincluded in for all test.
-
-.. sourcecode:: python
-
-    from cubicweb.qunit import QUnitTestCase
-
-    class MyQUnitTest(QUnitTestCase):
-
-        all_js_tests = (
-            ("relative/path/to/my_simple_testcase.js",)
-            ("relative/path/to/my_qunit_testcase.js",(
-                "rel/path/to/dependency_1.js",
-                "rel/path/to/dependency_2.js",)),
-            ("relative/path/to/my_complexe_qunit_testcase.js",(
-                 "rel/path/to/dependency_1.js",
-                 "rel/path/to/dependency_2.js",
-               ),(
-                 "rel/path/file_dependency.html",
-                 "path/file_dependency.json")
-                ),
-            )
--- a/doc/book/en/devweb/property.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-.. _cwprops:
-
-The property mecanism
----------------------
-
-.. XXX CWProperty and co
-
-
-Property API
-~~~~~~~~~~~~
-.. XXX feed me
-
-Registering and using your own property
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. XXX feed me
--- a/doc/book/en/devweb/publisher.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-.. _publisher:
-
-Publisher
----------
-
-What happens when an HTTP request is issued ?
-
-The story begins with the ``CubicWebPublisher.main_publish``
-method. We do not get upper in the bootstrap process because it is
-dependant on the used HTTP library. With `twisted`_ however,
-``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
-  delegated to the `urlpublisher` component)
-
-* the controller is then selected (if not, this is considered an
-  authorization failure and signaled as such) and called
-
-* then either a proper result is returned, in which case the
-  request/connection object issues a ``commit`` and returns the result
-
-* or error handling must happen:
-
-  * ``ValidationErrors`` pop up there and may lead to a redirect to a
-    previously arranged url or standard error handling applies
-  * an HTTP 500 error (`Internal Server Error`) is issued
-
-
-Now, let's turn to the controller. There are many of them in
-:mod:`cubicweb.web.views.basecontrollers`. We can just follow the
-default `view` controller that is selected on a `view` path. See the
-:ref:`controllers` chapter for more information on controllers.
-
-The `View` controller's entry point is the `publish` method. It does
-the following:
-
-* compute the `main` view to be applied, using either the given result
-  set or building one from a user provided rql string (`rql` and `vid`
-  can be forced from the url GET parameters), that is:
-
-    * compute the `vid` using the result set and the schema (see
-      `cubicweb.web.views.vid_from_rset`)
-    * handle all error cases that could happen in this phase
-
-* do some cache management chores
-
-* select a main template (typically `TheMainTemplate`, see chapter
-  :ref:`templates`)
-
-* call it with the result set and the computed view.
-
-What happens next actually depends on the template and the view, but
-in general this is the rendering phase.
-
-
-CubicWebPublisher API
-`````````````````````
-
-.. autoclass:: cubicweb.web.application.CubicWebPublisher
-   :members:
--- a/doc/book/en/devweb/request.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-The `Request` class (`cubicweb.web.request`)
---------------------------------------------
-
-Overview
-````````
-
-A request instance is created when an HTTP request is sent to the web
-server.  It contains informations such as form parameters,
-authenticated user, etc. It is a very prevalent object and is used
-throughout all of the framework and applications, as you'll access to
-almost every resources through it.
-
-**A request represents a user query, either through HTTP or not (we
-also talk about RQL queries on the server side for example).**
-
-Here is a non-exhaustive list of attributes and methods available on
-request objects (grouped by category):
-
-* `Browser control`:
-
-  * `ie_browser`: tells if the browser belong to the Internet Explorer
-    family
-
-* `User and identification`:
-
-  * `user`, instance of `cubicweb.entities.authobjs.CWUser` corresponding to the
-    authenticated user
-
-* `Session data handling`
-
-  * `session.data` is the dictionary of the session data; it can be
-    manipulated like an ordinary Python dictionary
-
-* `Edition` (utilities for edition control):
-
-  * `cancel_edition`: resets error url and cleans up pending operations
-  * `create_entity`: utility to create an entity (from an etype,
-    attributes and relation values)
-  * `datadir_url`: returns the url to the merged external resources
-    (|cubicweb|'s `web/data` directory plus all `data` directories of
-    used cubes)
-  * `edited_eids`: returns the list of eids of entities that are
-    edited under the current http request
-  * `eid_rset(eid)`: utility which returns a result set from an eid
-  * `entity_from_eid(eid)`: returns an entity instance from the given eid
-  * `encoding`: returns the encoding of the current HTTP request
-  * `ensure_ro_rql(rql)`: ensure some rql query is a data request
-  * etype_rset
-  * `form`, dictionary containing the values of a web form
-  * `encoding`, character encoding to use in the response
-  * `next_tabindex()`: returns a monotonically growing integer used to
-    build the html tab index of forms
-
-* `HTTP`
-
-  * `authmode`: returns a string describing the authentication mode
-    (http, cookie, ...)
-  * `lang`: returns the user agents/browser's language as carried by
-    the http request
-  * `demote_to_html()`: in the context of an XHTML compliant browser,
-    this will force emission of the response as an HTML document
-    (using the http content negociation)
-
-*  `Cookies handling`
-
-  * `get_cookie()`, returns a dictionary containing the value of the header
-    HTTP 'Cookie'
-  * `set_cookie(cookie, key, maxage=300)`, adds a header HTTP `Set-Cookie`,
-    with a minimal 5 minutes length of duration by default (`maxage` = None
-    returns a *session* cookie which will expire when the user closes the browser
-    window)
-  * `remove_cookie(cookie, key)`, forces a value to expire
-
-* `URL handling`
-
-  * `build_url(__vid, *args, **kwargs)`: return an absolute URL using
-    params dictionary key/values as URL parameters. Values are
-    automatically URL quoted, and the publishing method to use may be
-    specified or will be guessed.
-  * `build_url_params(**kwargs)`: returns a properly prepared (quoted,
-    separators, ...) string from the given parameters
-  * `url()`, returns the full URL of the HTTP request
-  * `base_url()`, returns the root URL of the web application
-  * `relative_path()`, returns the relative path of the request
-
-* `Web resource (.css, .js files, etc.) handling`:
-
-  * `add_css(cssfiles)`: adds the given list of css resources to the current
-    html headers
-  * `add_js(jsfiles)`: adds the given list of javascript resources to the
-    current html headers
-  * `add_onload(jscode)`: inject the given jscode fragment (a unicode
-    string) into the current html headers, wrapped inside a
-    document.ready(...) or another ajax-friendly one-time trigger event
-  * `add_header(header, values)`: adds the header/value pair to the
-    current html headers
-  * `status_out`: control the HTTP status of the response
-
-* `And more...`
-
-  * `set_content_type(content_type, filename=None)`, adds the header HTTP
-    'Content-Type'
-  * `get_header(header)`, returns the value associated to an arbitrary header
-    of the HTTP request
-  * `set_header(header, value)`, adds an arbitrary header in the response
-  * `execute(*args, **kwargs)`, executes an RQL query and return the result set
-  * `property_value(key)`, properties management (`CWProperty`)
-  * dictionary `data` to store data to share informations between components
-    *while a request is executed*
-
-Please note that this class is abstract and that a concrete implementation
-will be provided by the *frontend* web used (in particular *twisted* as of
-today). For the views or others that are executed on the server side,
-most of the interface of `Request` is defined in the session associated
-to the client.
-
-API
-```
-
-The elements we gave in overview for above are built in three layers,
-from ``cubicweb.req.RequestSessionBase``, ``cubicweb.repoapi.Connection`` and
-``cubicweb.web.ConnectionCubicWebRequestBase``.
-
-.. autoclass:: cubicweb.req.RequestSessionBase
-   :members:
-
-.. autoclass:: cubicweb.repoapi.Connection
-   :members:
-
-.. autoclass:: cubicweb.web.request.ConnectionCubicWebRequestBase
-   :members:
--- a/doc/book/en/devweb/resource.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-.. _resources:
-
-Locate resources
-----------------
-
-.. automethod:: cubicweb.web.webconfig.WebConfiguration.locate_resource
-.. automethod:: cubicweb.web.webconfig.WebConfiguration.locate_doc_file
-.. automethod:: cubicweb.web.webconfig.WebConfiguration.locate_all_files
-
-Static files handling
----------------------
-
-.. autoattribute:: cubicweb.web.webconfig.WebConfiguration.static_directory
-.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_exists
-.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_open
-.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_add
-.. automethod:: cubicweb.web.webconfig.WebConfiguration.static_file_del
-
--- a/doc/book/en/devweb/rtags.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-Configuring the user interface
-------------------------------
-
-.. _relation_tags:
-
-Relation tags
-~~~~~~~~~~~~~
-.. automodule:: cubicweb.rtags
-
-.. _uicfg:
-
-The uicfg module
-~~~~~~~~~~~~~~~~
-
-.. note::
-
- The part of uicfg that deals with primary views is in the
- :ref:`primary_view_configuration` chapter.
-
-.. automodule:: cubicweb.web.views.uicfg
-
-
-The uihelper module
-~~~~~~~~~~~~~~~~~~~
-
-.. automodule:: cubicweb.web.uihelper
-
--- a/doc/book/en/devweb/searchbar.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-.. _searchbar:
-
-RQL search bar
---------------
-
-The RQL search bar is a visual component, hidden by default, the tiny *search*
-input being enough for common use cases.
-
-An autocompletion helper is provided to help you type valid queries, both
-in terms of syntax and in terms of schema validity.
-
-.. autoclass:: cubicweb.web.views.magicsearch.RQLSuggestionsBuilder
-
-
-How search is performed
-+++++++++++++++++++++++
-
-You can use the *rql search bar* to either type RQL queries, plain text queries
-or standard shortcuts such as *<EntityType>* or *<EntityType> <attrname> <value>*.
-
-Ultimately, all queries are translated to rql since it's the only
-language understood on the server (data) side. To transform the user
-query into RQL, CubicWeb uses the so-called *magicsearch component*,
-defined in :mod:`cubicweb.web.views.magicsearch`, which in turn
-delegates to a number of query preprocessor that are responsible of
-interpreting the user query and generating corresponding RQL.
-
-The code of the main processor loop is easy to understand:
-
-.. sourcecode:: python
-
-  for proc in self.processors:
-      try:
-          return proc.process_query(uquery, req)
-      except (RQLSyntaxError, BadRQLQuery):
-          pass
-
-The idea is simple: for each query processor, try to translate the
-query. If it fails, try with the next processor, if it succeeds,
-we're done and the RQL query will be executed.
-
--- a/doc/book/en/devweb/views/basetemplates.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _templates:
-
-Templates
-=========
-
-Templates are the entry point for the |cubicweb| view system. As seen
-in :ref:`views_base_class`, there are two kinds of views: the
-templatable and non-templatable.
-
-
-Non-templatable views
----------------------
-
-Non-templatable views are standalone. They are responsible for all the details
-such as setting a proper content type (or mime type), the proper document
-headers, namespaces, etc. Examples are pure xml views such as RSS or Semantic Web
-views (`SIOC`_, `DOAP`_, `FOAF`_, `Linked Data`_, etc.), and views which generate
-binary files (pdf, excel files, etc.)
-
-.. _`SIOC`: http://sioc-project.org/
-.. _`DOAP`: http://trac.usefulinc.com/doap
-.. _`FOAF`: http://www.foaf-project.org/
-.. _`Linked Data`: http://linkeddata.org/
-
-
-To notice that a view is not templatable, you just have to set the
-view's class attribute `templatable` to `False`. In this case, it
-should set the `content_type` class attribute to the correct MIME
-type. By default, it is text/xhtml. Additionally, if your view
-generate a binary file, you have to set the view's class attribute
-`binary` to `True` too.
-
-
-Templatable views
------------------
-
-Templatable views are not concerned with such pesky details. They
-leave it to the template. Conversely, the template's main job is to:
-
-* set up the proper document header and content type
-* define the general layout of a document
-* invoke adequate views in the various sections of the document
-
-
-Look at :mod:`cubicweb.web.views.basetemplates` and you will find the base
-templates used to generate (X)HTML for your application. The most important
-template there is :class:`~cubicweb.web.views.basetemplates.TheMainTemplate`.
-
-.. _the_main_template_layout:
-
-TheMainTemplate
-~~~~~~~~~~~~~~~
-
-.. _the_main_template_sections:
-
-Layout and sections
-```````````````````
-
-A page is composed as indicated on the schema below :
-
-.. image:: ../../images/main_template.png
-
-The sections dispatches specific views:
-
-* `header`: the rendering of the header is delegated to the
-  `htmlheader` view, whose default implementation can be found in
-  ``basetemplates.py`` and which does the following things:
-
-    * inject the favicon if there is one
-    * inject the global style sheets and javascript resources
-    * call and display a link to an rss component if there is one available
-
-  it also sets up the page title, and fills the actual
-  `header` section with top-level components, using the `header` view, which:
-
-    * tries to display a logo, the name of the application and the `breadcrumbs`
-    * provides a login status area
-    * provides a login box (hiden by default)
-
-* `left column`: this is filled with all selectable boxes matching the
-  `left` context (there is also a right column but nowadays it is
-  seldom used due to bad usability)
-
-* `contentcol`: this is the central column; it is filled with:
-
-    * the `rqlinput` view (hidden by default)
-    * the `applmessages` component
-    * the `contentheader` view which in turns dispatches all available
-      content navigation components having the `navtop` context (this
-      is used to navigate through entities implementing the IPrevNext
-      interface)
-    * the view that was given as input to the template's `call`
-      method, also dealing with pagination concerns
-    * the `contentfooter`
-
-* `footer`: adds all footer actions
-
-.. note::
-
-  How and why a view object is given to the main template is explained
-  in the :ref:`publisher` chapter.
-
-Configure the main template
-```````````````````````````
-
-You can overload some methods of the
-:class:`~cubicweb.web.views.basetemplates.TheMainTemplate`, in order to fulfil
-your needs. There are also some attributes and methods which can be defined on a
-view to modify the base template behaviour:
-
-* `paginable`: if the result set is bigger than a configurable size, your result
-  page will be paginated by default. You can set this attribute to `False` to
-  avoid this.
-
-* `binary`: boolean flag telling if the view generates some text or a binary
-  stream.  Default to False. When view generates text argument given to `self.w`
-  **must be a unicode string**, encoded string otherwise.
-
-* `content_type`, view's content type, default to 'text/xhtml'
-
-* `templatable`, boolean flag telling if the view's content should be returned
-  directly (when `False`) or included in the main template layout (including
-  header, boxes and so on).
-
-* `page_title()`, method that should return a title that will be set as page
-  title in the html headers.
-
-* `html_headers()`, method that should return a list of HTML headers to be
-  included the html headers.
-
-
-You can also modify certain aspects of the main template of a page
-when building a url or setting these parameters in the req.form:
-
-* `__notemplate`, if present (whatever the value assigned), only the content view
-  is returned
-
-* `__force_display`, if present and its value is not null, no pagination whatever
-  the number of entities to display (e.g. similar effect as view's `paginable`
-  attribute described above.
-
-* `__method`, if the result set to render contains only one entity and this
-  parameter is set, it refers to a method to call on the entity by passing it the
-  dictionary of the forms parameters, before going the classic way (through step
-  1 and 2 described juste above)
-
-* `vtitle`, a title to be set as <h1> of the content
-
-Other templates
-~~~~~~~~~~~~~~~
-
-There are also the following other standard templates:
-
-* :class:`cubicweb.web.views.basetemplates.LogInTemplate`
-* :class:`cubicweb.web.views.basetemplates.LogOutTemplate`
-* :class:`cubicweb.web.views.basetemplates.ErrorTemplate` specializes
-  :class:`~cubicweb.web.views.basetemplates.TheMainTemplate` to do
-  proper end-user output if an error occurs during the computation of
-  TheMainTemplate (it is a fallback view).
--- a/doc/book/en/devweb/views/baseviews.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-Base views
-----------
-
-|cubicweb| provides a lot of standard views, that can be found in
-:mod:`cubicweb.web.views` sub-modules.
-
-A certain number of views are used to build the web interface, which apply to one
-or more entities. As other appobjects, their identifier is what distinguish them
-from each others. The most generic ones, found in
-:mod:`cubicweb.web.views.baseviews`, are described below.
-
-You'll probably want to customize one or more of the described views which are
-default, generic, implementations.
-
-
-.. automodule:: cubicweb.web.views.baseviews
-
-You will also find modules providing some specific services:
-
-.. automodule:: cubicweb.web.views.navigation
-
--- a/doc/book/en/devweb/views/boxes.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-Boxes
------
-
-(:mod:`cubicweb.web.views.boxes`)
-
-*sidebox*
-  This view displays usually a side box of some related entities
-  in a primary view.
-
-The action box
-~~~~~~~~~~~~~~~
-
-The ``add_related`` is an automatic menu in the action box that allows to create
-an entity automatically related to the initial entity (context in
-which the box is displayed). By default, the links generated in this
-box are computed from the schema properties of the displayed entity,
-but it is possible to explicitly specify them thanks to the
-`cubicweb.web.views.uicfg.rmode` *relation tag*:
-
-* `link`, indicates that a relation is in general created pointing
-  to an existing entity and that we should not to display a link
-  for this relation
-
-* `create`, indicates that a relation is in general created pointing
-  to new entities and that we should display a link to create a new
-  entity and link to it automatically
-
-
-If necessary, it is possible to overwrite the method
-`relation_mode(rtype, targettype, x='subject')` to dynamically
-compute a relation creation category.
-
-Please note that if at least one action belongs to the `addrelated` category,
-the automatic behavior is desactivated in favor of an explicit behavior
-(e.g. display of `addrelated` category actions only).
-
--- a/doc/book/en/devweb/views/breadcrumbs.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-Breadcrumbs
------------
-
-Breadcrumbs are a navigation component to help the user locate himself
-along a path of entities.
-
-Display
-~~~~~~~
-
-Breadcrumbs are displayed by default in the header section (see
-:ref:`the_main_template_sections`).  With the default main template,
-the header section is composed by the logo, the application name,
-breadcrumbs and, at the most right, the login box. Breadcrumbs are
-displayed just next to the application name, thus they begin with a
-separator.
-
-Here is the header section of the CubicWeb's forge:
-
-.. image:: ../../images/breadcrumbs_header.png
-
-There are three breadcrumbs components defined in
-:mod:`cubicweb.web.views.ibreadcrumbs`:
-
-- `BreadCrumbEntityVComponent`: displayed for a result set with one line
-  if the entity is adaptable to ``IBreadCrumbsAdapter``.
-- `BreadCrumbETypeVComponent`: displayed for a result set with more than
-  one line, but with all entities of the same type which can adapt to
-  ``IBreadCrumbsAdapter``.
-- `BreadCrumbAnyRSetVComponent`: displayed for any other result set.
-
-Building breadcrumbs
-~~~~~~~~~~~~~~~~~~~~
-
-The ``IBreadCrumbsAdapter`` adapter is defined in the
-:mod:`cubicweb.web.views.ibreadcrumbs` module. It specifies that an
-entity which implements this interface must have a ``breadcrumbs`` and
-a ``parent_entity`` method. A default implementation for each is
-provided. This implementation expoits the ITreeAdapter.
-
-.. note::
-
-   Redefining the breadcrumbs is the hammer way to do it. Another way
-   is to define an `ITreeAdapter` adapter on an entity type. If
-   available, it will be used to compute breadcrumbs.
-
-Here is the API of the ``IBreadCrumbsAdapter`` class:
-
-.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbsAdapter.parent_entity
-.. automethod:: cubicweb.web.views.ibreadcrumbs.IBreadCrumbsAdapter.breadcrumbs
-
-If the breadcrumbs method return a list of entities, the
-``cubicweb.web.views.ibreadcrumbs.BreadCrumbView`` is used to display
-the elements.
-
-By default, for any entity, if recurs=True, breadcrumbs method returns
-a list of entities, else a list of a simple string.
-
-In order to see a hierarchical breadcrumbs, entities must have a
-``parent`` method which returns the parent entity. By default this
-method doesn't exist on entity, given that it can not be guessed.
--- a/doc/book/en/devweb/views/idownloadable.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-The 'download' views
-====================
-
-.. automodule:: cubicweb.web.views.idownloadable
-
-Components
-----------
-
-.. autoclass:: cubicweb.web.views.idownloadable.DownloadBox
-
-Download views
---------------
-
-.. autoclass:: cubicweb.web.views.idownloadable.DownloadView
-.. autoclass:: cubicweb.web.views.idownloadable.DownloadLinkView
-.. autoclass:: cubicweb.web.views.idownloadable.IDownloadablePrimaryView
-
-Embedded views
---------------
-
-.. autoclass:: cubicweb.web.views.idownloadable.ImageView
-.. autoclass:: cubicweb.web.views.idownloadable.EHTMLView
--- a/doc/book/en/devweb/views/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-The View system
-===============
-
-This chapter aims to describe the concept of a `view` used all along
-the development of a web application and how it has been implemented
-in |cubicweb|.
-
-
-.. toctree::
-   :maxdepth: 3
-
-   views
-   basetemplates
-   primary
-   reledit
-   baseviews
-   startup
-   boxes
-   table
-   xmlrss
-   urlpublish
-   breadcrumbs
-   idownloadable
-   wdoc
-
-..   editforms
-..   embedding
-
--- a/doc/book/en/devweb/views/primary.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-.. _primary_view:
-
-The Primary View
------------------
-
-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.
-
-It is automatically selected on a one line result set containing an
-entity.
-
-It lives in the :mod:`cubicweb.web.views.primary` module.
-
-The *primary* view is supposed to render a maximum of informations about the
-entity.
-
-.. _primary_view_layout:
-
-Layout
-``````
-
-The primary view has the following layout.
-
-.. image:: ../../images/primaryview_template.png
-
-.. _primary_view_configuration:
-
-Primary view configuration
-``````````````````````````
-
-If you want to customize the primary view of an entity, overriding the primary
-view class may not be necessary. For simple adjustments (attributes or relations
-display locations and styles), a much simpler way is to use uicfg.
-
-Attributes/relations display location
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-In the primary view, there are three sections where attributes and
-relations can be displayed (represented in pink in the image above):
-
-* 'attributes'
-* 'relations'
-* 'sideboxes'
-
-**Attributes** can only be displayed in the attributes section (default
-  behavior). They can also be hidden. By default, attributes of type `Password`
-  and `Bytes` are hidden.
-
-For instance, to hide the ``title`` attribute of the ``Blog`` entity:
-
-.. sourcecode:: python
-
-   from cubicweb.web.views import uicfg
-   uicfg.primaryview_section.tag_attribute(('Blog', 'title'), 'hidden')
-
-**Relations** can be either displayed in one of the three sections or hidden.
-
-For relations, there are two methods:
-
-* ``tag_object_of`` for modifying the primary view of the object
-* ``tag_subject_of`` for modifying the primary view of the subject
-
-These two methods take two arguments:
-
-* a triplet ``(subject, relation_name, object)``, where subject or object can be replaced with ``'*'``
-* the section name or ``hidden``
-
-.. sourcecode:: python
-
-   pv_section = uicfg.primaryview_section
-   # hide every relation `entry_of` in the `Blog` primary view
-   pv_section.tag_object_of(('*', 'entry_of', 'Blog'), 'hidden')
-
-   # display `entry_of` relations in the `relations`
-   # section in the `BlogEntry` primary view
-   pv_section.tag_subject_of(('BlogEntry', 'entry_of', '*'), 'relations')
-
-
-Display content
-^^^^^^^^^^^^^^^
-
-You can use ``primaryview_display_ctrl`` to customize the display of attributes
-or relations. Values of ``primaryview_display_ctrl`` are dictionaries.
-
-
-Common keys for attributes and relations are:
-
-* ``vid``: specifies the regid of the view for displaying the attribute or the relation.
-
-  If ``vid`` is not specified, the default value depends on the section:
-    * ``attributes`` section: 'reledit' view
-    * ``relations`` section: 'autolimited' view
-    * ``sideboxes`` section: 'sidebox' view
-
-* ``order``: int used to control order within a section. When not specified,
-  automatically set according to order in which tags are added.
-
-* ``label``: label for the relations section or side box
-
-* ``showlabel``: boolean telling whether the label is displayed
-
-.. sourcecode:: python
-
-   # let us remind the schema of a blog entry
-   class BlogEntry(EntityType):
-       title = String(required=True, fulltextindexed=True, maxsize=256)
-       publish_date = Date(default='TODAY')
-       content = String(required=True, fulltextindexed=True)
-       entry_of = SubjectRelation('Blog', cardinality='?*')
-
-   # now, we want to show attributes
-   # with an order different from that in the schema definition
-   view_ctrl = uicfg.primaryview_display_ctrl
-   for index, attr in enumerate('title', 'content', 'publish_date'):
-       view_ctrl.tag_attribute(('BlogEntry', attr), {'order': index})
-
-By default, relations displayed in the 'relations' section are being displayed by
-the 'autolimited' view. This view will use comma separated values, or list view
-and/or limit your rset if there is too much items in it (and generate the "view
-all" link in this case).
-
-You can control this view by setting the following values in the
-`primaryview_display_ctrl` relation tag:
-
-* `limit`, maximum number of entities to display. The value of the
-  'navigation.related-limit'  cwproperty is used by default (which is 8 by default).
-  If None, no limit.
-
-* `use_list_limit`, number of entities until which they should be display as a list
-  (eg using the 'list' view). Below that limit, the 'csv' view is used. If None,
-  display using 'csv' anyway.
-
-* `subvid`, the subview identifier (eg view that should be used of each item in the
-  list)
-
-Notice you can also use the `filter` key to set up a callback taking the related
-result set as argument and returning it filtered, to do some arbitrary filtering
-that can't be done using rql for instance.
-
-
-.. sourcecode:: python
-
-   pv_section = uicfg.primaryview_section
-   # in `CWUser` primary view, display `created_by`
-   # relations in relations section
-   pv_section.tag_object_of(('*', 'created_by', 'CWUser'), 'relations')
-
-   # display this relation as a list, sets the label,
-   # limit the number of results and filters on comments
-   def filter_comment(rset):
-       return rset.filtered_rset(lambda x: x.e_schema == 'Comment')
-   pv_ctrl = uicfg.primaryview_display_ctrl
-   pv_ctrl.tag_object_of(('*', 'created_by', 'CWUser'),
-                         {'vid': 'list', 'label': _('latest comment(s):'),
-                          'limit': True,
-                          'filter': filter_comment})
-
-.. warning:: with the ``primaryview_display_ctrl`` rtag, the subject or the
-   object of the relation is ignored for respectively ``tag_object_of`` or
-   ``tag_subject_of``. To avoid warnings during execution, they should be set to
-   ``'*'``.
-
-
-.. automodule:: cubicweb.web.views.primary
-
-
-Example of customization and creation
-`````````````````````````````````````
-
-We'll show you now an example of a ``primary`` view and how to customize it.
-
-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.predicates import is_instance
-   from cubicweb.web.views.primary import Primaryview
-
-   class BlogEntryPrimaryView(PrimaryView):
-       __select__ = PrimaryView.__select__ & is_instance('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)
-
-
-The above source code defines a new primary view for
-``BlogEntry``. The `__reid__` class attribute is not repeated there since it
-is inherited through the `primary.PrimaryView` class.
-
-The selector for this view chains the selector of the inherited class
-with its own specific criterion.
-
-The view method ``self.w()`` is used to output data. Here `lines
-08-09` output HTML for the publication date of the entry.
-
-.. image:: ../../images/lax-book_09-new-view-blogentry_en.png
-   :alt: blog entries now look much nicer
-
-Let us now improve the primary view of a blog
-
-.. sourcecode:: python
-
- from logilab.mtconverter import xml_escape
- from cubicweb.predicates import is_instance, one_line_rset
- from cubicweb.web.views.primary import Primaryview
-
- class BlogPrimaryView(PrimaryView):
-     __regid__ = 'primary'
-     __select__ = PrimaryView.__select__ & is_instance('Blog')
-     rql = 'Any BE ORDERBY D DESC WHERE BE entry_of B, BE publish_date D, B eid %(b)s'
-
-     def render_entity_relations(self, entity):
-         rset = self._cw.execute(self.rql, {'b' : entity.eid})
-         for entry in rset.entities():
-             self.w(u'<p>%s</p>' % entry.view('inblogcontext'))
-
- class BlogEntryInBlogView(EntityView):
-     __regid__ = 'inblogcontext'
-     __select__ = is_instance('BlogEntry')
-
-     def cell_call(self, row, col):
-         entity = self.cw_rset.get_entity(row, col)
-         self.w(u'<a href="%s" title="%s">%s</a>' %
-                entity.absolute_url(),
-                xml_escape(entity.content[:50]),
-                xml_escape(entity.description))
-
-This happens in two places. First we override the
-render_entity_relations method of a Blog's primary view. Here we want
-to display our blog entries in a custom way.
-
-At `line 10`, a simple request is made to build a result set with all
-the entities linked to the current ``Blog`` entity by the relationship
-``entry_of``. The part of the framework handling the request knows
-about the schema and infers that such entities have to be of the
-``BlogEntry`` kind and retrieves them (in the prescribed publish_date
-order).
-
-The request returns a selection of data called a result set. Result
-set objects have an .entities() method returning a generator on
-requested entities (going transparently through the `ORM` layer).
-
-At `line 13` the view 'inblogcontext' is applied to each blog entry to
-output HTML. (Note that the 'inblogcontext' view is not defined
-whatsoever in *CubicWeb*. You are absolutely free to define whole view
-families.) We juste arrange to wrap each blogentry output in a 'p'
-html element.
-
-Next, we define the 'inblogcontext' view. This is NOT a primary view,
-with its well-defined sections (title, metadata, attribtues,
-relations/boxes). All a basic view has to define is cell_call.
-
-Since views are applied to result sets which can be tables of data, we
-have to recover the entity from its (row,col)-coordinates (`line
-20`). Then we can spit some HTML.
-
-.. warning::
-
-  Be careful: all strings manipulated in *CubicWeb* are actually
-  unicode strings. While web browsers are usually tolerant to
-  incoherent encodings they are being served, we should not abuse
-  it. Hence we have to properly escape our data. The xml_escape()
-  function has to be used to safely fill (X)HTML elements from Python
-  unicode strings.
-
-Assuming we added entries to the blog titled `MyLife`, displaying it
-now allows to read its description and all its entries.
-
-.. image:: ../../images/lax-book_10-blog-with-two-entries_en.png
-   :alt: a blog and all its entries
-
--- a/doc/book/en/devweb/views/reledit.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-.. _reledit:
-
-The "Click and Edit" (also `reledit`) View
-------------------------------------------
-
-The principal way to update data through the Web UI is through the
-`modify` action on entities, which brings a full form. This is
-described in the :ref:`webform` chapter.
-
-There is however another way to perform piecewise edition of entities
-and relations, using a specific `reledit` (for *relation edition*)
-view from the :mod:`cubicweb.web.views.reledit` module.
-
-This is typically applied from the default Primary View (see
-:ref:`primary_view`) on the attributes and relation section. It makes
-small editions more convenient.
-
-Of course, this can be used customely in any other view. Here come
-some explanation about its capabilities and instructions on the way to
-use it.
-
-Using `reledit`
-***************
-
-Let's start again with a simple example:
-
-.. sourcecode:: python
-
-   class Company(EntityType):
-        name = String(required=True, unique=True)
-        boss = SubjectRelation('Person', cardinality='1*')
-        status = SubjectRelation('File', cardinality='?*', composite='subject')
-
-In some view code we might want to show these attributes/relations and
-allow the user to edit each of them in turn without having to leave
-the current page. We would write code as below:
-
-.. sourcecode:: python
-
-   company.view('reledit', rtype='name', default_value='<name>') # editable name attribute
-   company.view('reledit', rtype='boss') # editable boss relation
-   company.view('reledit', rtype='status') # editable attribute-like relation
-
-If one wanted to edit the company from a boss's point of view, one
-would have to indicate the proper relation's role. By default the role
-is `subject`.
-
-.. sourcecode:: python
-
-   person.view('reledit', rtype='boss', role='object')
-
-Each of these will provide with a different editing widget. The `name`
-attribute will obviously get a text input field. The `boss` relation
-will be edited through a selection box, allowing to pick another
-`Person` as boss. The `status` relation, given that it defines Company
-as a composite entity with one file inside, will provide additional actions
-
-* to `add` a `File` when there is one
-* to `delete` the `File` (if the cardinality allows it)
-
-Moreover, editing the relation or using the `add` action leads to an
-embedded edition/creation form allowing edition of the target entity
-(which is `File` in our example) instead of merely allowing to choose
-amongst existing files.
-
-The `reledit_ctrl` rtag
-***********************
-
-The behaviour of reledited attributes/relations can be finely
-controlled using the reledit_ctrl rtag, defined in
-:mod:`cubicweb.web.views.uicfg`.
-
-This rtag provides four control variables:
-
-* ``default_value``: alternative default value
-   The default value is what is shown when there is no value.
-* ``reload``: boolean, eid (to reload to) or function taking subject
-   and returning bool/eid This is useful when editing a relation (or
-   attribute) that impacts the url or another parts of the current
-   displayed page. Defaults to false.
-* ``rvid``: alternative view id (as str) for relation or composite
-   edition Default is 'incontext' or 'csv' depending on the
-   cardinality. They can also be statically changed by subclassing
-   ClickAndEditFormView and redefining _one_rvid (resp. _many_rvid).
-* ``edit_target``: 'rtype' (to edit the relation) or 'related' (to
-   edit the related entity) This controls whether to edit the relation
-   or the target entity of the relation.  Currently only one-to-one
-   relations support target entity edition. By default, the 'related'
-   option is taken whenever the relation is composite and one-to-one.
-
-Let's see how to use these controls.
-
-.. sourcecode:: python
-
-    from logilab.mtconverter import xml_escape
-    from cubicweb.web.views.uicfg import reledit_ctrl
-    reledit_ctrl.tag_attribute(('Company', 'name'),
-                               {'reload': lambda x:x.eid,
-                                'default_value': xml_escape(u'<logilab tastes better>')})
-    reledit_ctrl.tag_object_of(('*', 'boss', 'Person'), {'edit_target': 'related'})
-
-The `default_value` needs to be an xml escaped unicode string.
-
-The `edit_target` tag on the `boss` relation being set to `related` will
-ensure edition of the `Person` entity instead (using a standard
-automatic form) of the association of Company and Person.
-
-Finally, the `reload` key accepts either a boolean, an eid or a
-unicode string representing a url. If an eid is provided, it will be
-internally transformed into a url. The eid/url case helps when one
-needs to reload and the current url is inappropriate. A common case is
-edition of a key attribute, which is part of the current url. If one
-user changed the Company's name from `lozilab` to `logilab`, reloading
-on http://myapp/company/lozilab would fail. Providing the entity's
-eid, then, forces to reload on something like http://myapp/company/42,
-which always work.
-
-
-Disable `reledit`
-*****************
-
-By default, `reledit` is available on attributes and relations displayed in
-the 'attribute' section of the default primary view.  If you want to disable
-it for some attribute or relation, you have use `uicfg`:
-
-.. sourcecode:: python
-
-    from cubicweb.web.views.uicfg import primaryview_display_ctrl as _pvdc
-    _pvdc.tag_attribute(('Company', 'name'), {'vid': 'incontext'})
-
-To deactivate it everywhere it's used automatically, you may use the code snippet
-below somewhere in your cube's views:
-
-.. sourcecode:: python
-
-    from cubicweb.web.views import reledit
-
-    class DeactivatedAutoClickAndEditFormView(reledit.AutoClickAndEditFormView):
-	def _should_edit_attribute(self, rschema):
-	    return False
-
-	def _should_edit_attribute(self, rschema, role):
-	    return False
-
-    def registration_callback(vreg):
-	vreg.register_and_replace(DeactivatedAutoClickAndEditFormView,
-				  reledit.AutoClickAndEditFormView)
-
-
--- a/doc/book/en/devweb/views/startup.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-Startup views
--------------
-
-Startup views are views requiring no context, from which you usually start
-browsing (for instance the index page). The usual selectors are
-:class:`~cubicweb.predicates.none_rset` or :class:`~logilab.common.registry.yes`.
-
-You'll find here a description of startup views provided by the framework.
-
-.. automodule:: cubicweb.web.views.startup
-
-
-Other startup views:
-
-*schema*
-    A view dedicated to the display of the schema of the instance
-
-.. XXX to be continued
\ No newline at end of file
--- a/doc/book/en/devweb/views/table.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-Table views
------------
-
-.. automodule:: cubicweb.web.views.tableview
-
-Example
-```````
-
-Let us take an example from the timesheet cube:
-
-.. sourcecode:: python
-
-    class ActivityResourcesTable(EntityView):
-        __regid__ = 'activity.resources.table'
-        __select__ = is_instance('Activity')
-
-        def call(self, showresource=True):
-            eids = ','.join(str(row[0]) for row in self.cw_rset)
-            rql = ('Any R,D,DUR,WO,DESCR,S,A, SN,RT,WT ORDERBY D DESC '
-                   'WHERE '
-                   '   A is Activity, A done_by R, R title RT, '
-                   '   A diem D, A duration DUR, '
-                   '   A done_for WO, WO title WT, '
-                   '   A description DESCR, A in_state S, S name SN, '
-                   '   A eid IN (%s)' % eids)
-            rset = self._cw.execute(rql)
-            self.wview('resource.table', rset, 'null')
-
-    class ResourcesTable(RsetTableView):
-        __regid__ = 'resource.table'
-        # notice you may wish a stricter selector to check rql's shape
-        __select__ = is_instance('Resource')
-        # my table headers
-        headers  = ['Resource', 'diem', 'duration', 'workpackage', 'description', 'state']
-        # I want a table where attributes are editable (reledit inside)
-        finalvid = 'editable-final'
-
-        cellvids = {3: 'editable-final'}
-        # display facets and actions with a menu
-        layout_args = {'display_filter': 'top',
-                       'add_view_actions': None}
-
-To obtain an editable table, you may specify the 'editable-table' view identifier
-using some of `cellvids`, `finalvid` or `nonfinalvid`.
-
-The previous example results in:
-
-.. image:: ../../images/views-table-shadow.png
-
-In order to activate table filter mechanism, the `display_filter` option is given
-as a layout argument. A small arrow will be displayed at the table's top right
-corner. Clicking on `show filter form` action, will display the filter form as
-below:
-
-.. image:: ../../images/views-table-filter-shadow.png
-
-By the same way, you can display additional actions for the selected entities
-by setting `add_view_actions` layout option to `True`. This will add actions
-returned by the view's :meth:`~cubicweb.web.views.tableview.TableMixIn.table_actions`.
-
-You can notice that all columns of the result set are not displayed. This is
-because of given `headers`, implying to display only columns from 0 to
-len(headers).
-
-Also Notice that the `ResourcesTable` view relies on a particular rql shape
-(which is not ensured by the way, the only checked thing is that the result set
-contains instance of the `Resource` type). That usually implies that you can't
-use this view for user specific queries (e.g. generated by facets or typed
-manually).
-
-
-So another option would be to write this view using
-:class:`~cubicweb.web.views.tableview.EntityTableView`, as below.
-
-.. sourcecode:: python
-
-    class ResourcesTable(EntityTableView):
-        __regid__ = 'resource.table'
-        __select__ = is_instance('Resource')
-        # table columns definition
-        columns  = ['resource', 'diem', 'duration', 'workpackage', 'description', 'in_state']
-        # I want a table where attributes are editable (reledit inside)
-        finalvid = 'editable-final'
-        # display facets and actions with a menu
-        layout_args = {'display_filter': 'top',
-                       'add_view_actions': None}
-
-        def workpackage_cell(entity):
-            activity = entity.reverse_done_in[0]
-            activity.view('reledit', rtype='done_for', role='subject', w=w)
-        def workpackage_sortvalue(entity):
-            activity = entity.reverse_done_in[0]
-            return activity.done_for[0].sortvalue()
-
-        column_renderers = {
-            'resource': MainEntityColRenderer(),
-            'workpackage': EntityTableColRenderer(
-               header='Workpackage',
-               renderfunc=worpackage_cell,
-               sortfunc=worpackage_sortvalue,),
-            'in_state': EntityTableColRenderer(
-               renderfunc=lambda w,x: w(x.cw_adapt_to('IWorkflowable').printable_state),
-               sortfunc=lambda x: x.cw_adapt_to('IWorkflowable').printable_state),
-         }
-
-Notice the following point:
-
-* `cell_<column>(w, entity)` will be searched for rendering the content of a
-  cell. If not found, `column` is expected to be an attribute of `entity`.
-
-* `cell_sortvalue_<column>(entity)` should return a typed value to use for
-  javascript sorting or None for not sortable columns (the default).
-
-* The :func:`etable_entity_sortvalue` decorator will set a 'sortvalue' function
-  for the column containing the main entity (the one given as argument to all
-  methods), which will call `entity.sortvalue()`.
-
-* You can set a column header using the :func:`etable_header_title` decorator.
-  This header will be translated. If it's not an already existing msgid, think
-  to mark it using `_()` (the example supposes headers are schema defined msgid).
-
-
-Pro/cons of each approach
-`````````````````````````
-:class:`EntityTableView` and :class:`RsetableView` provides basically the same
-set of features, though they don't share the same properties. Let's try to sum
-up pro and cons of each class.
-
-* `EntityTableView` view is:
-
-  - more verbose, but usually easier to understand
-
-  - easily extended (easy to add/remove columns for instance)
-
-  - doesn't rely on a particular rset shape. Simply give it a title and will be
-    listed in the 'possible views' box if any.
-
-* `RsetTableView` view is:
-
-  - hard to beat to display barely a result set, or for cases where some of
-    `headers`, `displaycols` or `cellvids` could be defined to enhance the table
-    while you don't care about e.g. pagination or facets.
-
-  - hardly extensible, as you usually have to change places where the view is
-    called to modify the RQL (hence the view's result set shape).
--- a/doc/book/en/devweb/views/urlpublish.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-URL publishing
---------------
-
-(:mod:`cubicweb.web.views.urlpublishing`)
-
-.. automodule:: cubicweb.web.views.urlpublishing
-
-.. autoclass:: cubicweb.web.views.urlpublishing.URLPublisherComponent
-   :members:
-
-
-You can write your own *URLPathEvaluator* class to handle custom paths.
-For instance, if you want */my-card-id* to redirect to the corresponding
-card's primary view, you would write:
-
-.. sourcecode:: python
-
-    class CardWikiidEvaluator(URLPathEvaluator):
-        priority = 3 # make it be evaluated *before* RestPathEvaluator
-
-        def evaluate_path(self, req, segments):
-            if len(segments) != 1:
-                raise PathDontMatch()
-            rset = req.execute('Any C WHERE C wikiid %(w)s',
-                               {'w': segments[0]})
-            if len(rset) == 0:
-                # Raise NotFound if no card is found
-                raise PathDontMatch()
-            return None, rset
-
-On the other hand, you can also deactivate some of the standard
-evaluators in your final application. The only thing you have to
-do is to unregister them, for instance in a *registration_callback*
-in your cube:
-
-.. sourcecode:: python
-
-    def registration_callback(vreg):
-        vreg.unregister(RestPathEvaluator)
-
-You can even replace the :class:`cubicweb.web.views.urlpublishing.URLPublisherComponent`
-class if you want to customize the whole toolchain process or if you want
-to plug into an early enough extension point to control your request
-parameters:
-
-.. sourcecode:: python
-
-    class SanitizerPublisherComponent(URLPublisherComponent):
-        """override default publisher component to explicitly ignore
-        unauthorized request parameters in anonymous mode.
-        """
-        unauthorized_form_params = ('rql', 'vid', '__login', '__password')
-
-        def process(self, req, path):
-            if req.session.anonymous_session:
-                self._remove_unauthorized_params(req)
-            return super(SanitizerPublisherComponent, self).process(req, path)
-
-        def _remove_unauthorized_params(self, req):
-            for param in req.form.keys():
-                if param in self.unauthorized_form_params:
-                     req.form.pop(param)
-
-
-    def registration_callback(vreg):
-        vreg.register_and_replace(SanitizerPublisherComponent, URLPublisherComponent)
-
-
-.. autoclass:: cubicweb.web.views.urlpublishing.RawPathEvaluator
-.. autoclass:: cubicweb.web.views.urlpublishing.EidPathEvaluator
-.. autoclass:: cubicweb.web.views.urlpublishing.URLRewriteEvaluator
-.. autoclass:: cubicweb.web.views.urlpublishing.RestPathEvaluator
-.. autoclass:: cubicweb.web.views.urlpublishing.ActionPathEvaluator
-
-URL rewriting
--------------
-
-(:mod:`cubicweb.web.views.urlrewrite`)
-
-.. autoclass:: cubicweb.web.views.urlrewrite.URLRewriter
-   :members:
-
-.. autoclass:: cubicweb.web.views.urlrewrite.SimpleReqRewriter
-   :members:
-
-.. autoclass:: cubicweb.web.views.urlrewrite.SchemaBasedRewriter
-   :members:
-
-
-``SimpleReqRewriter`` is enough for a certain number of simple cases. If it is not sufficient, ``SchemaBasedRewriter`` allows to do more elaborate things.
-
-Here is an example of ``SimpleReqRewriter`` usage with plain string:
-
-.. sourcecode:: python
-
-   from cubicweb.web.views.urlrewrite import SimpleReqRewriter
-   class TrackerSimpleReqRewriter(SimpleReqRewriter):
-       rules = [
-        ('/versions', dict(vid='versionsinfo')),
-        ]
-
-When the url is `<base_url>/versions`, the view with the __regid__ `versionsinfo` is displayed.
-
-Here is an example of ``SimpleReqRewriter`` usage with regular expressions:
-
-.. sourcecode:: python
-
-    from cubicweb.web.views.urlrewrite import (
-        SimpleReqRewriter, rgx)
-
-    class BlogReqRewriter(SimpleReqRewriter):
-        rules = [
-            (rgx('/blogentry/([a-z_]+)\.rss'),
-             dict(rql=('Any X ORDERBY CD DESC LIMIT 20 WHERE X is BlogEntry,'
-                       'X creation_date CD, X created_by U, '
-                       'U login "%(user)s"'
-                       % {'user': r'\1'}), vid='rss'))
-            ]
-
-When a url matches the regular expression, the view with the __regid__
-`rss` which match the result set is displayed.
-
-Here is an example of ``SchemaBasedRewriter`` usage:
-
-.. sourcecode:: python
-
-    from cubicweb.web.views.urlrewrite import (
-        SchemaBasedRewriter, rgx, build_rset)
-
-    class TrackerURLRewriter(SchemaBasedRewriter):
-        rules = [
-            (rgx('/project/([^/]+)/([^/]+)/tests'),
-             build_rset(rql='Version X WHERE X version_of P, P name %(project)s, X num %(num)s',
-                        rgxgroups=[('project', 1), ('num', 2)], vid='versiontests')),
-            ]
--- a/doc/book/en/devweb/views/views.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-
-.. _Views:
-
-Principles
-----------
-
-We'll start with a description of the interface providing a basic
-understanding of the available classes and methods, then detail the
-view selection principle.
-
-A `View` is an object responsible for the rendering of data from the
-model into an end-user consummable form. They typically churn out an
-XHTML stream, but there are views concerned with email other non-html
-outputs.
-
-.. _views_base_class:
-
-Discovering possible views
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-It is possible to configure the web user interface to have a left box
-showing all the views than can be applied to the current result set.
-
-To enable this, click on your login at the top right corner. Chose
-"user preferences", then "boxes", then "possible views box" and check
-"visible = yes" before validating your changes.
-
-The views listed there we either not selected because of a lower
-score, or they were deliberately excluded by the main template logic.
-
-
-Basic class for views
-~~~~~~~~~~~~~~~~~~~~~
-
-Class :class:`~cubicweb.view.View`
-``````````````````````````````````
-
-.. autoclass:: cubicweb.view.View
-
-The basic interface for views is as follows (remember that the result
-set has a tabular structure with rows and columns, hence cells):
-
-* `render(**context)`, render the view by calling `call` or
-  `cell_call` depending on the context
-
-* `call(**kwargs)`, call the view for a complete result set or null
-  (the default implementation calls `cell_call()` on each cell of the
-  result set)
-
-* `cell_call(row, col, **kwargs)`, call the view for a given cell of a
-  result set (`row` and `col` being integers used to access the cell)
-
-* `url()`, returns the URL enabling us to get the view with the current
-  result set
-
-* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of
-  identifier `__vid` on the given result set. It is possible to give a
-  fallback view identifier that will be used if the requested view is
-  not applicable to the result set.
-
-* `html_headers()`, returns a list of HTML headers to be set by the
-  main template
-
-* `page_title()`, returns the title to use in the HTML header `title`
-
-Other basic view classes
-````````````````````````
-Here are some of the subclasses of :class:`~cubicweb.view.View` defined in :mod:`cubicweb.view`
-that are more concrete as they relate to data rendering within the application:
-
-.. autoclass:: cubicweb.view.EntityView
-.. autoclass:: cubicweb.view.StartupView
-.. autoclass:: cubicweb.view.EntityStartupView
-.. autoclass:: cubicweb.view.AnyRsetView
-
-Examples of views class
-```````````````````````
-
-- Using `templatable`, `content_type` and HTTP cache configuration
-
-.. sourcecode:: python
-
-    class RSSView(XMLView):
-        __regid__ = 'rss'
-        title = _('rss')
-        templatable = False
-        content_type = 'text/xml'
-        http_cache_manager = MaxAgeHTTPCacheManager
-        cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
-
-
-- Using a custom selector
-
-.. sourcecode:: python
-
-    class SearchForAssociationView(EntityView):
-        """view called by the edition view when the user asks
-        to search for something to link to the edited eid
-        """
-        __regid__ = 'search-associate'
-        title = _('search for association')
-        __select__ = one_line_rset() & match_search_state('linksearch') & is_instance('Any')
-
-
-XML views, binaries views...
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-For views generating other formats than HTML (an image generated dynamically
-for example), and which can not simply be included in the HTML page generated
-by the main template (see above), you have to:
-
-* set the attribute `templatable` of the class to `False`
-* set, through the attribute `content_type` of the class, the MIME
-  type generated by the view to `application/octet-stream` or any
-  relevant and more specialised mime type
-
-For views dedicated to binary content creation (like dynamically generated
-images), we have to set the attribute `binary` of the class to `True` (which
-implies that `templatable == False`, so that the attribute `w` of the view could be
-replaced by a binary flow instead of unicode).
--- a/doc/book/en/devweb/views/wdoc.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Online documentation system
-===========================
-
-.. automodule:: cubicweb.web.views.wdoc
-
-Help views
-----------
-.. autoclass:: cubicweb.web.views.wdoc.InlineHelpView
-
-Actions
--------
-.. autoclass:: cubicweb.web.views.wdoc.HelpAction
-.. autoclass:: cubicweb.web.views.wdoc.AboutAction
--- a/doc/book/en/devweb/views/xmlrss.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-.. _XmlAndRss:
-
-XML and RSS views
------------------
-
-(:mod:`cubicweb.web.views.xmlrss`)
-
-Overview
-+++++++++
-
-*rss*
-    Creates a RSS/XML view and call the view `rssitem` for each entity of
-    the result set.
-
-*rssitem*
-    Create a RSS/XML view for each entity based on the results of the dublin core
-    methods of the entity (`dc_*`)
-
-RSS Channel Example
-++++++++++++++++++++
-
-Assuming you have several blog entries, click on the title of the
-search box in the left column. A larger search box should appear. Enter:
-
-.. sourcecode:: sql
-
-   Any X ORDERBY D WHERE X is BlogEntry, X creation_date D
-
-and you get a list of blog entries.
-
-Click on your login at the top right corner. Chose "user preferences",
-then "boxes", then "possible views box" and check "visible = yes"
-before validating your changes.
-
-Enter the same query in the search box and you will see the same list,
-plus a box titled "possible views" in the left column. Click on
-"entityview", then "RSS".
-
-You just applied the "RSS" view to the RQL selection you requested.
-
-That's it, you have a RSS channel for your blog.
-
-Try again with:
-
-.. sourcecode:: sql
-
-    Any X ORDERBY D WHERE X is BlogEntry, X creation_date D,
-    X entry_of B, B title "MyLife"
-
-Another RSS channel, but a bit more focused.
-
-A last one for the road:
-
-.. sourcecode:: sql
-
-    Any C ORDERBY D WHERE C is Comment, C creation_date D LIMIT 15
-
-displayed with the RSS view, that's a channel for the last fifteen
-comments posted.
-
-[WRITE ME]
-
-* show that the RSS view can be used to display an ordered selection
-  of blog entries, thus providing a RSS channel
-
-* show that a different selection (by category) means a different channel
Binary file doc/book/en/images/03-transitions-view_en.png has changed
Binary file doc/book/en/images/archi_globale.png has changed
Binary file doc/book/en/images/archi_globale_en.png has changed
Binary file doc/book/en/images/breadcrumbs_header.png has changed
Binary file doc/book/en/images/facet_date_range.png has changed
Binary file doc/book/en/images/facet_has_image.png has changed
Binary file doc/book/en/images/facet_overview.png has changed
Binary file doc/book/en/images/facet_range.png has changed
Binary file doc/book/en/images/lax-book_00-login_en.png has changed
Binary file doc/book/en/images/lax-book_01-start_en.png has changed
Binary file doc/book/en/images/lax-book_02-cookie-values_en.png has changed
Binary file doc/book/en/images/lax-book_02-create-blog_en.png has changed
Binary file doc/book/en/images/lax-book_03-list-one-blog_en.png has changed
Binary file doc/book/en/images/lax-book_03-site-config-panel_en.png has changed
Binary file doc/book/en/images/lax-book_03-state-submitted_en.png has changed
Binary file doc/book/en/images/lax-book_03-transitions-view_en.png has changed
Binary file doc/book/en/images/lax-book_04-detail-one-blog_en.png has changed
Binary file doc/book/en/images/lax-book_05-list-two-blog_en.png has changed
Binary file doc/book/en/images/lax-book_06-add-relation-entryof_en.png has changed
Binary file doc/book/en/images/lax-book_06-main-template-logo_en.png has changed
Binary file doc/book/en/images/lax-book_07-detail-one-blogentry_en.png has changed
Binary file doc/book/en/images/lax-book_08-schema_en.png has changed
Binary file doc/book/en/images/lax-book_09-new-view-blogentry_en.png has changed
Binary file doc/book/en/images/lax-book_10-blog-with-two-entries_en.png has changed
Binary file doc/book/en/images/main_template.png has changed
--- a/doc/book/en/images/main_template.svg	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="1036.6421"
-   height="845.07812"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docname="main_template.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.0"
-   inkscape:export-filename="/home/auc/cw/doc/book/en/images/main_template.png"
-   inkscape:export-xdpi="60.659016"
-   inkscape:export-ydpi="60.659016">
-  <defs
-     id="defs4">
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 526.18109 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="744.09448 : 526.18109 : 1"
-       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
-       id="perspective10" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.80355603"
-     inkscape:cx="510.91495"
-     inkscape:cy="422.53906"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:window-width="925"
-     inkscape:window-height="1168"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:snap-bbox="true" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Calque 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(162.2968,90.697922)">
-    <rect
-       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect2439"
-       width="854.37006"
-       height="698.2019"
-       x="20.307629"
-       y="-20.575344" />
-    <rect
-       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3301"
-       width="816.3457"
-       height="508.15628"
-       x="31.751091"
-       y="96.33345" />
-    <g
-       id="g3220"
-       transform="matrix(1.0035394,0,0,1,0.5745006,0)">
-      <rect
-         y="-89.447922"
-         x="-161.0468"
-         height="55.714287"
-         width="1031.1713"
-         id="rect3240"
-         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.50000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <text
-         id="text3264"
-         y="-51.771908"
-         x="757.85767"
-         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           id="tspan3266"
-           y="-51.771908"
-           x="757.85767"
-           sodipodi:role="line">header</tspan></text>
-    </g>
-    <rect
-       style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3270"
-       width="167.87744"
-       height="707.71222"
-       x="-160.02441"
-       y="-24.671618" />
-    <g
-       id="g2434"
-       transform="matrix(0.975467,0,0,1,0.6942419,-3.6587365)">
-      <rect
-         y="35.365849"
-         x="29.548275"
-         height="55.714287"
-         width="842.59979"
-         id="rect3279"
-         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <text
-         id="text3281"
-         y="72.885193"
-         x="681.65283"
-         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           id="tspan3283"
-           y="72.885193"
-           x="681.65283"
-           sodipodi:role="line">contentheader</tspan></text>
-    </g>
-    <g
-       id="g3170"
-       transform="matrix(1.0023324,0,0,1,-2.0421673,-10.976211)">
-      <rect
-         y="698.6355"
-         x="-158.28485"
-         height="55.714287"
-         width="1032.5997"
-         id="rect3285"
-         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <text
-         id="text3287"
-         y="736.52045"
-         x="770.28204"
-         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           id="tspan3289"
-           y="736.52045"
-           x="770.28204"
-           sodipodi:role="line">footer</tspan></text>
-    </g>
-    <g
-       id="g3211" />
-    <g
-       id="g3215"
-       transform="matrix(0.9712065,0,0,1,0.7659296,-17.074106)">
-      <rect
-         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-         id="rect3291"
-         width="844.62012"
-         height="55.714287"
-         x="27.850754"
-         y="629.88562" />
-      <text
-         id="text3293"
-         y="666.60339"
-         x="692.85773"
-         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           id="tspan3295"
-           y="666.60339"
-           x="692.85773"
-           sodipodi:role="line">contentfooter</tspan></text>
-    </g>
-    <text
-       xml:space="preserve"
-       style="font-size:23.38711166px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="-143.67273"
-       y="20.58094"
-       id="text3297"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan2432"
-         x="-143.67273"
-         y="20.58094">left column</tspan></text>
-    <text
-       transform="scale(0.9876573,1.0124969)"
-       id="text3175"
-       y="12.071429"
-       x="721.0575"
-       style="font-size:23.09845161px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-       xml:space="preserve"><tspan
-         id="tspan3177"
-         y="12.071429"
-         x="721.0575"
-         sodipodi:role="line">contentcol</tspan></text>
-    <text
-       transform="scale(0.9876573,1.0124969)"
-       id="text3179"
-       y="126.27104"
-       x="701.45959"
-       style="font-size:23.09845161px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-       xml:space="preserve"><tspan
-         id="tspan3181"
-         y="126.27104"
-         x="701.45959"
-         sodipodi:role="line">contentmain</tspan></text>
-  </g>
-</svg>
Binary file doc/book/en/images/main_template_layout.png has changed
Binary file doc/book/en/images/primaryview_template.png has changed
--- a/doc/book/en/images/primaryview_template.svg	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="1036.6421"
-   height="845.07812"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docname="primaryview_template.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.0"
-   inkscape:export-filename="/home/steph/local/fcubicweb/cubicweb/doc/book/en/images/primaryview_template.png"
-   inkscape:export-xdpi="43.451603"
-   inkscape:export-ydpi="43.451603">
-  <defs
-     id="defs4">
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 526.18109 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="744.09448 : 526.18109 : 1"
-       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
-       id="perspective10" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.9357135"
-     inkscape:cx="518.32104"
-     inkscape:cy="337.0428"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     inkscape:window-width="1307"
-     inkscape:window-height="1168"
-     inkscape:window-x="0"
-     inkscape:window-y="0" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Calque 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(162.2968,90.697922)">
-    <g
-       id="g3869"
-       transform="matrix(1,0,0,1.0373644,0,-72.039777)"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449">
-      <rect
-         y="-15.840891"
-         x="-159.08963"
-         height="770.11017"
-         width="1033.0049"
-         id="rect3301"
-         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.90144825;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-      <text
-         id="text3865"
-         y="19.784882"
-         x="-150.07172"
-         style="font-size:28.67479324px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
-         xml:space="preserve"><tspan
-           id="tspan3867"
-           y="19.784882"
-           x="-150.07172"
-           sodipodi:role="line">contentmain</tspan></text>
-    </g>
-    <rect
-       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.45654476;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect2383"
-       width="772.32111"
-       height="43.888428"
-       x="-131.1837"
-       y="86.559296"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449" />
-    <text
-       xml:space="preserve"
-       style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
-       x="-122.69418"
-       y="115.50363"
-       id="text2385"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         x="-122.69418"
-         y="115.50363"
-         id="tspan3163">navcontenttop</tspan></text>
-    <rect
-       style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:3.06523442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3167"
-       width="770.26868"
-       height="203.16078"
-       x="-125.88269"
-       y="172.90417"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449" />
-    <text
-       xml:space="preserve"
-       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="348.26724"
-       y="205.34305"
-       id="text3169"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         x="348.26724"
-         y="205.34305"
-         id="tspan3171">render_entity_attributes()</tspan></text>
-    <rect
-       style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:3.06523442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3173"
-       width="769.93549"
-       height="237.84663"
-       x="-125.03326"
-       y="391.32156"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449" />
-    <text
-       xml:space="preserve"
-       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="360.99954"
-       y="428.38055"
-       id="text3175"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         x="360.99954"
-         y="428.38055"
-         id="tspan3177">render_entity_relations()</tspan></text>
-    <rect
-       style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:2.15903592;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3185"
-       width="178.93939"
-       height="612.36584"
-       x="667.10443"
-       y="84.64225"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449" />
-    <text
-       xml:space="preserve"
-       style="font-size:22px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
-       x="105.32364"
-       y="-810.65997"
-       id="text3187"
-       transform="matrix(0,1,-1,0,0,0)"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         id="tspan2408">render_side_boxes()</tspan></text>
-    <rect
-       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:3.0652349;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3191"
-       width="771.97766"
-       height="55.647793"
-       x="-127.80586"
-       y="642.0293"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449" />
-    <text
-       xml:space="preserve"
-       style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="-121.22153"
-       y="674.1748"
-       id="text3181"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         x="-121.22153"
-         y="674.1748"
-         id="tspan3183">navcontentbottom</tspan></text>
-    <rect
-       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.68198514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3881"
-       width="986.90503"
-       height="45.800392"
-       x="-128.34428"
-       y="-31.574066"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449" />
-    <text
-       xml:space="preserve"
-       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="355.60541"
-       y="-2.7424495"
-       id="text3883"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         x="355.60541"
-         y="-2.7424495"
-         id="tspan3885">render_entity_toolbox(), render_entity_title()</tspan></text>
-    <rect
-       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.68198514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect3890"
-       width="986.90503"
-       height="45.800392"
-       x="-128.87863"
-       y="19.723684"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449" />
-    <text
-       xml:space="preserve"
-       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="565.71027"
-       y="50.135612"
-       id="text3892"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         x="565.71027"
-         y="50.135612"
-         id="tspan3894">render_entity_summary()</tspan></text>
-    <text
-       xml:space="preserve"
-       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="87.154541"
-       y="114.2578"
-       id="text3899"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         id="tspan3903"
-         x="87.154541"
-         y="114.2578">content_navigation_components('navcontenttop')</tspan></text>
-    <text
-       xml:space="preserve"
-       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="88.46772"
-       y="675.71582"
-       id="text2410"
-       sodipodi:linespacing="125%"
-       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
-       inkscape:export-xdpi="60.912449"
-       inkscape:export-ydpi="60.912449"><tspan
-         sodipodi:role="line"
-         id="tspan2412"
-         x="88.46772"
-         y="675.71582">content_navigation_components('navcontenttop')</tspan></text>
-  </g>
-</svg>
Binary file doc/book/en/images/request_session.png has changed
--- a/doc/book/en/images/request_session.svg	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="85.960938"
-   height="12.382812"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.48.3.1 r9886"
-   sodipodi:docname="request_session.svg">
-  <defs
-     id="defs4">
-    <marker
-       inkscape:stockid="Arrow1Lend"
-       orient="auto"
-       refY="0.0"
-       refX="0.0"
-       id="Arrow1Lend"
-       style="overflow:visible;">
-      <path
-         id="path3822"
-         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
-         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
-         transform="scale(0.8) rotate(180) translate(12.5,0)" />
-    </marker>
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.98994949"
-     inkscape:cx="25.928992"
-     inkscape:cy="-185.87004"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="false"
-     fit-margin-top="0"
-     fit-margin-left="0"
-     fit-margin-right="0"
-     fit-margin-bottom="0"
-     inkscape:window-width="958"
-     inkscape:window-height="1160"
-     inkscape:window-x="0"
-     inkscape:window-y="38"
-     inkscape:window-maximized="0"
-     inkscape:snap-global="true" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(-263.52249,-495.73373)">
-    <rect
-       style="fill:#ffffff;stroke:#000000;stroke-width:0.92460138;stroke-opacity:1"
-       id="rect3773"
-       width="214.15233"
-       height="184.80336"
-       x="57.578697"
-       y="366.01306" />
-    <rect
-       id="rect2985"
-       width="216.86372"
-       height="183.54575"
-       x="348.50262"
-       y="367.78079"
-       style="fill:#ffffff;stroke:#000000;stroke-width:0.55298227;stroke-opacity:1" />
-    <text
-       xml:space="preserve"
-       style="font-size:32px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="376.7869"
-       y="399.80365"
-       id="text3755"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3757"
-         x="376.7869"
-         y="399.80365">Repository</tspan></text>
-    <rect
-       style="fill:#ffffff;stroke:#000000;stroke-opacity:1"
-       id="rect3759"
-       width="144.45181"
-       height="104.04572"
-       x="237.38585"
-       y="423.03714" />
-    <text
-       xml:space="preserve"
-       style="font-size:24px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="262.63968"
-       y="470.51431"
-       id="text3761"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3763"
-         x="262.63968"
-         y="470.51431">REPOAPI</tspan></text>
-    <text
-       xml:space="preserve"
-       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="262.63968"
-       y="507.88998"
-       id="text3765"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3767"
-         x="262.63968"
-         y="507.88998">connection</tspan></text>
-    <text
-       xml:space="preserve"
-       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="419.21332"
-       y="509.91025"
-       id="text3769"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3771"
-         x="419.21332"
-         y="509.91025">session</tspan></text>
-    <text
-       xml:space="preserve"
-       style="font-size:32px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="102.02541"
-       y="397.78333"
-       id="text3775"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3777"
-         x="102.02541"
-         y="397.78333">Client</tspan></text>
-    <text
-       xml:space="preserve"
-       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="116.16754"
-       y="507.88995"
-       id="text3779"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3781"
-         x="116.16754"
-         y="507.88995">request</tspan></text>
-    <text
-       xml:space="preserve"
-       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="361.50729"
-       y="585.89832"
-       id="text3802"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3804"
-         x="361.50729"
-         y="585.89832">database </tspan><tspan
-         sodipodi:role="line"
-         x="361.50729"
-         y="605.89832"
-         id="tspan3806">connection</tspan></text>
-    <rect
-       style="fill:#ffffff;stroke:#000000;stroke-width:1.48014534;stroke-opacity:1"
-       id="rect3808"
-       width="192.09367"
-       height="58.095726"
-       x="365.79443"
-       y="621.50018" />
-    <text
-       xml:space="preserve"
-       style="font-size:36px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
-       x="369.5885"
-       y="662.66992"
-       id="text3810"
-       sodipodi:linespacing="125%"><tspan
-         sodipodi:role="line"
-         id="tspan3812"
-         x="369.5885"
-         y="662.66992">Database</tspan></text>
-    <path
-       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
-       d="M 197.57252,125.76645 195.76971,55.592808"
-       id="path4260"
-       inkscape:connector-type="polyline"
-       inkscape:connector-curvature="3"
-       inkscape:connection-start="#rect3808"
-       inkscape:connection-start-point="d4"
-       inkscape:connection-end="#rect2985"
-       inkscape:connection-end-point="d4"
-       transform="translate(263.52249,495.73373)" />
-  </g>
-</svg>
Binary file doc/book/en/images/server-class-diagram.png has changed
Binary file doc/book/en/images/tutos-base_blog-form_en.png has changed
Binary file doc/book/en/images/tutos-base_blog-primary-after-post-creation_en.png has changed
Binary file doc/book/en/images/tutos-base_blog-primary_en.png has changed
Binary file doc/book/en/images/tutos-base_blogs-list_en.png has changed
Binary file doc/book/en/images/tutos-base_form-generic-relations_en.png has changed
Binary file doc/book/en/images/tutos-base_index_en.png has changed
Binary file doc/book/en/images/tutos-base_login-form_en.png has changed
Binary file doc/book/en/images/tutos-base_myblog-blogentry-taggable-commentable-primary_en.png has changed
Binary file doc/book/en/images/tutos-base_myblog-community-custom-primary_en.png has changed
Binary file doc/book/en/images/tutos-base_myblog-community-default-primary_en.png has changed
Binary file doc/book/en/images/tutos-base_myblog-community-taggable-primary_en.png has changed
Binary file doc/book/en/images/tutos-base_myblog-custom-footer_en.png has changed
Binary file doc/book/en/images/tutos-base_myblog-schema_en.png has changed
Binary file doc/book/en/images/tutos-base_myblog-siteinfo_en.png has changed
Binary file doc/book/en/images/tutos-base_schema_en.png has changed
Binary file doc/book/en/images/tutos-base_siteconfig_en.png has changed
Binary file doc/book/en/images/tutos-base_user-menu_en.png has changed
Binary file doc/book/en/images/tutos-photowebsite_background-image.png has changed
Binary file doc/book/en/images/tutos-photowebsite_boxes.png has changed
Binary file doc/book/en/images/tutos-photowebsite_breadcrumbs.png has changed
Binary file doc/book/en/images/tutos-photowebsite_facets.png has changed
Binary file doc/book/en/images/tutos-photowebsite_grey-box.png has changed
Binary file doc/book/en/images/tutos-photowebsite_index-after.png has changed
Binary file doc/book/en/images/tutos-photowebsite_index-before.png has changed
Binary file doc/book/en/images/tutos-photowebsite_login-box.png has changed
Binary file doc/book/en/images/tutos-photowebsite_prevnext.png has changed
Binary file doc/book/en/images/tutos-photowebsite_ui1.png has changed
Binary file doc/book/en/images/tutos-photowebsite_ui2.png has changed
Binary file doc/book/en/images/tutos-photowebsite_ui3.png has changed
Binary file doc/book/en/images/undo_history-view_w600.png has changed
Binary file doc/book/en/images/undo_mesage_w600.png has changed
Binary file doc/book/en/images/undo_startup-link_w600.png has changed
Binary file doc/book/en/images/views-table-filter-shadow.png has changed
Binary file doc/book/en/images/views-table-filter.png has changed
Binary file doc/book/en/images/views-table-shadow.png has changed
Binary file doc/book/en/images/views-table.png has changed
--- a/doc/book/en/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _contents:
-
-=====================================================
-|cubicweb| - The Semantic Web is a construction game!
-=====================================================
-
-|cubicweb| is a semantic web application framework, licensed under the LGPL,
-that empowers developers to efficiently build web applications by reusing
-components (called `cubes`) and following the well known object-oriented design
-principles.
-
-Its main features are:
-
-* an engine driven by the explicit :ref:`data model
-  <TutosBaseCustomizingTheApplicationDataModel>` of the application,
-
-* a query language named :ref:`RQL <RQL>` similar to W3C's SPARQL,
-
-* a :ref:`selection+view <TutosBaseCustomizingTheApplicationCustomViews>`
-  mechanism for semi-automatic XHTML/XML/JSON/text generation,
-
-* a library of reusable :ref:`components <Cube>` (data model and views) that
-  fulfill common needs,
-
-* the power and flexibility of the Python_ programming language,
-
-* the reliability of SQL databases, LDAP directories, Subversion and Mercurial
-  for storage backends.
-
-Built since 2000 from an R&D effort still continued, supporting 100,000s of
-daily visits at some production sites, |cubicweb| is a proven end to end solution
-for semantic web application development that promotes quality, reusability and
-efficiency.
-
-The unbeliever will read the :ref:`Tutorials`.
-
-The hacker will join development at the forge_.
-
-The impatient developer will move right away to :ref:`SetUpEnv` then to :ref:`ConfigEnv`.
-
-The chatter lover will join the `jabber forum`_, the `mailing-list`_ and the blog_.
-
-.. _Logilab: http://www.logilab.fr/
-.. _forge: http://www.cubicweb.org/project/
-.. _Python: http://www.python.org/
-.. _`jabber forum`: http://www.logilab.org/blogentry/6718
-.. _`mailing-list`: http://lists.cubicweb.org/mailman/listinfo/cubicweb
-.. _blog: http://www.cubicweb.org/blog/1238
-
-.. toctree::
-   :maxdepth: 2
-
-   intro/index
-   tutorials/index
-
-.. toctree::
-   :maxdepth: 3
-
-   devrepo/index
-   devweb/index
-
-.. toctree::
-   :maxdepth: 2
-
-   admin/index
-   additionnal_services/index
-   annexes/index
-
-See also:
-
-* the :ref:`genindex`,
-* the :ref:`modindex`,
--- a/doc/book/en/intro/concepts.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _Concepts:
-
-The Core Concepts of |cubicweb|
-===============================
-
-This section defines some terms and core concepts of the |cubicweb| framework. To
-avoid confusion while reading this book, take time to go through the following
-definitions and use this section as a reference during your reading.
-
-
-.. _Cube:
-
-Cubes
------
-
-A cube is a software component made of three parts: its data model
-(: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
-`cubicweb-comment`_ could be used to make a cube named *myblog* with commentable
-blog entries.
-
-The `CubicWeb.org Forge`_ offers a large number of cubes developed by the community
-and available under a free software license.
-
-.. note::
-
- The command :command:`cubicweb-ctl list` displays the list of available cubes.
-
-.. _`CubicWeb.org Forge`: http://www.cubicweb.org/project/
-.. _`cubicweb-blog`: http://www.cubicweb.org/project/cubicweb-blog
-.. _`cubicweb-comment`: http://www.cubicweb.org/project/cubicweb-comment
-
-
-.. _Instance:
-
-Instances
----------
-
-An instance is a runnable application installed on a computer and based on a
-cube.
-
-The instance directory contains the configuration files. Several instances can be
-created and based on the same cube. For exemple, several software forges can be
-set up on one computer system based on the `cubicweb-forge`_ cube.
-
-.. _`cubicweb-forge`: http://www.cubicweb.org/project/cubicweb-forge
-
-Instances can be of three different types: all-in-one, web engine or data
-repository. For applications that support high traffic, several web (front-end)
-and data (back-end) instances can be set-up to share the load.
-
-.. image:: ../images/archi_globale_en.png
-
-The command :command:`cubicweb-ctl list` also displays the list of instances
-installed on your system.
-
-.. 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,
-  depending on the context. This book will try to use *application*, *cube* and
-  *instance* as appropriate.
-
-
-.. _RepositoryIntro:
-
-Data Repository
----------------
-
-The data repository [1]_ encapsulates and groups an access to one or
-more data sources (including SQL databases, LDAP repositories, other
-|cubicweb| instance repositories, filesystems, Google AppEngine's
-DataStore, etc).
-
-All interactions with the repository are done using the `Relation Query Language`
-(:ref:`RQL`). The repository federates the data sources and hides them from the
-querier, which does not realize when a query spans several data sources
-and requires running sub-queries and merges to complete.
-
-Application logic can be mapped to data events happenning within 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://pythonhosted.org/Pyro4/
-
-.. _WebEngineIntro:
-
-Web Engine
-----------
-
-The web engine replies to http requests and runs the user interface.
-
-By default the web engine provides a `CRUD`_ user interface based on
-the data model of the instance. Entities can be created, displayed,
-updated and deleted. As the default user interface is not very fancy,
-it is usually necessary to develop your own.
-
-It is common to run the web engine and the repository in the same
-process (see instances of type all-in-one above), but this is not a
-requirement. A repository can be set up to be accessed remotely using
-Pyro (`Python Remote Objects`_) and act as a standalone server, which
-can be directly accessed or also through a standalone web engine.
-
-.. _`CRUD`: http://en.wikipedia.org/wiki/Create,_read,_update_and_delete
-
-.. _SchemaIntro:
-
-Schema (Data Model)
--------------------
-
-The data model of a cube is described as an entity-relationship schema using a
-comprehensive language made of Python classes imported from the yams_ library.
-
-.. _yams: http://www.logilab.org/project/yams/
-
-An `entity type` defines a sequence of attributes. Attributes may be
-of the following types: `String`, `Int`, `Float`, `Boolean`, `Date`,
-`Time`, `Datetime`, `Interval`, `Password`, `Bytes`, `RichString`.
-
-A `relation type` is used to define an oriented binary relation
-between entity types.  The left-hand part of a relation is named the
-`subject` and the right-hand part is named the `object`.
-
-A `relation definition` is a triple (*subject entity type*, *relation type*, *object
-entity type*) associated with a set of properties such as cardinality,
-constraints, etc.
-
-Permissions can be set on entity types or relation definition to control who
-will be able to create, read, update or delete entities and relations. Permissions
-are granted to groups (to which users may belong) or using rql expressions (if the
-rql expression returns some results, the permission is granted).
-
-Some meta-data necessary to the system are added to the data model. That includes
-entities like users and groups, the entities used to store the data model
-itself and attributes like unique identifier, creation date, creator, etc.
-
-When you create a new |cubicweb| instance, the schema is stored in the database.
-When the cubes the instance is based on evolve, they may change their data model
-and provide migration scripts that will be executed when the administrator will
-run the upgrade process for the instance.
-
-
-.. _VRegistryIntro:
-
-Registries and application objects
-----------------------------------
-
-Application objects
-~~~~~~~~~~~~~~~~~~~
-
-Besides a few core functionalities, almost every feature of the framework is
-achieved by dynamic objects (`application objects` or `appobjects`) stored in a
-two-levels registry. Each object is affected to a registry with
-an identifier in this registry. You may have more than one object sharing an
-identifier in the same registry:
-
-  object's `__registry__` : object's `__regid__` : [list of app objects]
-
-In other words, the `registry` contains several (sub-)registries which hold a
-list of appobjects associated to an identifier.
-
-The base class of appobjects is :class:`cubicweb.appobject.AppObject`.
-
-Selectors
-~~~~~~~~~
-
-At runtime, appobjects can be selected in a registry according to some
-contextual information. Selection is done by comparing the *score*
-returned by each appobject's *selector*.
-
-The better the object fits the context, the higher the score. Scores
-are the glue that ties appobjects to the data model. Using them
-appropriately is an essential part of the construction of well behaved
-cubes.
-
-|cubicweb| provides a set of basic selectors that may be parametrized.  Also,
-selectors can be combined with the `~` unary operator (negation) and the binary
-operators `&` and `|` (respectivly 'and' and 'or') to build more complex
-selectors. Of course complex selectors may be combined too. Last but not least, you
-can write your own selectors.
-
-The `registry`
-~~~~~~~~~~~~~~~
-
-At startup, the `registry` inspects a number of directories looking
-for compatible class definitions. After a recording process, the
-objects are assigned to registries and become available through the
-selection process.
-
-In a cube, application object classes are looked in the following modules or
-packages:
-
-- `entities`
-- `views`
-- `hooks`
-- `sobjects`
-
-There are three common ways to look up some application object from a
-registry:
-
-* get the most appropriate object by specifying an identifier and
-  context objects. The object with the greatest score is
-  selected. There should always be a single appobject with a greater
-  score than others for a particular context.
-
-* get all objects applying to a context by specifying a registry. A
-  list of objects will be returned containing the object with the
-  highest score (> 0) for each identifier in that registry.
-
-* get the object within a particular registry/identifier. No selection
-  process is involved: the registry will expect to find a single
-  object in that cell.
-
-
-.. _RQLIntro:
-
-The RQL query 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 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.
-
-
-Result set
-~~~~~~~~~~
-
-Every request made (using RQL) to the data repository returns an object we call a
-Result Set. It enables easy use of the retrieved data, providing a translation
-layer between the backend's native datatypes and |cubicweb| schema's EntityTypes.
-
-Result sets provide access to the raw data, yielding either basic Python data
-types, or schema-defined high-level entities, in a straightforward way.
-
-
-.. _ViewIntro:
-
-Views
------
-
-**CubicWeb is data driven**
-
-The view system is loosely coupled to data through the selection system explained
-above. Views are application objects with a dedicated interface to 'render'
-something, eg producing some html, text, xml, pdf, or whatsover that can be
-displayed to a user.
-
-Views actually are partitioned into different kind of objects such as
-`templates`, `boxes`, `components` and proper `views`, which are more
-high-level abstraction useful to build the user interface in an object
-oriented way.
-
-
-.. _HookIntro:
-
-Hooks and operations
---------------------
-
-**CubicWeb provides an extensible data repository**
-
-The data model defined using Yams types allows to express the data
-model in a comfortable way. However several aspects of the data model
-can not be expressed there. For instance:
-
-* managing computed attributes
-
-* enforcing complicated business rules
-
-* real-world side-effects linked to data events (email notification
-  being a prime example)
-
-The hook system is much like the triggers of an SQL database engine,
-except that:
-
-* it is not limited to one specific SQL backend (every one of them
-  having an idiomatic way to encode triggers), nor to SQL backends at
-  all (think about LDAP or a Subversion repository)
-
-* it is well-coupled to the rest of the framework
-
-Hooks are also application objects (in the `hooks` registry) and
-selected on events such as after/before add/update/delete on
-entities/relations, server startup or shutdown, etc.
-
-`Operations` may be instantiated by hooks to do further processing at different
-steps of the transaction's commit / rollback, which usually can not be done
-safely at the hook execution time.
-
-Hooks and operation are an essential building block of any moderately complicated
-cubicweb application.
-
-.. note::
-   RQL queries executed in hooks and operations are *unsafe* by default, i.e. the
-   read and write security is deactivated unless explicitly asked.
--- a/doc/book/en/intro/history.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-A little history...
-===================
-
-*CubicWeb* is a semantic web application framework that Logilab_ started
-developing in 2001 as an offspring of its Narval_ research project. *CubicWeb*
-is written in Python and includes a data server and a web engine.
-
-Its data server publishes data federated from different sources like
-SQL databases, LDAP directories, `VCS`_ repositories or even from other
-CubicWeb data servers.
-
-.. _`VCS`: http://en.wikipedia.org/wiki/Revision_control
-
-Its web engine was designed to let the final user control what content to select
-and how to display it. It allows one to browse the federated data sources and
-display the results with the rendering that best fits the context. This
-flexibility of the user interface gives back to the user some capabilities
-usually only accessible to application developers.
-
-*CubicWeb* has been developed by Logilab_ and used in-house for many years
-before it was first installed for its clients in 2006 as version 2.
-
-In 2008, *CubicWeb* version 3 became downloadable for free under the
-terms of the LGPL license. Its community is now steadily growing
-without hampering the fast-paced stream of changes thanks to the time
-and energy originally put in the design of the framework.
-
-
-.. _Narval: http://www.logilab.org/project/narval-moved
-.. _Logilab: http://www.logilab.fr/
--- a/doc/book/en/intro/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _Part1:
-
---------------------------
-Introduction to *CubicWeb*
---------------------------
-
-This first part of the book offers different reading path to
-discover the *CubicWeb* framework, provides a tutorial to get a quick
-overview of its features and lists its key concepts.
-
-
-.. toctree::
-   :maxdepth: 2
-   :numbered:
-
-   history
-   concepts.rst
--- a/doc/book/en/makefile	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-SRC=.
-
-# You can set these sphinx variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-PAPER         =
-#BUILDDIR      = build
-BUILDDIR      = ../..
-CWDIR         = ../../..
-JSDIR         = ${CWDIR}/web/data
-JSTORST       = ${CWDIR}/doc/tools/pyjsrest.py
-BUILDJS       = devweb/js_api
-
-# Internal variables for sphinx
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d ${BUILDDIR}/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-
-
-.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
-
-help:
-	@echo "Please use \`make <target>' where <target> is one of"
-	@echo "  all       to make standalone HTML files, developer manual and API doc"
-	@echo "  html      to make standalone HTML files"
-	@echo "---  "
-	@echo "  pickle    to make pickle files (usable by e.g. sphinx-web)"
-	@echo "  htmlhelp  to make HTML files and a HTML help project"
-	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  changes   to make an overview over all changed/added/deprecated items"
-	@echo "  linkcheck to check all external links for integrity"
-
-clean:
-	rm -f *.html
-	-rm -rf ${BUILDDIR}/html ${BUILDDIR}/doctrees
-	-rm -rf ${BUILDJS}
-
-all: html
-
-# run sphinx ###
-html: js
-	mkdir -p ${BUILDDIR}/html ${BUILDDIR}/doctrees
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) ${BUILDDIR}/html
-	@echo
-	@echo "Build finished. The HTML pages are in ${BUILDDIR}/html."
-
-js:
-	mkdir -p ${BUILDJS}
-	$(JSTORST) -p ${JSDIR} -o ${BUILDJS}
-
-pickle:
-	mkdir -p ${BUILDDIR}/pickle ${BUILDDIR}/doctrees
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) ${BUILDDIR}/pickle
-	@echo
-	@echo "Build finished; now you can process the pickle files or run"
-	@echo "  sphinx-web ${BUILDDIR}/pickle"
-	@echo "to start the sphinx-web server."
-
-web: pickle
-
-htmlhelp:
-	mkdir -p ${BUILDDIR}/htmlhelp ${BUILDDIR}/doctrees
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) ${BUILDDIR}/htmlhelp
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in ${BUILDDIR}/htmlhelp."
-
-latex:
-	mkdir -p ${BUILDDIR}/latex ${BUILDDIR}/doctrees
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) ${BUILDDIR}/latex
-	@echo
-	@echo "Build finished; the LaTeX files are in ${BUILDDIR}/latex."
-	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
-	      "run these through (pdf)latex."
-
-changes:
-	mkdir -p ${BUILDDIR}/changes ${BUILDDIR}/doctrees
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) ${BUILDDIR}/changes
-	@echo
-	@echo "The overview file is in ${BUILDDIR}/changes."
-
-linkcheck:
-	mkdir -p ${BUILDDIR}/linkcheck ${BUILDDIR}/doctrees
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) ${BUILDDIR}/linkcheck
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in ${BUILDDIR}/linkcheck/output.txt."
--- a/doc/book/en/tutorials/advanced/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-
-.. _TutosPhotoWebSite:
-
-Building a photo gallery with |cubicweb|
-========================================
-
-Desired features
-----------------
-
-* basically a photo gallery
-
-* photo stored on the file system and displayed dynamically through a web interface
-
-* navigation through folder (album), tags, geographical zone, people on the
-  picture... using facets
-
-* advanced security (not everyone can see everything). More on this later.
-
-
-.. toctree::
-   :maxdepth: 2
-
-   part01_create-cube
-   part02_security
-   part03_bfss
-   part04_ui-base
-   part05_ui-advanced
-
-
--- a/doc/book/en/tutorials/advanced/part01_create-cube.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-.. _TutosPhotoWebSiteCubeCreation:
-
-Cube creation and schema definition
------------------------------------
-
-.. _adv_tuto_create_new_cube:
-
-Step 1: creating a new cube for my web site
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-One note about my development environment: I wanted to use the packaged
-version of CubicWeb and cubes while keeping my cube in my user
-directory, let's say `~src/cubes`.  I achieve this by setting the
-following environment variables::
-
-  CW_CUBES_PATH=~/src/cubes
-  CW_MODE=user
-
-I can now create the cube which will hold custom code for this web
-site using::
-
-  cubicweb-ctl newcube --directory=~/src/cubes sytweb
-
-
-.. _adv_tuto_assemble_cubes:
-
-Step 2: pick building blocks into existing cubes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Almost everything I want to handle in my web-site is somehow already modelized in
-existing cubes that I'll extend for my need. So I'll pick the following cubes:
-
-* `folder`, containing the `Folder` entity type, which will be used as
-  both 'album' and a way to map file system folders. Entities are
-  added to a given folder using the `filed_under` relation.
-
-* `file`, containing `File` entity type, gallery view, and a file system import
-  utility.
-
-* `zone`, containing the `Zone` entity type for hierarchical geographical
-  zones. Entities (including sub-zones) are added to a given zone using the
-  `situated_in` relation.
-
-* `person`, containing the `Person` entity type plus some basic views.
-
-* `comment`, providing a full commenting system allowing one to comment entity types
-  supporting the `comments` relation by adding a `Comment` entity.
-
-* `tag`, providing a full tagging system as an easy and powerful way to classify
-  entities supporting the `tags` relation by linking the to `Tag` entities. This
-  will allows navigation into a large number of picture.
-
-Ok, now I'll tell my cube requires all this by editing :file:`cubes/sytweb/__pkginfo__.py`:
-
-  .. sourcecode:: python
-
-    __depends__ = {'cubicweb': '>= 3.10.0',
-                   'cubicweb-file': '>= 1.9.0',
-		   'cubicweb-folder': '>= 1.1.0',
-		   'cubicweb-person': '>= 1.2.0',
-		   'cubicweb-comment': '>= 1.2.0',
-		   'cubicweb-tag': '>= 1.2.0',
-		   'cubicweb-zone': None}
-
-Notice that you can express minimal version of the cube that should be used,
-`None` meaning whatever version available. All packages starting with 'cubicweb-'
-will be recognized as being cube, not bare python packages. You can still specify
-this explicitly using instead the `__depends_cubes__` dictionary which should
-contains cube's name without the prefix. So the example below would be written
-as:
-
-  .. sourcecode:: python
-
-    __depends__ = {'cubicweb': '>= 3.10.0'}
-    __depends_cubes__ = {'file': '>= 1.9.0',
-		         'folder': '>= 1.1.0',
-		   	 'person': '>= 1.2.0',
-		   	 'comment': '>= 1.2.0',
-		   	 'tag': '>= 1.2.0',
-		   	 'zone': None}
-
-If your cube is packaged for debian, it's a good idea to update the
-`debian/control` file at the same time, so you won't forget it.
-
-
-Step 3: glue everything together in my cube's schema
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. sourcecode:: python
-
-    from yams.buildobjs import RelationDefinition
-
-    class comments(RelationDefinition):
-	subject = 'Comment'
-	object = 'File'
-	cardinality = '1*'
-	composite = 'object'
-
-    class tags(RelationDefinition):
-	subject = 'Tag'
-	object = 'File'
-
-    class filed_under(RelationDefinition):
-	subject = 'File'
-	object = 'Folder'
-
-    class situated_in(RelationDefinition):
-	subject = 'File'
-	object = 'Zone'
-
-    class displayed_on(RelationDefinition):
-	subject = 'Person'
-	object = 'File'
-
-
-This schema:
-
-* allows to comment and tag on `File` entity type by adding the `comments` and
-  `tags` relations. This should be all we've to do for this feature since the
-  related cubes provide 'pluggable section' which are automatically displayed on
-  the primary view of entity types supporting the relation.
-
-* adds a `situated_in` relation definition so that image entities can be
-  geolocalized.
-
-* add a new relation `displayed_on` relation telling who can be seen on a
-  picture.
-
-This schema will probably have to evolve as time goes (for security handling at
-least), but since the possibility to let a schema evolve is one of CubicWeb's
-features (and goals), we won't worry about it for now and see that later when needed.
-
-
-Step 4: creating the instance
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Now that I have a schema, I want to create an instance. To
-do so using this new 'sytweb' cube, I run::
-
-  cubicweb-ctl create sytweb sytweb_instance
-
-Hint: if you get an error while the database is initialized, you can
-avoid having to answer the questions again by running::
-
-   cubicweb-ctl db-create sytweb_instance
-
-This will use your already configured instance and start directly from the create
-database step, thus skipping questions asked by the 'create' command.
-
-Once the instance and database are fully initialized, run ::
-
-  cubicweb-ctl start sytweb_instance
-
-to start the instance, check you can connect on it, etc...
-
--- a/doc/book/en/tutorials/advanced/part02_security.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,440 +0,0 @@
-.. _TutosPhotoWebSiteSecurity:
-
-Security, testing and migration
--------------------------------
-
-This part will cover various topics:
-
-* configuring security
-* migrating existing instance
-* writing some unit tests
-
-Here is the ``read`` security model I want:
-
-* folders, files, images and comments should have one of the following visibility:
-
-  - ``public``, everyone can see it
-  - ``authenticated``, only authenticated users can see it
-  - ``restricted``, only a subset of authenticated users can see it
-
-* managers (e.g. me) can see everything
-* only authenticated users can see people
-* everyone can see classifier entities, such as tag and zone
-
-Also, unless explicitly specified, the visibility of an image should be the same as
-its parent folder, as well as visibility of a comment should be the same as the
-commented entity. If there is no parent entity, the default visibility is
-``authenticated``.
-
-Regarding write security, that's much easier:
-* anonymous can't write anything
-* authenticated users can only add comment
-* managers will add the remaining stuff
-
-Now, let's implement that!
-
-Proper security in CubicWeb is done at the schema level, so you don't have to
-bother with it in views: users will only see what they can see automatically.
-
-.. _adv_tuto_security:
-
-Step 1: configuring security into the schema
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In schema, you can grant access according to groups, or to some RQL expressions:
-users get access if the expression returns some results. To implement the read
-security defined earlier, groups are not enough, we'll need some RQL expression. Here
-is the idea:
-
-* add a `visibility` attribute on Folder, File and Comment, which may be one of
-  the value explained above
-
-* add a `may_be_read_by` relation from Folder, File and Comment to users,
-  which will define who can see the entity
-
-* security propagation will be done in hook.
-
-So the first thing to do is to modify my cube's schema.py to define those
-relations:
-
-.. sourcecode:: python
-
-    from yams.constraints import StaticVocabularyConstraint
-
-    class visibility(RelationDefinition):
-	subject = ('Folder', 'File', 'Comment')
-	object = 'String'
-	constraints = [StaticVocabularyConstraint(('public', 'authenticated',
-						   'restricted', 'parent'))]
-	default = 'parent'
-	cardinality = '11' # required
-
-    class may_be_read_by(RelationDefinition):
-        __permissions__ = {
-	    'read':   ('managers', 'users'),
-	    'add':    ('managers',),
-	    'delete': ('managers',),
-	    }
-
-	subject = ('Folder', 'File', 'Comment',)
-	object = 'CWUser'
-
-We can note the following points:
-
-* we've added a new `visibility` attribute to folder, file, image and comment
-  using a `RelationDefinition`
-
-* `cardinality = '11'` means this attribute is required. This is usually hidden
-  under the `required` argument given to the `String` constructor, but we can
-  rely on this here (same thing for StaticVocabularyConstraint, which is usually
-  hidden by the `vocabulary` argument)
-
-* the `parent` possible value will be used for visibility propagation
-
-* think to secure the `may_be_read_by` permissions, else any user can add/delete it
-  by default, which somewhat breaks our security model...
-
-Now, we should be able to define security rules in the schema, based on these new
-attribute and relation. Here is the code to add to *schema.py*:
-
-.. sourcecode:: python
-
-    from cubicweb.schema import ERQLExpression
-
-    VISIBILITY_PERMISSIONS = {
-	'read':   ('managers',
-		   ERQLExpression('X visibility "public"'),
-		   ERQLExpression('X may_be_read_by U')),
-	'add':    ('managers',),
-	'update': ('managers', 'owners',),
-	'delete': ('managers', 'owners'),
-	}
-    AUTH_ONLY_PERMISSIONS = {
-	    'read':   ('managers', 'users'),
-	    'add':    ('managers',),
-	    'update': ('managers', 'owners',),
-	    'delete': ('managers', 'owners'),
-	    }
-    CLASSIFIERS_PERMISSIONS = {
-	    'read':   ('managers', 'users', 'guests'),
-	    'add':    ('managers',),
-	    'update': ('managers', 'owners',),
-	    'delete': ('managers', 'owners'),
-	    }
-
-    from cubes.folder.schema import Folder
-    from cubes.file.schema import File
-    from cubes.comment.schema import Comment
-    from cubes.person.schema import Person
-    from cubes.zone.schema import Zone
-    from cubes.tag.schema import Tag
-
-    Folder.__permissions__ = VISIBILITY_PERMISSIONS
-    File.__permissions__ = VISIBILITY_PERMISSIONS
-    Comment.__permissions__ = VISIBILITY_PERMISSIONS.copy()
-    Comment.__permissions__['add'] = ('managers', 'users',)
-    Person.__permissions__ = AUTH_ONLY_PERMISSIONS
-    Zone.__permissions__ = CLASSIFIERS_PERMISSIONS
-    Tag.__permissions__ = CLASSIFIERS_PERMISSIONS
-
-What's important in there:
-
-* `VISIBILITY_PERMISSIONS` provides read access to managers group, if
-  `visibility` attribute's value is 'public', or if user (designed by the 'U'
-  variable in the expression) is linked to the entity (the 'X' variable) through
-  the `may_be_read_by` permission
-
-* we modify permissions of the entity types we use by importing them and
-  modifying their `__permissions__` attribute
-
-* notice the `.copy()`: we only want to modify 'add' permission for `Comment`,
-  not for all entity types using `VISIBILITY_PERMISSIONS`!
-
-* the remaining part of the security model is done using regular groups:
-
-  - `users` is the group to which all authenticated users will belong
-  - `guests` is the group of anonymous users
-
-
-.. _adv_tuto_security_propagation:
-
-Step 2: security propagation in hooks
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To fullfill the requirements, we have to implement::
-
-  Also, unless explicity specified, visibility of an image should be the same as
-  its parent folder, as well as visibility of a comment should be the same as the
-  commented entity.
-
-This kind of `active` rule will be done using CubicWeb's hook
-system. Hooks are triggered on database events such as addition of a new
-entity or relation.
-
-The tricky part of the requirement is in *unless explicitly specified*, notably
-because when the entity is added, we don't know yet its 'parent'
-entity (e.g. Folder of an File, File commented by a Comment). To handle such things,
-CubicWeb provides `Operation`, which allow to schedule things to do at commit time.
-
-In our case we will:
-
-* on entity creation, schedule an operation that will set default visibility
-
-* when a "parent" relation is added, propagate parent's visibility unless the
-  child already has a visibility set
-
-Here is the code in cube's *hooks.py*:
-
-.. sourcecode:: python
-
-    from cubicweb.predicates import is_instance
-    from cubicweb.server import hook
-
-    class SetVisibilityOp(hook.DataOperationMixIn, hook.Operation):
-
-	def precommit_event(self):
-	    for eid in self.get_data():
-		entity = self.session.entity_from_eid(eid)
-		if entity.visibility == 'parent':
-		    entity.cw_set(visibility=u'authenticated')
-
-    class SetVisibilityHook(hook.Hook):
-	__regid__ = 'sytweb.setvisibility'
-	__select__ = hook.Hook.__select__ & is_instance('Folder', 'File', 'Comment')
-	events = ('after_add_entity',)
-
-	def __call__(self):
-	    SetVisibilityOp.get_instance(self._cw).add_data(self.entity.eid)
-
-    class SetParentVisibilityHook(hook.Hook):
-	__regid__ = 'sytweb.setparentvisibility'
-	__select__ = hook.Hook.__select__ & hook.match_rtype('filed_under', 'comments')
-	events = ('after_add_relation',)
-
-	def __call__(self):
-	    parent = self._cw.entity_from_eid(self.eidto)
-	    child = self._cw.entity_from_eid(self.eidfrom)
-	    if child.visibility == 'parent':
-		child.cw_set(visibility=parent.visibility)
-
-Notice:
-
-* hooks are application objects, hence have selectors that should match entity or
-  relation types to which the hook applies. To match a relation type, we use the
-  hook specific `match_rtype` selector.
-
-* usage of `DataOperationMixIn`: instead of adding an operation for each added entity,
-  DataOperationMixIn allows to create a single one and to store entity's eids to be
-  processed in the transaction data. This is a good pratice to avoid heavy
-  operations manipulation cost when creating a lot of entities in the same
-  transaction.
-
-* the `precommit_event` method of the operation will be called at transaction's
-  commit time.
-
-* in a hook, `self._cw` is the repository session, not a web request as usually
-  in views
-
-* according to hook's event, you have access to different attributes on the hook
-  instance. Here:
-
-  - `self.entity` is the newly added entity on 'after_add_entity' events
-
-  - `self.eidfrom` / `self.eidto` are the eid of the subject / object entity on
-    'after_add_relation' events (you may also get the relation type using
-    `self.rtype`)
-
-The `parent` visibility value is used to tell "propagate using parent security"
-because we want that attribute to be required, so we can't use None value else
-we'll get an error before we get any chance to propagate...
-
-Now, we also want to propagate the `may_be_read_by` relation. Fortunately,
-CubicWeb provides some base hook classes for such things, so we only have to add
-the following code to *hooks.py*:
-
-.. sourcecode:: python
-
-    # relations where the "parent" entity is the subject
-    S_RELS = set()
-    # relations where the "parent" entity is the object
-    O_RELS = set(('filed_under', 'comments',))
-
-    class AddEntitySecurityPropagationHook(hook.PropagateRelationHook):
-	"""propagate permissions when new entity are added"""
-	__regid__ = 'sytweb.addentity_security_propagation'
-	__select__ = (hook.PropagateRelationHook.__select__
-		      & hook.match_rtype_sets(S_RELS, O_RELS))
-	main_rtype = 'may_be_read_by'
-	subject_relations = S_RELS
-	object_relations = O_RELS
-
-    class AddPermissionSecurityPropagationHook(hook.PropagateRelationAddHook):
-	"""propagate permissions when new entity are added"""
-	__regid__ = 'sytweb.addperm_security_propagation'
-	__select__ = (hook.PropagateRelationAddHook.__select__
-		      & hook.match_rtype('may_be_read_by',))
-	subject_relations = S_RELS
-	object_relations = O_RELS
-
-    class DelPermissionSecurityPropagationHook(hook.PropagateRelationDelHook):
-	__regid__ = 'sytweb.delperm_security_propagation'
-	__select__ = (hook.PropagateRelationDelHook.__select__
-		      & hook.match_rtype('may_be_read_by',))
-	subject_relations = S_RELS
-	object_relations = O_RELS
-
-* the `AddEntitySecurityPropagationHook` will propagate the relation
-  when `filed_under` or `comments` relations are added
-
-  - the `S_RELS` and `O_RELS` set as well as the `match_rtype_sets` selector are
-    used here so that if my cube is used by another one, it'll be able to
-    configure security propagation by simply adding relation to one of the two
-    sets.
-
-* the two others will propagate permissions changes on parent entities to
-  children entities
-
-
-.. _adv_tuto_tesing_security:
-
-Step 3: testing our security
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Security is tricky. Writing some tests for it is a very good idea. You should
-even write them first, as Test Driven Development recommends!
-
-Here is a small test case that will check the basis of our security
-model, in *test/unittest_sytweb.py*:
-
-.. sourcecode:: python
-
-    from cubicweb.devtools.testlib import CubicWebTC
-    from cubicweb import Binary
-
-    class SecurityTC(CubicWebTC):
-
-        def test_visibility_propagation(self):
-            with self.admin_access.repo_cnx() as cnx:
-                # create a user for later security checks
-                toto = self.create_user(cnx, 'toto')
-                cnx.commit()
-                # init some data using the default manager connection
-                folder = cnx.create_entity('Folder',
-                                           name=u'restricted',
-                                           visibility=u'restricted')
-                photo1 = cnx.create_entity('File',
-                                           data_name=u'photo1.jpg',
-                                           data=Binary('xxx'),
-                                           filed_under=folder)
-                cnx.commit()
-                # visibility propagation
-                self.assertEquals(photo1.visibility, 'restricted')
-                # unless explicitly specified
-                photo2 = cnx.create_entity('File',
-                                           data_name=u'photo2.jpg',
-                                           data=Binary('xxx'),
-                                           visibility=u'public',
-                                           filed_under=folder)
-                cnx.commit()
-                self.assertEquals(photo2.visibility, 'public')
-            with self.new_access('toto').repo_cnx() as cnx:
-                # test security
-                self.assertEqual(1, len(cnx.execute('File X'))) # only the public one
-                self.assertEqual(0, len(cnx.execute('Folder X'))) # restricted...
-            with self.admin_access.repo_cnx() as cnx:
-                # may_be_read_by propagation
-                folder = cnx.entity_from_eid(folder.eid)
-                folder.cw_set(may_be_read_by=toto)
-                cnx.commit()
-            with self.new_access('toto').repo_cnx() as cnx:
-                photo1 = cnx.entity_from_eid(photo1.eid)
-                self.failUnless(photo1.may_be_read_by)
-                # test security with permissions
-                self.assertEquals(2, len(cnx.execute('File X'))) # now toto has access to photo2
-                self.assertEquals(1, len(cnx.execute('Folder X'))) # and to restricted folder
-
-    if __name__ == '__main__':
-        from logilab.common.testlib import unittest_main
-        unittest_main()
-
-It's not complete, but shows most things you'll want to do in tests: adding some
-content, creating users and connecting as them in the test, etc...
-
-To run it type:
-
-.. sourcecode:: bash
-
-    $ pytest unittest_sytweb.py
-    ========================  unittest_sytweb.py  ========================
-    -> creating tables [....................]
-    -> inserting default user and default groups.
-    -> storing the schema in the database [....................]
-    -> database for instance data initialized.
-    .
-    ----------------------------------------------------------------------
-    Ran 1 test in 22.547s
-
-    OK
-
-
-The first execution is taking time, since it creates a sqlite database for the
-test instance. The second one will be much quicker:
-
-.. sourcecode:: bash
-
-    $ pytest unittest_sytweb.py
-    ========================  unittest_sytweb.py  ========================
-    .
-    ----------------------------------------------------------------------
-    Ran 1 test in 2.662s
-
-    OK
-
-If you do some changes in your schema, you'll have to force regeneration of that
-database. You do that by removing the tmpdb files before running the test: ::
-
-    $ rm data/database/tmpdb*
-
-
-.. Note::
-  pytest is a very convenient utility used to control test execution. It is available from the `logilab-common`_ package.
-
-.. _`logilab-common`: http://www.logilab.org/project/logilab-common
-
-.. _adv_tuto_migration_script:
-
-Step 4: writing the migration script and migrating the instance
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Prior to those changes, I created an instance, fed it with some data, so I
-don't want to create a new one, but to migrate the existing one. Let's see how to
-do that.
-
-Migration commands should be put in the cube's *migration* directory, in a
-file named file:`<X.Y.Z>_Any.py` ('Any' being there mostly for historical reasons).
-
-Here I'll create a *migration/0.2.0_Any.py* file containing the following
-instructions:
-
-.. sourcecode:: python
-
-  add_relation_type('may_be_read_by')
-  add_relation_type('visibility')
-  sync_schema_props_perms()
-
-Then I update the version number in the cube's *__pkginfo__.py* to 0.2.0. And
-that's it! Those instructions will:
-
-* update the instance's schema by adding our two new relations and update the
-  underlying database tables accordingly (the first two instructions)
-
-* update schema's permissions definition (the last instruction)
-
-
-To migrate my instance I simply type::
-
-   cubicweb-ctl upgrade sytweb_instance
-
-You'll then be asked some questions to do the migration step by step. You should say
-YES when it asks if a backup of your database should be done, so you can get back
-to initial state if anything goes wrong...
--- a/doc/book/en/tutorials/advanced/part03_bfss.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-Storing images on the file-system
----------------------------------
-
-Step 1: configuring the BytesFileSystem storage
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To avoid cluttering my database, and to ease file manipulation, I don't want them
-to be stored in the database. I want to be able create File entities for some
-files on the server file system, where those file will be accessed to get
-entities data. To do so I've to set a custom :class:`BytesFileSystemStorage`
-storage for the File 'data' attribute, which hold the actual file's content.
-
-Since the function to register a custom storage needs to have a repository
-instance as first argument, we've to call it in a server startup hook. So I added
-in `cubes/sytweb/hooks.py` :
-
-.. sourcecode:: python
-
-    from os import makedirs
-    from os.path import join, exists
-
-    from cubicweb.server import hook
-    from cubicweb.server.sources import storages
-
-    class ServerStartupHook(hook.Hook):
-        __regid__ = 'sytweb.serverstartup'
-        events = ('server_startup', 'server_maintenance')
-
-        def __call__(self):
-            bfssdir = join(self.repo.config.appdatahome, 'bfss')
-            if not exists(bfssdir):
-                makedirs(bfssdir)
-                print 'created', bfssdir
-            storage = storages.BytesFileSystemStorage(bfssdir)
-            storages.set_attribute_storage(self.repo, 'File', 'data', storage)
-
-.. Note::
-
-  * how we built the hook's registry identifier (`__regid__`): you can introduce
-    'namespaces' by using there python module like naming identifiers. This is
-    especially important for hooks where you usually want a new custom hook, not
-    overriding / specializing an existant one, but the concept may be applied to
-    any application objects
-
-  * we catch two events here: "server_startup" and "server_maintenance". The first
-    is called on regular repository startup (eg, as a server), the other for
-    maintenance task such as shell or upgrade. In both cases, we need to have
-    the storage set, else we'll be in trouble...
-
-  * the path given to the storage is the place where file added through the ui
-    (or in the database before migration) will be located
-
-  * beware that by doing this, you can't anymore write queries that will try to
-    restrict on File `data` attribute. Hopefuly we don't do that usually
-    on file's content or more generally on attributes for the Bytes type
-
-Now, if you've already added some photos through the web ui, you'll have to
-migrate existing data so file's content will be stored on the file-system instead
-of the database. There is a migration command to do so, let's run it in the
-cubicweb shell (in real life, you would have to put it in a migration script as we
-have seen last time):
-
-::
-
-   $ cubicweb-ctl shell sytweb_instance
-   entering the migration python shell
-   just type migration commands or arbitrary python code and type ENTER to execute it
-   type "exit" or Ctrl-D to quit the shell and resume operation
-   >>> storage_changed('File', 'data')
-   [........................]
-
-
-That's it. Now, files added through the web ui will have their content stored on
-the file-system, and you'll also be able to import files from the file-system as
-explained in the next part.
-
-Step 2: importing some data into the instance
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Hey, we start to have some nice features, let us give a try to this new web
-site. For instance if I have a 'photos/201005WePyrenees' containing pictures for
-a particular event, I can import it to my web site by typing ::
-
-  $ cubicweb-ctl fsimport -F sytweb_instance photos/201005WePyrenees/
-  ** importing directory /home/syt/photos/201005WePyrenees
-  importing IMG_8314.JPG
-  importing IMG_8274.JPG
-  importing IMG_8286.JPG
-  importing IMG_8308.JPG
-  importing IMG_8304.JPG
-
-.. Note::
-  The -F option means that folders should be mapped, hence my photos will be
-  linked to a Folder entity corresponding to the file-system folder.
-
-Let's take a look at the web ui:
-
-.. image:: ../../images/tutos-photowebsite_ui1.png
-
-Nothing different, I can't see the new folder... But remember our security model!
-By default, files are only accessible to authenticated users, and I'm looking at
-the site as anonymous, e.g. not authenticated. If I login, I can now see:
-
-.. image:: ../../images/tutos-photowebsite_ui2.png
-
-Yeah, it's there! You will notice that I can see some entities as well as
-folders and images the anonymous user can't. It just works **everywhere in the
-ui** since it's handled at the repository level, thanks to our security model.
-
-Now if I click on the recently inserted folder, I can see
-
-.. image:: ../../images/tutos-photowebsite_ui3.png
-
-Great! There is even my pictures in the folder. I can know give to this folder a
-nicer name (provided I don't intend to import from it anymore, else already
-imported photos will be reimported), change permissions, title for some pictures,
-etc... Having a good content is much more difficult than having a good web site
-;)
-
-
-Conclusion
-~~~~~~~~~~
-
-We started to see here an advanced feature of our repository: the ability
-to store some parts of our data-model into a custom storage, outside the
-database. There is currently only the :class:`BytesFileSystemStorage` available,
-but you can expect to see more coming in a near future (or write your own!).
-
-Also, we can know start to feed our web-site with some nice pictures!
-The site isn't perfect (far from it actually) but it's usable, and we can
-now start using it and improve it on the way. The Incremental Cubic Way :)
--- a/doc/book/en/tutorials/advanced/part04_ui-base.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,361 +0,0 @@
-Let's make it more user friendly
-================================
-
-
-Step 1: let's improve site's usability for our visitors
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The first thing I've noticed is that people to whom I send links to photos with
-some login/password authentication get lost, because they don't grasp they have
-to login by clicking on the 'authenticate' link. That's much probably because
-they only get a 404 when trying to access an unauthorized folder, and the site
-doesn't make clear that 1. you're not authenticated, 2. you could get more
-content by authenticating yourself.
-
-So, to improve this situation, I decided that I should:
-
-* make a login box appears for anonymous, so they see at a first glance a place
-  to put the login / password information I provided
-
-* customize the 404 page, proposing to login to anonymous.
-
-Here is the code, samples from my cube's `views.py` file:
-
-.. sourcecode:: python
-
-    from cubicweb.predicates import is_instance
-    from cubicweb.web import component
-    from cubicweb.web.views import error
-    from cubicweb.predicates import anonymous_user
-
-    class FourOhFour(error.FourOhFour):
-	__select__ = error.FourOhFour.__select__ & anonymous_user()
-
-	def call(self):
-	    self.w(u"<h1>%s</h1>" % self._cw._('this resource does not exist'))
-	    self.w(u"<p>%s</p>" % self._cw._('have you tried to login?'))
-
-
-    class LoginBox(component.CtxComponent):
-	"""display a box containing links to all startup views"""
-	__regid__ = 'sytweb.loginbox'
-	__select__ = component.CtxComponent.__select__ & anonymous_user()
-
-	title = _('Authenticate yourself')
-	order = 70
-
-	def render_body(self, w):
-	    cw = self._cw
-	    form = cw.vreg['forms'].select('logform', cw)
-	    form.render(w=w, table_class='', display_progress_div=False)
-
-The first class provides a new specific implementation of the default page you
-get on 404 error, to display an adapted message to anonymous user.
-
-.. Note::
-
-  Thanks to the selection mecanism, it will be selected for anoymous user,
-  since the additional `anonymous_user()` selector gives it a higher score than
-  the default, and not for authenticated since this selector will return 0 in
-  such case (hence the object won't be selectable)
-
-The second class defines a simple box, that will be displayed by default with
-boxes in the left column, thanks to default :class:`component.CtxComponent`
-selector. The HTML is written to match default CubicWeb boxes style. The code
-fetch the actual login form and render it.
-
-
-.. figure:: ../../images/tutos-photowebsite_login-box.png
-   :alt: login box / 404 screenshot
-
-   The login box and the custom 404 page for an anonymous visitor (translated in french)
-
-
-Step 2: providing a custom index page
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Another thing we can easily do to improve the site is... A nicer index page
-(e.g. the first page you get when accessing the web site)! The default one is
-quite intimidating (that should change in a near future). I will provide a much
-simpler index page that simply list available folders (e.g. photo albums in that
-site).
-
-.. sourcecode:: python
-
-    from cubicweb.web.views import startup
-
-    class IndexView(startup.IndexView):
-	def call(self, **kwargs):
-	    self.w(u'<div>\n')
-	    if self._cw.cnx.anonymous_connection:
-		self.w(u'<h4>%s</h4>\n' % self._cw._('Public Albums'))
-	    else:
-		self.w(u'<h4>%s</h4>\n' % self._cw._('Albums for %s') % self._cw.user.login)
-	    self._cw.vreg['views'].select('tree', self._cw).render(w=self.w)
-	    self.w(u'</div>\n')
-
-    def registration_callback(vreg):
-	vreg.register_all(globals().values(), __name__, (IndexView,))
-	vreg.register_and_replace(IndexView, startup.IndexView)
-
-As you can see, we override the default index view found in
-`cubicweb.web.views.startup`, geting back nothing but its identifier and selector
-since we override the top level view's `call` method.
-
-.. Note::
-
-  in that case, we want our index view to **replace** the existing one. To do so
-  we've to implements the `registration_callback` function, in which we tell to
-  register everything in the module *but* our IndexView, then we register it
-  instead of the former index view.
-
-Also, we added a title that tries to make it more evident that the visitor is
-authenticated, or not. Hopefuly people will get it now!
-
-
-.. figure:: ../../images/tutos-photowebsite_index-before.png
-   :alt: default index page screenshot
-
-   The default index page
-
-.. figure:: ../../images/tutos-photowebsite_index-after.png
-   :alt: new index page screenshot
-
-   Our simpler, less intimidating, index page (still translated in french)
-
-
-Step 3: more navigation improvments
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-There are still a few problems I want to solve...
-
-* Images in a folder are displayed in a somewhat random order. I would like to
-  have them ordered by file's name (which will usually, inside a given folder,
-  also result ordering photo by their date and time)
-
-* When clicking a photo from an album view, you've to get back to the gallery
-  view to go to the next photo. This is pretty annoying...
-
-* Also, when viewing an image, there is no clue about the folder to which this
-  image belongs to.
-
-I will first try to explain the ordering problem. By default, when accessing
-related entities by using the ORM's API, you should get them ordered according to
-the target's class `cw_fetch_order`. If we take a look at the file cube'schema,
-we can see:
-
-.. sourcecode:: python
-
-    class File(AnyEntity):
-	"""customized class for File entities"""
-	__regid__ = 'File'
-	fetch_attrs, cw_fetch_order = fetch_config(['data_name', 'title'])
-
-
-By default, `fetch_config` will return a `cw_fetch_order` method that will order
-on the first attribute in the list. So, we could expect to get files ordered by
-their name. But we don't.  What's up doc ?
-
-The problem is that files are related to folder using the `filed_under` relation.
-And that relation is ambiguous, eg it can lead to `File` entities, but also to
-`Folder` entities. In such case, since both entity types doesn't share the
-attribute on which we want to sort, we'll get linked entities sorted on a common
-attribute (usually `modification_date`).
-
-To fix this, we've to help the ORM. We'll do this in the method from the `ITree`
-folder's adapter, used in the folder's primary view to display the folder's
-content. Here's the code, that I've put in our cube's `entities.py` file, since
-it's more logical stuff than view stuff:
-
-.. sourcecode:: python
-
-    from cubes.folder import entities as folder
-
-    class FolderITreeAdapter(folder.FolderITreeAdapter):
-
-	def different_type_children(self, entities=True):
-	    rql = self.entity.cw_related_rql(self.tree_relation,
-					     self.parent_role, ('File',))
-	    rset = self._cw.execute(rql, {'x': self.entity.eid})
-	    if entities:
-		return list(rset.entities())
-	    return rset
-
-    def registration_callback(vreg):
-	vreg.register_and_replace(FolderITreeAdapter, folder.FolderITreeAdapter)
-
-As you can see, we simple inherit from the adapter defined in the `folder` cube,
-then we override the `different_type_children` method to give a clue to the ORM's
-`cw_related_rql` method, that is responsible to generate the rql to get entities
-related to the folder by the `filed_under` relation (the value of the
-`tree_relation` attribute).  The clue is that we only want to consider the `File`
-target entity type. By doing this, we remove the ambiguity and get back a RQL
-query that correctly order files by their `data_name` attribute.
-
-
-.. Note::
-
-    * As seen earlier, we want to **replace** the folder's `ITree` adapter by our
-      implementation, hence the custom `registration_callback` method.
-
-
-Ouf. That one was tricky...
-
-Now the easier parts. Let's start by adding some links on the file's primary view
-to see the previous / next image in the same folder. CubicWeb's provide a
-component that do exactly that. To make it appears, one have to be adaptable to
-the `IPrevNext` interface. Here is the related code sample, extracted from our
-cube's `views.py` file:
-
-.. sourcecode:: python
-
-    from cubicweb.predicates import is_instance
-    from cubicweb.web.views import navigation
-
-
-    class FileIPrevNextAdapter(navigation.IPrevNextAdapter):
-	__select__ = is_instance('File')
-
-	def previous_entity(self):
-	    rset = self._cw.execute('File F ORDERBY FDN DESC LIMIT 1 WHERE '
-				    'X filed_under FOLDER, F filed_under FOLDER, '
-				    'F data_name FDN, X data_name > FDN, X eid %(x)s',
-				    {'x': self.entity.eid})
-	    if rset:
-		return rset.get_entity(0, 0)
-
-	def next_entity(self):
-	    rset = self._cw.execute('File F ORDERBY FDN ASC LIMIT 1 WHERE '
-				    'X filed_under FOLDER, F filed_under FOLDER, '
-				    'F data_name FDN, X data_name < FDN, X eid %(x)s',
-				    {'x': self.entity.eid})
-	    if rset:
-		return rset.get_entity(0, 0)
-
-
-The `IPrevNext` interface implemented by the adapter simply consist in the
-`previous_entity` / `next_entity` methods, that should respectivly return the
-previous / next entity or `None`. We make an RQL query to get files in the same
-folder, ordered similarly (eg by their `data_name` attribute). We set
-ascendant/descendant ordering and a strict comparison with current file's name
-(the "X" variable representing the current file).
-
-Notice that this query supposes we wont have two files of the same name in the
-same folder, else things may go wrong. Fixing this is out of the scope of this
-blog. And as I would like to have at some point a smarter, context sensitive
-previous/next entity, I'll probably never fix this query (though if I had to, I
-would probably choosing to add a constraint in the schema so that we can't add
-two files of the same name in a folder).
-
-One more thing: by default, the component will be displayed below the content
-zone (the one with the white background). You can change this in the site's
-properties through the ui, but you can also change the default value in the code
-by modifying the `context` attribute of the component:
-
-.. sourcecode:: python
-
-    navigation.NextPrevNavigationComponent.context = 'navcontentbottom'
-
-.. Note::
-
-   `context` may be one of 'navtop', 'navbottom', 'navcontenttop' or
-   'navcontentbottom'; the first two being outside the main content zone, the two
-   others inside it.
-
-.. figure:: ../../images/tutos-photowebsite_prevnext.png
-   :alt: screenshot of the previous/next entity component
-
-   The previous/next entity component, at the bottom of the main content zone.
-
-Now, the only remaining stuff in my todo list is to see the file's folder. I'll use
-the standard breadcrumb component to do so. Similarly as what we've seen before, this
-component is controled by the :class:`IBreadCrumbs` interface, so we'll have to provide a custom
-adapter for `File` entity, telling the a file's parent entity is its folder:
-
-.. sourcecode:: python
-
-    from cubicweb.web.views import ibreadcrumbs
-
-    class FileIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
-	__select__ = is_instance('File')
-
-	def parent_entity(self):
-	    if self.entity.filed_under:
-		return self.entity.filed_under[0]
-
-In that case, we simply use attribute notation provided by the ORM to get the
-folder in which the current file (e.g. `self.entity`) is located.
-
-.. Note::
-
-   The :class:`IBreadCrumbs` interface is a `breadcrumbs` method, but the default
-   :class:`IBreadCrumbsAdapter` provides a default implementation for it that will look
-   at the value returned by its `parent_entity` method. It also provides a
-   default implementation for this method for entities adapting to the `ITree`
-   interface, but as our `File` doesn't, we've to provide a custom adapter.
-
-.. figure:: ../../images/tutos-photowebsite_breadcrumbs.png
-   :alt: screenshot of the breadcrumb component
-
-   The breadcrumb component when on a file entity, now displaying parent folder.
-
-
-Step 4: preparing the release and migrating the instance
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Now that greatly enhanced our cube, it's time to release it to upgrade production site.
-I'll probably detail that process later, but I currently simply transfer the new code
-to the server running the web site.
-
-However, I've still today some step to respect to get things done properly...
-
-First, as I've added some translatable string, I've to run: ::
-
-  $ cubicweb-ctl i18ncube sytweb
-
-To update the cube's gettext catalogs (the '.po' files under the cube's `i18n`
-directory). Once the above command is executed, I'll then update translations.
-
-To see if everything is ok on my test instance, I do: ::
-
-  $ cubicweb-ctl i18ninstance sytweb
-  $ cubicweb-ctl start -D sytweb
-
-The first command compile i18n catalogs (e.g. generates '.mo' files) for my test
-instance. The second command start it in debug mode, so I can open my browser and
-navigate through the web site to see if everything is ok...
-
-.. Note::
-
-   In the 'cubicweb-ctl i18ncube' command, `sytweb` refers to the **cube**, while
-   in the two other, it refers to the **instance** (if you can't see the
-   difference, reread CubicWeb's concept chapter !).
-
-
-Once I've checked it's ok, I simply have to bump the version number in the
-`__pkginfo__` module to trigger a migration once I'll have updated the code on
-the production site. I can check then check the migration is also going fine, by
-first restoring a dump from the production site, then upgrading my test instance.
-
-To generate a dump from the production site: ::
-
-  $ cubicweb-ctl db-dump sytweb
-  pg_dump -Fc --username=syt --no-owner --file /home/syt/etc/cubicweb.d/sytweb/backup/tmpYIN0YI/system sytweb
-  -> backup file /home/syt/etc/cubicweb.d/sytweb/backup/sytweb-2010-07-13_10-22-40.tar.gz
-
-I can now get back the dump file ('sytweb-2010-07-13_10-22-40.tar.gz') to my test
-machine (using `scp` for instance) to restore it and start migration: ::
-
-  $ cubicweb-ctl db-restore sytweb sytweb-2010-07-13_10-22-40.tar.gz
-  $ cubicweb-ctl upgrade sytweb
-
-You'll have to answer some questions, as we've seen in `an earlier post`_.
-
-Now that everything is tested, I can transfer the new code to the production
-server, `apt-get upgrade` cubicweb and its dependencies, and eventually
-upgrade the production instance.
-
-
-.. _`several improvments`: http://www.cubicweb.org/blogentry/1179899
-.. _`3.8`: http://www.cubicweb.org/blogentry/917107
-.. _`first blog of this series`: http://www.cubicweb.org/blogentry/824642
-.. _`an earlier post`: http://www.cubicweb.org/867464
--- a/doc/book/en/tutorials/advanced/part05_ui-advanced.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,374 +0,0 @@
-Building my photos web site with |cubicweb| part V: let's make it even more user friendly
-=========================================================================================
-
-.. _uiprops:
-
-Step 1: tired of the default look?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-OK... Now our site has its most desired features. But... I would like to make it look
-somewhat like *my* website. It is not www.cubicweb.org after all. Let's tackle this
-first!
-
-The first thing we can to is to change the logo. There are various way to achieve
-this. The easiest way is to put a :file:`logo.png` file into the cube's :file:`data`
-directory. As data files are looked at according to cubes order (CubicWeb
-resources coming last), that file will be selected instead of CubicWeb's one.
-
-.. Note::
-   As the location for static resources are cached, you'll have to restart
-   your instance for this to be taken into account.
-
-Though there are some cases where you don't want to use a :file:`logo.png` file.
-For instance if it's a JPEG file. You can still change the logo by defining in
-the cube's :file:`uiprops.py` file:
-
-.. sourcecode:: python
-
-   LOGO = data('logo.jpg')
-
-The uiprops machinery is used to define some static file resources,
-such as the logo, default Javascript / CSS files, as well as CSS
-properties (we'll see that later).
-
-.. Note::
-   This file is imported specifically by |cubicweb|, with a predefined name space,
-   containing for instance the `data` function, telling the file is somewhere
-   in a cube or CubicWeb's data directory.
-
-   One side effect of this is that it can't be imported as a regular python
-   module.
-
-The nice thing is that in debug mode, change to a :file:`uiprops.py` file are detected
-and then automatically reloaded.
-
-Now, as it's a photos web-site, I would like to have a photo of mine as background...
-After some trials I won't detail here, I've found a working recipe explained `here`_.
-All I've to do is to override some stuff of the default CubicWeb user interface to
-apply it as explained.
-
-The first thing to to get the ``<img/>`` tag as first element after the
-``<body>`` tag.  If you know a way to avoid this by simply specifying the image
-in the CSS, tell me!  The easiest way to do so is to override the
-:class:`HTMLPageHeader` view, since that's the one that is directly called once
-the ``<body>`` has been written. How did I find this?  By looking in the
-:mod:`cubiweb.web.views.basetemplates` module, since I know that global page
-layouts sits there. I could also have grep the "body" tag in
-:mod:`cubicweb.web.views`... Finding this was the hardest part. Now all I need is
-to customize it to write that ``img`` tag, as below:
-
-.. sourcecode:: python
-
-    class HTMLPageHeader(basetemplates.HTMLPageHeader):
-	# override this since it's the easier way to have our bg image
-	# as the first element following <body>
-	def call(self, **kwargs):
-            self.w(u'<img id="bg-image" src="%sbackground.jpg" alt="background image"/>'
-                   % self._cw.datadir_url)
-	    super(HTMLPageHeader, self).call(**kwargs)
-
-
-    def registration_callback(vreg):
-	vreg.register_all(globals().values(), __name__, (HTMLPageHeader))
-	vreg.register_and_replace(HTMLPageHeader, basetemplates.HTMLPageHeader)
-
-
-As you may have guessed, my background image is in a :file:`background.jpg` file
-in the cube's :file:`data` directory, but there are still some things to explain
-to newcomers here:
-
-* The :meth:`call` method is there the main access point of the view. It's called by
-  the view's :meth:`render` method. It is not the only access point for a view, but
-  this will be detailed later.
-
-* Calling `self.w` writes something to the output stream. Except for binary views
-  (which do not generate text), it *must* be passed an Unicode string.
-
-* The proper way to get a file in :file:`data` directory is to use the `datadir_url`
-  attribute of the incoming request (e.g. `self._cw`).
-
-I won't explain again the :func:`registration_callback` stuff, you should understand it
-now!  If not, go back to previous posts in the series :)
-
-Fine. Now all I've to do is to add a bit of CSS to get it to behave nicely (which
-is not the case at all for now). I'll put all this in a :file:`cubes.sytweb.css`
-file, stored as usual in our :file:`data` directory:
-
-.. sourcecode:: css
-
-
-    /* fixed full screen background image
-     * as explained on http://webdesign.about.com/od/css3/f/blfaqbgsize.htm
-     *
-     * syt update: set z-index=0 on the img instead of z-index=1 on div#page & co to
-     * avoid pb with the user actions menu
-     */
-    img#bg-image {
-	position: fixed;
-	top: 0;
-	left: 0;
-	width: 100%;
-	height: 100%;
-	z-index: 0;
-    }
-
-    div#page, table#header, div#footer {
-	background: transparent;
-	position: relative;
-    }
-
-    /* add some space around the logo
-     */
-    img#logo {
-	padding: 5px 15px 0px 15px;
-    }
-
-    /* more dark font for metadata to have a chance to see them with the background
-     *  image
-     */
-    div.metadata {
-	color: black;
-    }
-
-You can see here stuff explained in the cited page, with only a slight modification
-explained in the comments, plus some additional rules to make things somewhat cleaner:
-
-* a bit of padding around the logo
-
-* darker metadata which appears by default below the content (the white frame in the page)
-
-To get this CSS file used everywhere in the site, I have to modify the :file:`uiprops.py` file
-introduced above:
-
-.. sourcecode:: python
-
-   STYLESHEETS = sheet['STYLESHEETS'] + [data('cubes.sytweb.css')]
-
-.. Note::
-   `sheet` is another predefined variable containing values defined by
-   already process `:file:`uiprops.py`` file, notably the CubicWeb's one.
-
-Here we simply want our CSS in addition to CubicWeb's base CSS files, so we
-redefine the `STYLESHEETS` variable to existing CSS (accessed through the `sheet`
-variable) with our one added. I could also have done:
-
-.. sourcecode:: python
-
-   sheet['STYLESHEETS'].append(data('cubes.sytweb.css'))
-
-But this is less interesting since we don't see the overriding mechanism...
-
-At this point, the site should start looking good, the background image being
-resized to fit the screen.
-
-.. image:: ../../images/tutos-photowebsite_background-image.png
-
-The final touch: let's customize CubicWeb's CSS to get less orange... By simply adding
-
-.. sourcecode:: python
-
-  contextualBoxTitleBg = incontextBoxTitleBg = '#AAAAAA'
-
-and reloading the page we've just seen, we know have a nice greyed box instead of
-the orange one:
-
-.. image:: ../../images/tutos-photowebsite_grey-box.png
-
-This is because CubicWeb's CSS include some variables which are
-expanded by values defined in uiprops file. In our case we controlled the
-properties of the CSS `background` property of boxes with CSS class
-`contextualBoxTitleBg` and `incontextBoxTitleBg`.
-
-
-Step 2: configuring boxes
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Boxes present to the user some ways to use the application. Let's first do a few
-user interface tweaks in our :file:`views.py` file:
-
-.. sourcecode:: python
-
-  from cubicweb.predicates import none_rset
-  from cubicweb.web.views import bookmark
-  from cubes.zone import views as zone
-  from cubes.tag import views as tag
-
-  # change bookmarks box selector so it's only displayed on startup views
-  bookmark.BookmarksBox.__select__ = bookmark.BookmarksBox.__select__ & none_rset()
-  # move zone box to the left instead of in the context frame and tweak its order
-  zone.ZoneBox.context = 'left'
-  zone.ZoneBox.order = 100
-  # move tags box to the left instead of in the context frame and tweak its order
-  tag.TagsBox.context = 'left'
-  tag.TagsBox.order = 102
-  # hide similarity box, not interested
-  tag.SimilarityBox.visible = False
-
-The idea is to move all boxes in the left column, so we get more space for the
-photos.  Now, serious things: I want a box similar to the tags box but to handle
-the `Person displayed_on File` relation. We can do this simply by adding a
-:class:`AjaxEditRelationCtxComponent` subclass to our views, as below:
-
-.. sourcecode:: python
-
-    from logilab.common.decorators import monkeypatch
-    from cubicweb import ValidationError
-    from cubicweb.web.views import uicfg, component
-    from cubicweb.web.views import basecontrollers
-
-    # hide displayed_on relation using uicfg since it will be displayed by the box below
-    uicfg.primaryview_section.tag_object_of(('*', 'displayed_on', '*'), 'hidden')
-
-    class PersonBox(component.AjaxEditRelationCtxComponent):
-	__regid__ = 'sytweb.displayed-on-box'
-	# box position
-	order = 101
-	context = 'left'
-	# define relation to be handled
-	rtype = 'displayed_on'
-	role = 'object'
-	target_etype = 'Person'
-	# messages
-	added_msg = _('person has been added')
-	removed_msg = _('person has been removed')
-	# bind to js_* methods of the json controller
-	fname_vocabulary = 'unrelated_persons'
-	fname_validate = 'link_to_person'
-	fname_remove = 'unlink_person'
-
-
-    @monkeypatch(basecontrollers.JSonController)
-    @basecontrollers.jsonize
-    def js_unrelated_persons(self, eid):
-	"""return tag unrelated to an entity"""
-	rql = "Any F + ' ' + S WHERE P surname S, P firstname F, X eid %(x)s, NOT P displayed_on X"
-	return [name for (name,) in self._cw.execute(rql, {'x' : eid})]
-
-
-    @monkeypatch(basecontrollers.JSonController)
-    def js_link_to_person(self, eid, people):
-	req = self._cw
-	for name in people:
-	    name = name.strip().title()
-	    if not name:
-		continue
-	    try:
-		firstname, surname = name.split(None, 1)
-	    except:
-		raise ValidationError(eid, {('displayed_on', 'object'): 'provide <first name> <surname>'})
-	    rset = req.execute('Person P WHERE '
-			       'P firstname %(firstname)s, P surname %(surname)s',
-			       locals())
-	    if rset:
-		person = rset.get_entity(0, 0)
-	    else:
-		person = req.create_entity('Person', firstname=firstname,
-						surname=surname)
-	    req.execute('SET P displayed_on X WHERE '
-			'P eid %(p)s, X eid %(x)s, NOT P displayed_on X',
-			{'p': person.eid, 'x' : eid})
-
-    @monkeypatch(basecontrollers.JSonController)
-    def js_unlink_person(self, eid, personeid):
-	self._cw.execute('DELETE P displayed_on X WHERE P eid %(p)s, X eid %(x)s',
-			 {'p': personeid, 'x': eid})
-
-
-You basically subclass to configure with some class attributes. The `fname_*`
-attributes give the name of methods that should be defined on the json control to
-make the AJAX part of the widget work: one to get the vocabulary, one to add a
-relation and another to delete a relation. These methods must start by a `js_`
-prefix and are added to the controller using the `@monkeypatch` decorator. In my
-case, the most complicated method is the one which adds a relation, since it
-tries to see if the person already exists, and else automatically create it,
-assuming the user entered "firstname surname".
-
-Let's see how it looks like on a file primary view:
-
-.. image:: ../../images/tutos-photowebsite_boxes.png
-
-Great, it's now as easy for me to link my pictures to people than to tag them.
-Also, visitors get a consistent display of these two pieces of information.
-
-.. Note::
-  The ui component system has been refactored in `CubicWeb 3.10`_, which also
-  introduced the :class:`AjaxEditRelationCtxComponent` class.
-
-
-Step 3: configuring facets
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The last feature we'll add today is facet configuration. If you access to the
-'/file' url, you'll see a set of 'facets' appearing in the left column. Facets
-provide an intuitive way to build a query incrementally, by proposing to the user
-various way to restrict the result set. For instance CubicWeb proposes a facet to
-restrict based on who created an entity; the tag cube proposes a facet to
-restrict based on tags; the zoe cube a facet to restrict based on geographical
-location, and so on. In that gist, I want to propose a facet to restrict based on
-the people displayed on the picture. To do so, there are various classes in the
-:mod:`cubicweb.web.facet` module which simply have to be configured using class
-attributes as we've done for the box. In our case, we'll define a subclass of
-:class:`RelationFacet`.
-
-.. Note::
-
-   Since that's ui stuff, we'll continue to add code below to our
-   :file:`views.py` file. Though we begin to have a lot of various code their, so
-   it's may be a good time to split our views module into submodules of a `view`
-   package. In our case of a simple application (glue) cube, we could start using
-   for instance the layout below: ::
-
-     views/__init__.py   # uicfg configuration, facets
-     views/layout.py     # header/footer/background stuff
-     views/components.py # boxes, adapters
-     views/pages.py      # index view, 404 view
-
-.. sourcecode:: python
-
-    from cubicweb.web import facet
-
-    class DisplayedOnFacet(facet.RelationFacet):
-	__regid__ = 'displayed_on-facet'
-	# relation to be displayed
-	rtype = 'displayed_on'
-	role = 'object'
-	# view to use to display persons
-	label_vid = 'combobox'
-
-Let's say we also want to filter according to the `visibility` attribute. This is
-even simpler as we just have to derive from the :class:`AttributeFacet` class:
-
-.. sourcecode:: python
-
-    class VisibilityFacet(facet.AttributeFacet):
-	__regid__ = 'visibility-facet'
-	rtype = 'visibility'
-
-Now if I search for some pictures on my site, I get the following facets available:
-
-.. image:: ../../images/tutos-photowebsite_facets.png
-
-.. Note::
-
-  By default a facet must be applyable to every entity in the result set and
-  provide at leat two elements of vocabulary to be displayed (for instance you
-  won't see the `created_by` facet if the same user has created all
-  entities). This may explain why you don't see yours...
-
-
-Conclusion
-~~~~~~~~~~
-
-We started to see the power behind the infrastructure provided by the
-framework, both on the pure ui (CSS, Javascript) side and on the Python side
-(high level generic classes for components, including boxes and facets). We now
-have, with a few lines of code, a full-featured web site with a personalized look.
-
-Of course we'll probably want more as time goes, but we can now
-concentrate on making good pictures, publishing albums and sharing them with
-friends...
-
-
-
-.. _`CubicWeb 3.10`: http://www.cubicweb.org/blogentry/1330518
-.. _`here`: http://webdesign.about.com/od/css3/f/blfaqbgsize.htm
--- a/doc/book/en/tutorials/base/blog-in-five-minutes.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _TutosBaseBlogFiveMinutes:
-
-Get a blog running in five minutes!
------------------------------------
-
-For Debian or Ubuntu users, first install the following packages
-(:ref:`DebianInstallation`)::
-
-    cubicweb, cubicweb-dev, cubicweb-blog
-
-Windows or Mac OS X users must install |cubicweb| from source (see
-:ref:`SourceInstallation` and :ref:`WindowsInstallation`).
-
-Then create and initialize your instance::
-
-    cubicweb-ctl create blog myblog
-
-You'll be asked a few questions, and you can keep the default answer for most of
-them. The one question you'll have to think about is the database you'll want to
-use for that instance. For a quick test, if you don't have `postgresql` installed
-and configured (see :ref:`PostgresqlConfiguration`), it's highly recommended to
-choose `sqlite` when asked for which database driver to use, since it has a much
-simple setup (no database server needed).
-
-One the process is completed (including database initialisation), you can start
-your instance by using: ::
-
-    cubicweb-ctl start -D myblog
-
-The `-D` option activates the debugging mode. Removing it will launch the instance
-as a daemon in the background, and ``cubicweb-ctl stop myblog`` will stop
-it in that case. 
-
-
-About file system permissions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Unless you installed from sources, the above commands assume that you have root
-access to the :file:`/etc/` directory. In order to initialize your instance as a
-regular user, within your home directory, you can use the :envvar:`CW_MODE`
-environment variable: ::
-
-  export CW_MODE=user
-
-then create a :file:`~/etc/cubicweb.d` directory that will hold your instances.
-
-More information about how to configure your own environment is
-available in :ref:`ResourceMode`.
-
-
-Instance parameters
-~~~~~~~~~~~~~~~~~~~
-
-If you would like to change database parameters such as the database host or the
-user name used to connect to the database, edit the `sources` file located in the
-:file:`/etc/cubicweb.d/myblog` directory.
-
-Then relaunch the database creation::
-
-     cubicweb-ctl db-create myblog
-
-Other parameters, like web server or emails parameters, can be modified in the
-:file:`/etc/cubicweb.d/myblog/all-in-one.conf` file.
-
-You'll have to restart the instance after modification in one of those files.
-
-This is it. Your blog is functional and running. Visit http://localhost:8080 and enjoy it!
-
--- a/doc/book/en/tutorials/base/conclusion.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-What's next?
-------------
-
-In this tutorial, we have seen that you can, right after the installation of
-|cubicweb|, build a web application in a few minutes by defining a data model as
-assembling cubes. You get a working application that you can then customize there
-and there while keeping something that works. This is important in agile
-development practices, you can right from the start of the project show things
-to customer and so take the right decision early in the process.
-
-The next steps will be to discover hooks, security, data sources, digging deeper
-into view writing and interface customisation... Yet a lot of fun stuff to
-discover! You will find more `tutorials and howtos`_ in the blog published on the
-CubicWeb.org website.
-
-.. _`tutorials and howtos`: http://www.cubicweb.org/view?rql=Any+X+ORDERBY+D+DESC+WHERE+X+is+BlogEntry%2C+T+tags+X%2C+T+name+IN+%28%22tutorial%22%2C+%22howto%22%29%2C+X+creation_date+D
--- a/doc/book/en/tutorials/base/customizing-the-application.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,539 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _TutosBaseCustomizingTheApplication:
-
-Customizing your application
-----------------------------
-
-So far so good. The point is that usually, you won't get enough by assembling
-cubes out-of-the-box. You will want to customize them, have a personal look and
-feel, add your own data model and so on. Or maybe start from scratch?
-
-So let's get a bit deeper and start coding our own cube. In our case, we want
-to customize the blog we created to add more features to it.
-
-
-Create your own cube
-~~~~~~~~~~~~~~~~~~~~
-
-First, notice that if you've installed |cubicweb| using Debian packages, you will
-need the additional ``cubicweb-dev`` package to get the commands necessary to
-|cubicweb| development. All `cubicweb-ctl` commands are described in details in
-:ref:`cubicweb-ctl`.
-
-Once your |cubicweb| development environment is set up, you can create a new
-cube::
-
-  cubicweb-ctl newcube myblog
-
-This will create in the cubes directory (:file:`/path/to/grshell/cubes` for source
-installation, :file:`/usr/share/cubicweb/cubes` for Debian packages installation)
-a directory named :file:`blog` reflecting the structure described in
-:ref:`cubelayout`.
-
-For packages installation, you can still create new cubes in your home directory
-using the following configuration. Let's say you want to develop your new cubes
-in `~src/cubes`, then set the following environment variables: ::
-
-  CW_CUBES_PATH=~/src/cubes
-
-and then create your new cube using: ::
-
-  cubicweb-ctl newcube --directory=~/src/cubes myblog
-
-.. Note::
-
-   We previously used `myblog` as the name of our *instance*. We're now creating
-   a *cube* with the same name. Both are different things. We'll now try to
-   specify when we talk about one or another, but keep in mind this difference.
-
-
-Cube metadata
-~~~~~~~~~~~~~
-
-A simple set of metadata about your cube are stored in the :file:`__pkginfo__.py`
-file. In our case, we want to extend the blog cube, so we have to tell that our
-cube depends on this cube, by modifying the ``__depends__`` dictionary in that
-file:
-
-.. sourcecode:: python
-
-   __depends__ =  {'cubicweb': '>= 3.10.7',
-                   'cubicweb-blog': None}
-
-where the ``None`` means we do not depends on a particular version of the cube.
-
-.. _TutosBaseCustomizingTheApplicationDataModel:
-
-Extending the data model
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-The data model or schema is the core of your |cubicweb| application.  It defines
-the type of content your application will handle. It is defined in the file
-:file:`schema.py` of the cube.
-
-
-Defining our model
-******************
-
-For the sake of example, let's say we want a new entity type named `Community`
-with a name, a description. A `Community` will hold several blogs.
-
-.. sourcecode:: python
-
-  from yams.buildobjs import EntityType, RelationDefinition, String, RichString
-
-  class Community(EntityType):
-      name = String(maxsize=50, required=True)
-      description = RichString()
-
-  class community_blog(RelationDefinition):
-      subject = 'Community'
-      object = 'Blog'
-      cardinality = '*?'
-      composite = 'subject'
-
-The first step is the import from the :mod:`yams` package necessary classes to build
-the schema.
-
-This file defines the following:
-
-* a `Community` has a title and a description as attributes
-
-  - the name is a string that is required and can't be longer than 50 characters
-
-  - the description is a string that is not constrained and may contains rich
-    content such as HTML or Restructured text.
-
-* a `Community` may be linked to a `Blog` using the `community_blog` relation
-
-  - ``*`` means a community may be linked to 0 to N blog, ``?`` means a blog may
-    be linked to 0 to 1 community. For completeness, remember that you can also
-    use ``+`` for 1 to N, and ``1`` for single, mandatory relation (e.g. one to one);
-
-  - this is a composite relation where `Community` (e.g. the subject of the
-    relation) is the composite. That means that if you delete a community, its
-    blog will be deleted as well.
-
-Of course, there are a lot of other data types and things such as constraints,
-permissions, etc, that may be defined in the schema, but those won't be covered
-in this tutorial.
-
-Notice that our schema refers to the `Blog` entity type which is not defined
-here.  But we know this type is available since we depend on the `blog` cube
-which is defining it.
-
-
-Applying changes to the model into our instance
-***********************************************
-
-Now the problem is that we created an instance using the `blog` cube, not our
-`myblog` cube, so if we don't do anything there is no way that we'll see anything
-changing in the instance.
-
-One easy way, as we've no really valuable data in the instance would be to trash and recreated it::
-
-  cubicweb-ctl stop myblog # or Ctrl-C in the terminal running the server in debug mode
-  cubicweb-ctl delete myblog
-  cubicweb-ctl create myblog
-  cubicweb-ctl start -D myblog
-
-Another way is to add our cube to the instance using the cubicweb-ctl shell
-facility. It's a python shell connected to the instance with some special
-commands available to manipulate it (the same as you'll have in migration
-scripts, which are not covered in this tutorial). In that case, we're interested
-in the `add_cube` command: ::
-
-  $ cubicweb-ctl stop myblog # or Ctrl-C in the terminal running the server in debug mode
-  $ cubicweb-ctl shell myblog
-  entering the migration python shell
-  just type migration commands or arbitrary python code and type ENTER to execute it
-  type "exit" or Ctrl-D to quit the shell and resume operation
-  >>> add_cube('myblog')
-  >>>
-  $ cubicweb-ctl start -D myblog
-
-The `add_cube` command is enough since it automatically updates our
-application to the cube's schema. There are plenty of other migration
-commands of a more finer grain. They are described in :ref:`migration`
-
-As explained, leave the shell by typing Ctrl-D. If you restart the instance and
-take another look at the schema, you'll see that changes to the data model have
-actually been applied (meaning database schema updates and all necessary stuff
-has been done).
-
-.. image:: ../../images/tutos-base_myblog-schema_en.png
-   :alt: the instance schema after adding our cube
-
-If you follow the 'info' link in the user pop-up menu, you'll also see that the
-instance is using blog and myblog cubes.
-
-.. image:: ../../images/tutos-base_myblog-siteinfo_en.png
-   :alt: the instance schema after adding our cube
-
-You can now add some communities, link them to blog, etc... You'll see that the
-framework provides default views for this entity type (we have not yet defined any
-view for it!), and also that the blog primary view will show the community it's
-linked to if any. All this thanks to the model driven interface provided by the
-framework.
-
-You'll then be able to redefine each of them according to your needs
-and preferences. We'll now see how to do such thing.
-
-.. _TutosBaseCustomizingTheApplicationCustomViews:
-
-Defining your views
-~~~~~~~~~~~~~~~~~~~
-
-|cubicweb| provides a lot of standard views in directory
-:file:`cubicweb/web/views/`. We already talked about 'primary' and 'list' views,
-which are views which apply to one ore more entities.
-
-A view is defined by a python class which includes:
-
-  - an identifier: all objects used to build the user interface in |cubicweb| are
-    recorded in a registry and this identifier will be used as a key in that
-    registry. There may be multiple views for the same identifier.
-
-  - a *selector*, which is a kind of filter telling how well a view suit to a
-    particular context. When looking for a particular view (e.g. given an
-    identifier), |cubicweb| computes for each available view with that identifier
-    a score which is returned by the selector. Then the view with the highest
-    score is used. The standard library of predicates is in
-    :mod:`cubicweb.predicates`.
-
-A view has a set of methods inherited from the :class:`cubicweb.view.View` class,
-though you usually don't derive directly from this class but from one of its more
-specific child class.
-
-Last but not least, |cubicweb| provides a set of default views accepting any kind
-of entities.
-
-Want a proof? Create a community as you've already done for other entity types
-through the index page, you'll then see something like that:
-
-.. image:: ../../images/tutos-base_myblog-community-default-primary_en.png
-   :alt: the default primary view for our community entity type
-
-
-If you notice the weird messages that appear in the page: those are messages
-generated for the new data model, which have no translation yet. To fix that,
-we'll have to use dedicated `cubicweb-ctl` commands:
-
-.. sourcecode: bash
-
-  cubicweb-ctl i18ncube myblog # build/update cube's message catalogs
-  # then add translation into .po file into the cube's i18n directory
-  cubicweb-ctl i18ninstance myblog # recompile instance's message catalogs
-  cubicweb-ctl restart -D myblog # instance has to be restarted to consider new catalogs
-
-You'll then be able to redefine each of them according to your needs and
-preferences. So let's see how to do such thing.
-
-Changing the layout of the application
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The layout is the general organization of the pages in the site. Views that generate
-the layout are sometimes referred to as 'templates'. They are implemented in the
-framework in the module :mod:`cubicweb.web.views.basetemplates`. By overriding
-classes in this module, you can customize whatever part you wish of the default
-layout.
-
-But notice that |cubicweb| provides many other ways to customize the
-interface, thanks to actions and components (which you can individually
-(de)activate, control their location, customize their look...) as well as
-"simple" CSS customization. You should first try to achieve your goal using such
-fine grained parametrization rather then overriding a whole template, which usually
-embeds customisation access points that you may loose in the process.
-
-But for the sake of example, let's say we want to change the generic page
-footer...  We can simply add to the module ``views`` of our cube,
-e.g. :file:`cubes/myblog/views.py`, the code below:
-
-.. sourcecode:: python
-
-  from cubicweb.web.views import basetemplates
-
-  class MyHTMLPageFooter(basetemplates.HTMLPageFooter):
-
-      def footer_content(self):
-	  self.w(u'This website has been created with <a href="http://cubicweb.org">CubicWeb</a>.')
-
-  def registration_callback(vreg):
-      vreg.register_all(globals().values(), __name__, (MyHTMLPageFooter,))
-      vreg.register_and_replace(MyHTMLPageFooter, basetemplates.HTMLPageFooter)
-
-
-* Our class inherits from the default page footer to ease getting things right,
-  but this is not mandatory.
-
-* When we want to write something to the output stream, we simply call `self.w`,
-  which *must be passed a unicode string*.
-
-* The latest function is the most exotic stuff. The point is that without it, you
-  would get an error at display time because the framework wouldn't be able to
-  choose which footer to use between :class:`HTMLPageFooter` and
-  :class:`MyHTMLPageFooter`, since both have the same selector, hence the same
-  score...  In this case, we want our footer to replace the default one, so we have
-  to define a :func:`registration_callback` function to control object
-  registration: the first instruction tells to register everything in the module
-  but the :class:`MyHTMLPageFooter` class, then the second to register it instead
-  of :class:`HTMLPageFooter`. Without this function, everything in the module is
-  registered blindly.
-
-.. Note::
-
-  When a view is modified while running in debug mode, it is not required to
-  restart the instance server. Save the Python file and reload the page in your
-  web browser to view the changes.
-
-We will now have this simple footer on every page of the site.
-
-
-Primary view customization
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The 'primary' view (i.e. any view with the identifier set to 'primary') is the one used to
-display all the information about a single entity. The standard primary view is one
-of the most sophisticated views of all. It has several customisation points, but
-its power comes with `uicfg`, allowing you to control it without having to
-subclass it.
-
-However this is a bit off-topic for this first tutorial. Let's say we simply want a
-custom primary view for my `Community` entity type, using directly the view
-interface without trying to benefit from the default implementation (you should
-do that though if you're rewriting reusable cubes; everything is described in more
-details in :ref:`primary_view`).
-
-
-So... Some code! That we'll put again in the module ``views`` of our cube.
-
-.. sourcecode:: python
-
-  from cubicweb.predicates import is_instance
-  from cubicweb.web.views import primary
-
-  class CommunityPrimaryView(primary.PrimaryView):
-      __select__ = is_instance('Community')
-
-      def cell_call(self, row, col):
-          entity = self.cw_rset.get_entity(row, col)
-          self.w(u'<h1>Welcome to the "%s" community</h1>' % entity.printable_value('name'))
-          if entity.description:
-              self.w(u'<p>%s</p>' % entity.printable_value('description'))
-
-What's going on here?
-
-* Our class inherits from the default primary view, here mainly to get the correct
-  view identifier, since we don't use any of its features.
-
-* We set on it a selector telling that it only applies when trying to display
-  some entity of the `Community` type. This is enough to get an higher score than
-  the default view for entities of this type.
-
-* View applying to entities usually have to define `cell_call` as entry point,
-  and are given `row` and `col` arguments tell to which entity in the result set
-  the view is applied. We can then get this entity from the result set
-  (`self.cw_rset`) by using the `get_entity` method.
-
-* To ease thing, we access our entity's attribute for display using its
-  printable_value method, which will handle formatting and escaping when
-  necessary. As you can see, you can also access attributes by their name on the
-  entity to get the raw value.
-
-
-You can now reload the page of the community we just created and see the changes.
-
-.. image:: ../../images/tutos-base_myblog-community-custom-primary_en.png
-   :alt: the custom primary view for our community entity type
-
-We've seen here a lot of thing you'll have to deal with to write views in
-|cubicweb|. The good news is that this is almost everything that is used to
-build higher level layers.
-
-.. Note::
-
-  As things get complicated and the volume of code in your cube increases, you can
-  of course still split your views module into a python package with subpackages.
-
-You can find more details about views and selectors in :ref:`Views`.
-
-
-Write entities to add logic in your data
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-|cubicweb| provides an ORM to easily programmaticaly manipulate
-entities (just like the one we have fetched earlier by calling
-`get_entity` on a result set). By default, entity
-types are instances of the :class:`AnyEntity` class, which holds a set of
-predefined methods as well as property automatically generated for
-attributes/relations of the type it represents.
-
-You can redefine each entity to provide additional methods or whatever you want
-to help you write your application. Customizing an entity requires that your
-entity:
-
-- inherits from :class:`cubicweb.entities.AnyEntity` or any subclass
-
-- defines a :attr:`__regid__` linked to the corresponding data type of your schema
-
-You may then want to add your own methods, override default implementation of some
-method, etc...
-
-.. sourcecode:: python
-
-    from cubicweb.entities import AnyEntity, fetch_config
-
-
-    class Community(AnyEntity):
-        """customized class for Community entities"""
-        __regid__ = 'Community'
-
-        fetch_attrs, cw_fetch_order = fetch_config(['name'])
-
-        def dc_title(self):
-            return self.name
-
-        def display_cw_logo(self):
-            return 'CubicWeb' in self.description
-
-In this example:
-
-* we used convenience :func:`fetch_config` function to tell which attributes
-  should be prefetched by the ORM when looking for some related entities of this
-  type, and how they should be ordered
-
-* we overrode the standard `dc_title` method, used in various place in the interface
-  to display the entity (though in this case the default implementation would
-  have had the same result)
-
-* we implemented here a method :meth:`display_cw_logo` which tests if the blog
-  entry title contains 'CW'.  It can then be used when you're writing code
-  involving 'Community' entities in your views, hooks, etc. For instance, you can
-  modify your previous views as follows:
-
-.. sourcecode:: python
-
-
-  class CommunityPrimaryView(primary.PrimaryView):
-      __select__ = is_instance('Community')
-
-      def cell_call(self, row, col):
-          entity = self.cw_rset.get_entity(row, col)
-          self.w(u'<h1>Welcome to the "%s" community</h1>' % entity.printable_value('name'))
-          if entity.display_cw_logo():
-              self.w(u'<img src="http://www.cubicweb.org/doc/en/_static/cubicweb.png"/>')
-          if entity.description:
-              self.w(u'<p>%s</p>' % entity.printable_value('description'))
-
-Then each community whose description contains 'CW' is shown with the |cubicweb|
-logo in front of it.
-
-.. Note::
-
-  As for view, you don't have to restart your instance when modifying some entity
-  classes while your server is running in debug mode, the code will be
-  automatically reloaded.
-
-
-Extending the application by using more cubes!
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-One of the goal of the |cubicweb| framework was to have truly reusable
-components. To do so, they must both behave nicely when plugged into the
-application and be easily customisable, from the data model to the user
-interface. And I think the result is pretty successful, thanks to system such as
-the selection mechanism and the choice to write views as python code which allows
-to build our page using true object oriented programming techniques, that no
-template language provides.
-
-
-A library of standard cubes is available from `CubicWeb Forge`_, to address a
-lot of common concerns such has manipulating people, files, things to do, etc. In
-our community blog case, we could be interested for instance in functionalities
-provided by the `comment` and `tag` cubes. The former provides threaded
-discussion functionalities, the latter a simple tag mechanism to classify content.
-Let's say we want to try those. We will first modify our cube's :file:`__pkginfo__.py`
-file:
-
-.. sourcecode:: python
-
-   __depends__ =  {'cubicweb': '>= 3.10.7',
-                   'cubicweb-blog': None,
-                   'cubicweb-comment': None,
-                   'cubicweb-tag': None}
-
-Now, we'll simply tell on which entity types we want to activate the 'comment'
-and 'tag' facilities by adding respectively the 'comments' and 'tags' relations on
-them in our schema (:file:`schema.py`).
-
-.. sourcecode:: python
-
-  class comments(RelationDefinition):
-      subject = 'Comment'
-      object = 'BlogEntry'
-      cardinality = '1*'
-      composite = 'object'
-
-  class tags(RelationDefinition):
-      subject = 'Tag'
-      object = ('Community', 'BlogEntry')
-
-
-So in the case above we activated comments on `BlogEntry` entities and tags on
-both `Community` and `BlogEntry`. Various views from both `comment` and `tag`
-cubes will then be automatically displayed when one of those relations is
-supported.
-
-Let's synchronize the data model as we've done earlier: ::
-
-
-  $ cubicweb-ctl stop myblog
-  $ cubicweb-ctl shell myblog
-  entering the migration python shell
-  just type migration commands or arbitrary python code and type ENTER to execute it
-  type "exit" or Ctrl-D to quit the shell and resume operation
-  >>> add_cubes(('comment', 'tag'))
-  >>>
-
-Then restart the instance. Let's look at a blog entry:
-
-.. image:: ../../images/tutos-base_myblog-blogentry-taggable-commentable-primary_en.png
-   :alt: the primary view for a blog entry with comments and tags activated
-
-As you can see, we now have a box displaying tags and a section proposing to add
-a comment and displaying existing one below the post. All this without changing
-anything in our views, thanks to the design of generic views provided by the
-framework. Though if we take a look at a community, we won't see the tags box!
-That's because by default this box try to locate itself in the left column within
-the white frame, and this column is handled by the primary view we
-hijacked. Let's change our view to make it more extensible, by keeping both our
-custom rendering but also extension points provided by the default
-implementation.
-
-
-.. sourcecode:: python
-
-  class CommunityPrimaryView(primary.PrimaryView):
-      __select__ = is_instance('Community')
-
-      def render_entity_title(self, entity):
-	  self.w(u'<h1>Welcome to the "%s" community</h1>' % entity.printable_value('name'))
-
-      def render_entity_attributes(self, entity):
-	  if entity.display_cw_logo():
-	      self.w(u'<img src="http://www.cubicweb.org/doc/en/_static/cubicweb.png"/>')
-	  if entity.description:
-	      self.w(u'<p>%s</p>' % entity.printable_value('description'))
-
-It appears now properly:
-
-.. image:: ../../images/tutos-base_myblog-community-taggable-primary_en.png
-   :alt: the custom primary view for a community entry with tags activated
-
-You can control part of the interface independently from each others, piece by
-piece. Really.
-
-
-
-.. _`CubicWeb Forge`: http://www.cubicweb.org/project
--- a/doc/book/en/tutorials/base/discovering-the-ui.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-
-.. _TutosBaseDiscoveringTheUI:
-
-Discovering the web interface
------------------------------
-
-You can now access your web instance to create blogs and post messages
-by visiting the URL http://localhost:8080/.
-
-By default, anonymous access is disabled, so a login form will appear. If you
-asked to allow anonymous access when initializing the instance, click on the
-'login' link in the top right hand corner. To login, you need then use the admin
-account you specified at the time you initialized the database with
-``cubicweb-ctl create``.
-
-.. image:: ../../images/tutos-base_login-form_en.png
-   :alt: the login form
-
-
-Once authenticated, you can start playing with your instance. The default index
-page looks like the following:
-
-.. image:: ../../images/tutos-base_index_en.png
-   :alt: the index page
-
-
-Minimal configuration
-~~~~~~~~~~~~~~~~~~~~~
-
-Before creating entities, let's change that 'unset title' thing that appears
-here and there. This comes from a |cubicweb| system properties. To set it,
-click on the 'site configuration link' in the pop-up menu behind your login name
-in the upper left-hand corner
-
-.. image:: ../../images/tutos-base_user-menu_en.png
-   :alt: the user pop-up menu
-
-The site title is in the 'Ui' section. Simply set it to the desired value and
-click the 'validate' button.
-
-.. image:: ../../images/tutos-base_siteconfig_en.png
-   :alt: the site configuration form
-
-You should see a 'changes applied' message. You can now go back to the
-index page by clicking on the |cubicweb| logo in the upper left-hand corner.
-
-You will much likely still see 'unset title' at this point. This is because by
-default the index page is cached. Force a refresh of the page (by typing Ctrl-R
-in Firefox for instance) and you should now see the title you entered.
-
-
-Adding entities
-~~~~~~~~~~~~~~~
-
-The ``blog`` cube defines several entity types, among them ``Blog`` which is a
-container for ``BlogEntry`` (i.e. posts) on a particular topic. We can get a
-graphical view of the schema by clicking on the 'site schema' link in the user
-pop-up menu we've already seen:
-
-.. image:: ../../images/tutos-base_schema_en.png
-   :alt: graphical view of the schema (aka data-model)
-
-Nice isn't it? Notice that this, as most other stuff we'll see in this tutorial,
-is generated by the framework according to the model of the application. In our
-case, the model defined by the ``blog`` cube.
-
-Now let us create a few of these entities.
-
-
-Add a blog
-**********
-
-Clicking on the `[+]` at the left of the 'Blog' link on the index page will lead
-you to an HTML form to create a blog.
-
-.. image:: ../../images/tutos-base_blog-form_en.png
-   :alt: the blog creation form
-
-For instance, call this new blog 'Tech-blog' and type in 'everything about
-technology' as the description , then validate the form by clicking on
-'Validate'. You will be redirected to the `primary` view of the newly created blog.
-
-.. image:: ../../images/tutos-base_blog-primary_en.png
-   :alt: the blog primary view
-
-
-Add a blog post
-***************
-
-There are several ways to add a blog entry. The simplest is to click on the 'add
-blog entry' link in the actions box on viewing the blog you have just created.
-You will then see a form to create a post, with a 'blog entry of' field preset
-to the blog we're coming from. Enter a title, some content, click the 'validate'
-button and you're done. You will be redirected to the blog primary view, though you
-now see that it contains the blog post you've just created.
-
-.. image:: ../../images/tutos-base_blog-primary-after-post-creation_en.png
-   :alt: the blog primary view after creation of a post
-
-Notice there are some new boxes that appears in the left column.
-
-You can achieve the same thing by following the same path as we did for the blog
-creation, e.g. by clicking on the `[+]` at the left of the 'Blog entry' link on
-the index page. The diffidence being that since there is no context information,
-the 'blog entry of' selector won't be preset to the blog.
-
-
-If you click on the 'modify' link of the action box, you are back to
-the form to edit the entity you just created, except that the form now
-has another section with a combo-box entitled 'add relation'. It
-provisos a generic way to edit relations which don't appears in the
-above form. Choose the relation you want to add and a second combo box
-appears where you can pick existing entities.  If there are too many
-of them, you will be offered to navigate to the target entity, that is
-go away from the form and go back to it later, once you've selected
-the entity you want to link with.
-
-.. image:: ../../images/tutos-base_form-generic-relations_en.png
-   :alt: the generic relations combo box
-
-This combo box can't appear until the entity is actually created. That's why you
-haven't seen it at creation time. You could also have hit 'Apply' instead of
-'validate' and it would have showed up.
-
-
-About ui auto-adaptation
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-One of the things that make |cubicweb| different of other frameworks is
-its automatic user interface that adapts itself according to the data being
-displayed. Let's see an example.
-
-If you go back to the home page an click on the 'Blog' link, you will be redirected
-to the primary view of the blog, the same we've seen earlier. Now, add another
-blog, go back to the index page, and click again on this link. You will see
-a very different view (namely the 'list' view).
-
-.. image:: ../../images/tutos-base_blogs-list_en.png
-   :alt: the list view when there are more than one blog to display
-
-This is because in the first case, the framework chose to use the 'primary'
-view since there was only one entity in the data to be displayed. Now that there
-are two entities, the 'list' view is more appropriate and hence is being used.
-
-There are various other places where |cubicweb| adapts to display data in the best
-way, the main being provided by the view *selection* mechanism that will be detailed
-later.
-
-
-Digging deeper
-~~~~~~~~~~~~~~
-
-By following principles explained below, you should now be able to
-create new users for your application, to configure with a finer
-grain, etc... You will notice that the index page lists a lot of types
-you don't know about. Most are built-in types provided by the framework
-to make the whole system work. You may ignore them in a first time and
-discover them as time goes.
-
-One thing that is worth playing with is the search box. It may be used in various
-way, from simple full text search to advanced queries using the :ref:`RQL` .
--- a/doc/book/en/tutorials/base/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _TutosBase:
-
-Building a simple blog with |cubicweb|
-======================================
-
-|cubicweb| is a semantic web application framework that favors reuse and
-object-oriented design.
-
-
-This tutorial is designed to help in your very first steps to start with
-|cubicweb|. We will tour through basic concepts such as:
-
-* getting an application running by using existing components
-* discovering the default user interface
-* basic extending and customizing the look and feel of that application
-
-More advanced concepts are covered in :ref:`TutosPhotoWebSite`.
-
-
-.. _TutosBaseVocab:
-
-Some vocabulary
----------------
-
-|cubicweb| comes with a few words of vocabulary that you should know to
-understand what we're talking about. To follow this tutorial, you should at least
-know that:
-
-* a `cube` is a component that usually includes a model defining some data types
-  and a set of views to display them. A cube can be built by assembling other
-  cubes;
-
-* an `instance` is a specific installation of one or more cubes and includes
-  configuration files, a web server and a database.
-
-Reading :ref:`Concepts` for more vocabulary will be required at some point.
-
-Now, let's start the hot stuff!
-
-.. toctree::
-   :maxdepth: 2
-
-   blog-in-five-minutes
-   discovering-the-ui
-   customizing-the-application
-   conclusion
--- a/doc/book/en/tutorials/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-.. _Tutorials:
-
----------
-Tutorials
----------
-
-We present two tutorials of different levels. The blog building
-tutorial introduces one smoothly to the basic concepts.
-
-Then there is a photo gallery construction tutorial which highlights
-more advanced concepts such as unit tests, security settings,
-migration scripts.
-
-.. toctree::
-   :maxdepth: 1
-   :numbered:
-
-   base/index
-   advanced/index
-   tools/windmill.rst
-   textreports/index
--- a/doc/book/en/tutorials/textreports/index.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Writing text reports with RestructuredText
-==========================================
-
-|cubicweb| offers several text formats for the RichString type used in schemas,
-including restructuredtext.
-
-Three additional restructuredtext roles are defined by |cubicweb|:
-
-.. autofunction:: cubicweb.ext.rest.eid_reference_role
-.. autofunction:: cubicweb.ext.rest.rql_role
-.. autofunction:: cubicweb.ext.rest.bookmark_role
--- a/doc/book/en/tutorials/tools/windmill.rst	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-==========================
-Use Windmill with CubicWeb
-==========================
-
-Windmill_ implements cross browser testing, in-browser recording and playback,
-and functionality for fast accurate debugging and test environment integration.
-
-.. _Windmill: http://www.getwindmill.com/
-
-`Online features list <http://www.getwindmill.com/features>`_ is available.
-
-
-Installation
-============
-
-Windmill
---------
-
-You have to install Windmill manually for now. If you're using Debian, there is
-no binary package (`yet <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=579109>`_).
-
-The simplest solution is to use a *setuptools/pip* command (for a clean
-environment, take a look to the `virtualenv
-<http://pypi.python.org/pypi/virtualenv>`_ project as well)::
-
-    $ pip install windmill
-    $ curl -O http://github.com/windmill/windmill/tarball/master
-
-However, the Windmill project doesn't release frequently. Our recommandation is
-to used the last snapshot of the Git repository::
-
-    $ git clone git://github.com/windmill/windmill.git HEAD
-    $ cd windmill
-    $ python setup.py develop
-
-Install instructions are `available <http://wiki.github.com/windmill/windmill/installing>`_.
-
-Be sure to have the windmill module in your PYTHONPATH afterwards::
-
-    $ python -c "import windmill"
-
-X dummy
--------
-
-In order to reduce unecessary system load from your test machines, It's
-recommended to use X dummy server for testing the Unix web clients, you need a
-dummy video X driver (as xserver-xorg-video-dummy package in Debian) coupled
-with a light X server as `Xvfb <http://en.wikipedia.org/wiki/Xvfb>`_.
-
-    The dummy driver is a special driver available with the XFree86 DDX. To use
-    the dummy driver, simply substitue it for your normal card driver in the
-    Device section of your xorg.conf configuration file. For example, if you
-    normally uses an ati driver, then you will have a Device section with
-    Driver "ati" to let the X server know that you want it to load and use the
-    ati driver; however, for these conformance tests, you would change that
-    line to Driver "dummy" and remove any other ati specific options from the
-    Device section.
-
-    *From: http://www.x.org/wiki/XorgTesting*
-
-Then, you can run the X server with the following command ::
-
-    $ /usr/bin/X11/Xvfb :1 -ac -screen 0 1280x1024x8 -fbdir /tmp
-
-
-Windmill usage
-==============
-
-Record your use case
---------------------
-
-- start your instance manually
-- start Windmill_ with url site as last argument (read Usage_ or use *'-h'*
-  option to find required command line arguments)
-- use the record button
-- click on save to obtain python code of your use case
-- copy the content to a new file in a *windmill* directory
-
-.. _Usage: http://wiki.github.com/windmill/windmill/running-tests
-
-If you are using firefox as client, consider the "firebug" option.
-
-If you have a running instance, you can refine the test by the *loadtest* windmill option::
-
-    $ windmill -m firebug loadtest=<test_file.py> <instance url>
-
-Or use the internal windmill shell to explore available commands::
-
-    $ windmill -m firebug shell <instance url>
-
-And enter python commands:
-
-.. sourcecode:: python
-
-    >>> load_test(<your test file>)
-    >>> run_test(<your test file>)
-
-
-
-Integrate Windmill tests into CubicWeb
-======================================
-
-Set environment
----------------
-
-You have to create a new unit test file and a `windmill` directory and copy all
-your windmill use case into it.
-
-.. sourcecode:: python
-
-    # test_windmill.py
-
-    # Run all scenarii found in windmill directory
-    from cubicweb.devtools.cwwindmill import (CubicWebWindmillUseCase,
-                                              unittest_main)
-
-    if __name__ == '__main__':
-        unittest_main()
-
-Run your tests
---------------
-
-You can easily run your windmill test suite through `pytest` or :mod:`unittest`.
-You have to copy a *test_windmill.py* file from :mod:`web.test`.
-
-To run your test series::
-
-    $ pytest test/test_windmill.py
-
-By default, CubicWeb will use **firefox** as the default browser and will try
-to run test instance server on localhost. In the general case, You've no need
-to change anything.
-
-Check :class:`cubicweb.devtools.cwwindmill.CubicWebWindmillUseCase` for
-Windmill configuration. You can edit windmill settings with following class attributes:
-
-* browser
-  identification string (firefox|ie|safari|chrome) (firefox by default)
-* test_dir
-  testing file path or directory (windmill directory under your unit case
-  file by default)
-* edit_test
-  load and edit test for debugging (False by default)
-
-Examples:
-
-.. sourcecode:: python
-
-    browser = 'firefox'
-    test_dir = osp.join(__file__, 'windmill')
-    edit_test = False
-
-If you want to change cubicweb test server parameters, you can check class
-variables from :class:`CubicWebServerConfig` or inherit it with overriding the
-:attr:`configcls` attribute in :class:`CubicWebServerTC` ::
-
-.. sourcecode:: python
-
-    class OtherCubicWebServerConfig(CubicWebServerConfig):
-        port = 9999
-
-    class NewCubicWebServerTC(CubicWebServerTC):
-        configcls = OtherCubicWebServerConfig
-
-For instance, CubicWeb framework windmill tests can be manually run by::
-
-    $ pytest web/test/test_windmill.py
-
-Edit your tests
----------------
-
-You can toggle the `edit_test` variable to enable test edition.
-
-But if you are using `pytest` as test runner, use the `-i` option directly.
-The test series will be loaded and you can run assertions step-by-step::
-
-    $ pytest -i test/test_windmill.py
-
-In this case, the `firebug` extension will be loaded automatically for you.
-
-Afterwards, don't forget to save your edited test into the right file (no autosave feature).
-
-Best practises
---------------
-
-Don't run another instance on the same port. You risk to silence some
-regressions (test runner will automatically fail in further versions).
-
-Start your use case by using an assert on the expected primary url page.
-Otherwise all your tests could fail without clear explanation of the used
-navigation.
-
-In the same location of the *test_windmill.py*, create a *windmill/* with your
-windmill recorded use cases.
-
-
-Caveats
-=======
-
-File Upload
------------
-
-Windmill can't do file uploads. This is a limitation of browser Javascript
-support / sandboxing, not of Windmill per se.  It would be nice if there were
-some command that would prime the Windmill HTTP proxy to add a particular file
-to the next HTTP request that comes through, so that uploads could at least be
-faked.
-
-.. http://groups.google.com/group/windmill-dev/browse_thread/thread/cf9dc969722bd6bb/01aa18fdd652f7ff?lnk=gst&q=input+type+file#01aa18fdd652f7ff
-
-.. http://davisagli.com/blog/in-browser-integration-testing-with-windmill
-
-.. http://groups.google.com/group/windmill-dev/browse_thread/thread/b7bebcc38ed30dc7
-
-
-Preferences
-===========
-
-A *.windmill/prefs.py* could be used to redefine default configuration values.
-
-.. define CubicWeb preferences in the parent test case instead with a dedicated firefox profile
-
-For managing browser extensions, read `advanced topic chapter
-<http://wiki.github.com/windmill/windmill/advanced-topics>`_.
-
-More configuration examples could be seen in *windmill/conf/global_settings.py*
-as template.
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,2 @@
+.. -*- coding: utf-8 -*-
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/intro/concepts.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,306 @@
+.. -*- coding: utf-8 -*-
+
+.. _Concepts:
+
+The Core Concepts of |cubicweb|
+===============================
+
+This section defines some terms and core concepts of the |cubicweb| framework. To
+avoid confusion while reading this book, take time to go through the following
+definitions and use this section as a reference during your reading.
+
+
+.. _Cube:
+
+Cubes
+-----
+
+A cube is a software component made of three parts: its data model
+(: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
+`cubicweb-comment`_ could be used to make a cube named *myblog* with commentable
+blog entries.
+
+The `CubicWeb.org Forge`_ offers a large number of cubes developed by the community
+and available under a free software license.
+
+.. note::
+
+ The command :command:`cubicweb-ctl list` displays the list of available cubes.
+
+.. _`CubicWeb.org Forge`: http://www.cubicweb.org/project/
+.. _`cubicweb-blog`: http://www.cubicweb.org/project/cubicweb-blog
+.. _`cubicweb-comment`: http://www.cubicweb.org/project/cubicweb-comment
+
+
+.. _Instance:
+
+Instances
+---------
+
+An instance is a runnable application installed on a computer and based on a
+cube.
+
+The instance directory contains the configuration files. Several instances can be
+created and based on the same cube. For exemple, several software forges can be
+set up on one computer system based on the `cubicweb-forge`_ cube.
+
+.. _`cubicweb-forge`: http://www.cubicweb.org/project/cubicweb-forge
+
+Instances can be of three different types: all-in-one, web engine or data
+repository. For applications that support high traffic, several web (front-end)
+and data (back-end) instances can be set-up to share the load.
+
+.. image:: ../images/archi_globale_en.png
+
+The command :command:`cubicweb-ctl list` also displays the list of instances
+installed on your system.
+
+.. 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,
+  depending on the context. This book will try to use *application*, *cube* and
+  *instance* as appropriate.
+
+
+.. _RepositoryIntro:
+
+Data Repository
+---------------
+
+The data repository [1]_ encapsulates and groups an access to one or
+more data sources (including SQL databases, LDAP repositories, other
+|cubicweb| instance repositories, filesystems, Google AppEngine's
+DataStore, etc).
+
+All interactions with the repository are done using the `Relation Query Language`
+(:ref:`RQL`). The repository federates the data sources and hides them from the
+querier, which does not realize when a query spans several data sources
+and requires running sub-queries and merges to complete.
+
+Application logic can be mapped to data events happenning within 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://pythonhosted.org/Pyro4/
+
+.. _WebEngineIntro:
+
+Web Engine
+----------
+
+The web engine replies to http requests and runs the user interface.
+
+By default the web engine provides a `CRUD`_ user interface based on
+the data model of the instance. Entities can be created, displayed,
+updated and deleted. As the default user interface is not very fancy,
+it is usually necessary to develop your own.
+
+It is common to run the web engine and the repository in the same
+process (see instances of type all-in-one above), but this is not a
+requirement. A repository can be set up to be accessed remotely using
+Pyro (`Python Remote Objects`_) and act as a standalone server, which
+can be directly accessed or also through a standalone web engine.
+
+.. _`CRUD`: http://en.wikipedia.org/wiki/Create,_read,_update_and_delete
+
+.. _SchemaIntro:
+
+Schema (Data Model)
+-------------------
+
+The data model of a cube is described as an entity-relationship schema using a
+comprehensive language made of Python classes imported from the yams_ library.
+
+.. _yams: http://www.logilab.org/project/yams/
+
+An `entity type` defines a sequence of attributes. Attributes may be
+of the following types: `String`, `Int`, `Float`, `Boolean`, `Date`,
+`Time`, `Datetime`, `Interval`, `Password`, `Bytes`, `RichString`.
+
+A `relation type` is used to define an oriented binary relation
+between entity types.  The left-hand part of a relation is named the
+`subject` and the right-hand part is named the `object`.
+
+A `relation definition` is a triple (*subject entity type*, *relation type*, *object
+entity type*) associated with a set of properties such as cardinality,
+constraints, etc.
+
+Permissions can be set on entity types or relation definition to control who
+will be able to create, read, update or delete entities and relations. Permissions
+are granted to groups (to which users may belong) or using rql expressions (if the
+rql expression returns some results, the permission is granted).
+
+Some meta-data necessary to the system are added to the data model. That includes
+entities like users and groups, the entities used to store the data model
+itself and attributes like unique identifier, creation date, creator, etc.
+
+When you create a new |cubicweb| instance, the schema is stored in the database.
+When the cubes the instance is based on evolve, they may change their data model
+and provide migration scripts that will be executed when the administrator will
+run the upgrade process for the instance.
+
+
+.. _VRegistryIntro:
+
+Registries and application objects
+----------------------------------
+
+Application objects
+~~~~~~~~~~~~~~~~~~~
+
+Besides a few core functionalities, almost every feature of the framework is
+achieved by dynamic objects (`application objects` or `appobjects`) stored in a
+two-levels registry. Each object is affected to a registry with
+an identifier in this registry. You may have more than one object sharing an
+identifier in the same registry:
+
+  object's `__registry__` : object's `__regid__` : [list of app objects]
+
+In other words, the `registry` contains several (sub-)registries which hold a
+list of appobjects associated to an identifier.
+
+The base class of appobjects is :class:`cubicweb.appobject.AppObject`.
+
+Selectors
+~~~~~~~~~
+
+At runtime, appobjects can be selected in a registry according to some
+contextual information. Selection is done by comparing the *score*
+returned by each appobject's *selector*.
+
+The better the object fits the context, the higher the score. Scores
+are the glue that ties appobjects to the data model. Using them
+appropriately is an essential part of the construction of well behaved
+cubes.
+
+|cubicweb| provides a set of basic selectors that may be parametrized.  Also,
+selectors can be combined with the `~` unary operator (negation) and the binary
+operators `&` and `|` (respectivly 'and' and 'or') to build more complex
+selectors. Of course complex selectors may be combined too. Last but not least, you
+can write your own selectors.
+
+The `registry`
+~~~~~~~~~~~~~~~
+
+At startup, the `registry` inspects a number of directories looking
+for compatible class definitions. After a recording process, the
+objects are assigned to registries and become available through the
+selection process.
+
+In a cube, application object classes are looked in the following modules or
+packages:
+
+- `entities`
+- `views`
+- `hooks`
+- `sobjects`
+
+There are three common ways to look up some application object from a
+registry:
+
+* get the most appropriate object by specifying an identifier and
+  context objects. The object with the greatest score is
+  selected. There should always be a single appobject with a greater
+  score than others for a particular context.
+
+* get all objects applying to a context by specifying a registry. A
+  list of objects will be returned containing the object with the
+  highest score (> 0) for each identifier in that registry.
+
+* get the object within a particular registry/identifier. No selection
+  process is involved: the registry will expect to find a single
+  object in that cell.
+
+
+.. _RQLIntro:
+
+The RQL query 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 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.
+
+
+Result set
+~~~~~~~~~~
+
+Every request made (using RQL) to the data repository returns an object we call a
+Result Set. It enables easy use of the retrieved data, providing a translation
+layer between the backend's native datatypes and |cubicweb| schema's EntityTypes.
+
+Result sets provide access to the raw data, yielding either basic Python data
+types, or schema-defined high-level entities, in a straightforward way.
+
+
+.. _ViewIntro:
+
+Views
+-----
+
+**CubicWeb is data driven**
+
+The view system is loosely coupled to data through the selection system explained
+above. Views are application objects with a dedicated interface to 'render'
+something, eg producing some html, text, xml, pdf, or whatsover that can be
+displayed to a user.
+
+Views actually are partitioned into different kind of objects such as
+`templates`, `boxes`, `components` and proper `views`, which are more
+high-level abstraction useful to build the user interface in an object
+oriented way.
+
+
+.. _HookIntro:
+
+Hooks and operations
+--------------------
+
+**CubicWeb provides an extensible data repository**
+
+The data model defined using Yams types allows to express the data
+model in a comfortable way. However several aspects of the data model
+can not be expressed there. For instance:
+
+* managing computed attributes
+
+* enforcing complicated business rules
+
+* real-world side-effects linked to data events (email notification
+  being a prime example)
+
+The hook system is much like the triggers of an SQL database engine,
+except that:
+
+* it is not limited to one specific SQL backend (every one of them
+  having an idiomatic way to encode triggers), nor to SQL backends at
+  all (think about LDAP or a Subversion repository)
+
+* it is well-coupled to the rest of the framework
+
+Hooks are also application objects (in the `hooks` registry) and
+selected on events such as after/before add/update/delete on
+entities/relations, server startup or shutdown, etc.
+
+`Operations` may be instantiated by hooks to do further processing at different
+steps of the transaction's commit / rollback, which usually can not be done
+safely at the hook execution time.
+
+Hooks and operation are an essential building block of any moderately complicated
+cubicweb application.
+
+.. note::
+   RQL queries executed in hooks and operations are *unsafe* by default, i.e. the
+   read and write security is deactivated unless explicitly asked.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/intro/history.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,32 @@
+.. -*- coding: utf-8 -*-
+
+A little history...
+===================
+
+*CubicWeb* is a semantic web application framework that Logilab_ started
+developing in 2001 as an offspring of its Narval_ research project. *CubicWeb*
+is written in Python and includes a data server and a web engine.
+
+Its data server publishes data federated from different sources like
+SQL databases, LDAP directories, `VCS`_ repositories or even from other
+CubicWeb data servers.
+
+.. _`VCS`: http://en.wikipedia.org/wiki/Revision_control
+
+Its web engine was designed to let the final user control what content to select
+and how to display it. It allows one to browse the federated data sources and
+display the results with the rendering that best fits the context. This
+flexibility of the user interface gives back to the user some capabilities
+usually only accessible to application developers.
+
+*CubicWeb* has been developed by Logilab_ and used in-house for many years
+before it was first installed for its clients in 2006 as version 2.
+
+In 2008, *CubicWeb* version 3 became downloadable for free under the
+terms of the LGPL license. Its community is now steadily growing
+without hampering the fast-paced stream of changes thanks to the time
+and energy originally put in the design of the framework.
+
+
+.. _Narval: http://www.logilab.org/project/narval-moved
+.. _Logilab: http://www.logilab.fr/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/intro/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,19 @@
+.. -*- coding: utf-8 -*-
+
+.. _Part1:
+
+--------------------------
+Introduction to *CubicWeb*
+--------------------------
+
+This first part of the book offers different reading path to
+discover the *CubicWeb* framework, provides a tutorial to get a quick
+overview of its features and lists its key concepts.
+
+
+.. toctree::
+   :maxdepth: 2
+   :numbered:
+
+   history
+   concepts.rst
--- a/doc/book/mode_plan.py	Mon Jul 06 17:39:35 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of CubicWeb.
-#
-# CubicWeb is free software: you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
-"""
->>> from mode_plan import *
->>> ls()
-<list of directory content>
->>> ren('A01','A03')
-rename A010-joe.en.txt to A030-joe.en.txt
-accept [y/N]?
-"""
-
-def ren(a,b):
-    names = glob.glob('%s*'%a)
-    for name in names :
-        print 'rename %s to %s' % (name, name.replace(a,b))
-    if raw_input('accept [y/N]?').lower() =='y':
-        for name in names:
-            os.system('hg mv %s %s' % (name, name.replace(a,b)))
-
-
-def ls(): print '\n'.join(sorted(os.listdir('.')))
-
-def move():
-    filenames = []
-    for name in sorted(os.listdir('.')):
-        num = name[:2]
-        if num.isdigit():
-            filenames.append( (int(num), name) )
-
-
-    #print filenames
-
-    for num, name in filenames:
-        if num >= start:
-            print 'hg mv %s %2i%s' %(name,num+1,name[2:])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/3.14.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,164 @@
+Whats new in CubicWeb 3.14
+==========================
+
+First notice CW 3.14 depends on yams 0.34 (which is incompatible with prior
+cubicweb releases regarding instance re-creation).
+
+API changes
+-----------
+
+* `Entity.fetch_rql` `restriction` argument has been deprecated and should be
+  replaced with a call to the new `Entity.fetch_rqlst` method, get the returned
+  value (a rql `Select` node) and use the RQL syntax tree API to include the
+  above-mentionned restrictions.
+
+  Backward compat is kept with proper warning.
+
+* `Entity.fetch_order` and `Entity.fetch_unrelated_order` class methods have been
+  replaced by `Entity.cw_fetch_order` and `Entity.cw_fetch_unrelated_order` with
+  a different prototype:
+
+  - instead of taking (attr, var) as two string argument, they now take (select,
+    attr, var) where select is the rql syntax tree beinx constructed and var the
+    variable *node*.
+
+  - instead of returning some string to be inserted in the ORDERBY clause, it has
+    to modify the syntax tree
+
+  Backward compat is kept with proper warning, BESIDE cases below:
+
+  - custom order method return **something else the a variable name with or
+    without the sorting order** (e.g. cases where you sort on the value of a
+    registered procedure as it was done in the tracker for instance). In such
+    case, an error is logged telling that this sorting is ignored until API
+    upgrade.
+
+  - client code use direct access to one of those methods on an entity (no code
+    known to do that).
+
+* `Entity._rest_attr_info` class method has been renamed to
+  `Entity.cw_rest_attr_info`
+
+  No backward compat yet since this is a protected method an no code is known to
+  use it outside cubicweb itself.
+
+* `AnyEntity.linked_to` has been removed as part of a refactoring of this
+  functionality (link a entity to another one at creation step). It was replaced
+  by a `EntityFieldsForm.linked_to` property.
+
+  In the same refactoring, `cubicweb.web.formfield.relvoc_linkedto`,
+  `cubicweb.web.formfield.relvoc_init` and
+  `cubicweb.web.formfield.relvoc_unrelated` were removed and replaced by
+  RelationField methods with the same names, that take a form as a parameter.
+
+  **No backward compatibility yet**. It's still time to cry for it.
+  Cubes known to be affected: tracker, vcsfile, vcreview.
+
+* `CWPermission` entity type and its associated require_permission relation type
+  (abstract) and require_group relation definitions have been moved to a new
+  `localperms` cube. With this have gone some functions from the
+  `cubicweb.schemas` package as well as some views. This makes cubicweb itself
+  smaller while you get all the local permissions stuff into a single,
+  documented, place.
+
+  Backward compat is kept for existing instances, **though you should have
+  installed the localperms cubes**. A proper error should be displayed when
+  trying to migrate to 3.14 an instance the use `CWPermission` without the new
+  cube installed. For new instances / test, you should add a dependancy on the
+  new cube in cubes using this feature, along with a dependancy on cubicweb >=
+  3.14.
+
+* jQuery has been updated to 1.6.4 and jquery-tablesorter to 2.0.5. No backward
+  compat issue known.
+
+* Table views refactoring : new `RsetTableView` and `EntityTableView`, as well as
+  rewritten an enhanced version of `PyValTableView` on the same bases, with logic
+  moved to some column renderers and a layout. Those should be well documented
+  and deprecates former `TableView`, `EntityAttributesTableView` and `CellView`,
+  which are however kept for backward compat, with some warnings that may not be
+  very clear unfortunatly (you may see your own table view subclass name here,
+  which doesn't make the problem that clear). Notice that `_cw.view('table',
+  rset, *kwargs)` will be routed to the new `RsetTableView` or to the old
+  `TableView` depending on given extra arguments. See #1986413.
+
+* `display_name` don't call .lower() anymore. This may leads to changes in your
+  user interface. Different msgid for upper/lower cases version of entity type
+  names, as this is the only proper way to handle this with some languages.
+
+* `IEditControlAdapter` has been deprecated in favor of `EditController`
+  overloading, which was made easier by adding dedicated selectors called
+  `match_edited_type` and `match_form_id`.
+
+* Pre 3.6 API backward compat has been dropped, though *data* migration
+  compatibility has been kept. You may have to fix errors due to old API usage
+  for your instance before to be able to run migration, but then you should be
+  able to upgrade even a pre 3.6 database.
+
+* Deprecated `cubicweb.web.views.iprogress` in favor of new `iprogress` cube.
+
+* Deprecated `cubicweb.web.views.flot` in favor of new `jqplot` cube.
+
+
+Unintrusive API changes
+-----------------------
+
+* Refactored properties forms (eg user preferences and site wide properties) as
+  well as pagination components to ease overridding.
+
+* New `cubicweb.web.uihelper` module with high-level helpers for uicfg.
+
+* New `anonymized_request` decorator to temporary run stuff as an anonymous
+  user, whatever the currently logged in user.
+
+* New 'verbatimattr' attribute view.
+
+* New facet and form widget for Integer used to store binary mask.
+
+* New `js_href` function to generated proper javascript href.
+
+* `match_kwargs` and `match_form_params` selectors both accept a new
+  `once_is_enough` argument.
+
+* `printable_value` is now a method of request, and may be given dict of
+   formatters to use.
+
+* `[Rset]TableView` allows to set None in 'headers', meaning the label should be
+  fetched from the result set as done by default.
+
+* Field vocabulary computation on entity creation now takes `__linkto`
+  information into accounet.
+
+* Started a `cubicweb.pylintext` pylint plugin to help pylint analyzing cubes.
+
+
+RQL
+---
+
+* Support for HAVING in 'SET' and 'DELETE' queries.
+
+* new `AT_TZ` function to get back a timestamp at a given time-zone.
+
+* new `WEEKDAY` date extraction function
+
+
+User interface changes
+----------------------
+
+* Datafeed source now present an history of the latest import's log, including
+  global status and debug/info/warning/error messages issued during
+  imports. Import logs older than a configurable amount of time are automatically
+  deleted.
+
+* Breadcrumbs component is properly kept when creating an entity with '__linkto'.
+
+* users and groups management now really lead to that (i.e. includes *groups*
+  management).
+
+* New 'jsonp' controller with 'jsonexport' and 'ejsonexport' views.
+
+
+Configuration
+------------
+
+* Added option 'resources-concat' to make javascript/css files concatenation
+  optional.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/3.15.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,96 @@
+What's new in CubicWeb 3.15?
+============================
+
+New functionnalities
+--------------------
+
+* Add Zmq server, based on the cutting edge ZMQ (http://www.zeromq.org/) socket
+  library.  This allows to access distant instance, in a similar way as Pyro.
+
+* Publish/subscribe mechanism using ZMQ for communication among cubicweb
+  instances.  The new zmq-address-sub and zmq-address-pub configuration variables
+  define where this communication occurs.  As of this release this mechanism is
+  used for entity cache invalidation.
+
+* Improved WSGI support. While there is still some caveats, most of the code
+  which was twisted only is now generic and allows related functionalities to work
+  with a WSGI front-end.
+
+* Full undo/transaction support : undo of modification has eventually been
+  implemented, and the configuration simplified (basically you activate it or not
+  on an instance basis).
+
+* Controlling HTTP status code used is not much more easier :
+
+  - `WebRequest` now has a `status_out` attribut to control the response status ;
+
+  - most web-side exceptions take an optional ``status`` argument.
+
+API changes
+-----------
+
+* The base registry implementation has been moved to a new
+  `logilab.common.registry` module (see #1916014). This includes code from :
+
+  * `cubicweb.vreg` (the whole things that was in there)
+  * `cw.appobject` (base selectors and all).
+
+  In the process, some renaming was done:
+
+  * the top level registry is now `RegistryStore` (was `VRegistry`), but that
+    should not impact cubicweb client code ;
+
+  * former selectors functions are now known as "predicate", though you still use
+    predicates to build an object'selector ;
+
+  * for consistency, the `objectify_selector` decoraror has hence be renamed to
+    `objectify_predicate` ;
+
+  * on the CubicWeb side, the `selectors` module has been renamed to
+    `predicates`.
+
+  Debugging refactoring dropped the more need for the `lltrace` decorator.  There
+  should be full backward compat with proper deprecation warnings.  Notice the
+  `yes` predicate and `objectify_predicate` decorator, as well as the
+  `traced_selection` function should now be imported from the
+  `logilab.common.registry` module.
+
+* All login forms are now submitted to <app_root>/login. Redirection to requested
+  page is now handled by the login controller (it was previously handle by the
+  session manager).
+
+* `Publisher.publish` has been renamed to `Publisher.handle_request`. This
+  method now contains generic version of logic previously handled by
+  Twisted. `Controller.publish` is **not** affected.
+
+Unintrusive API changes
+-----------------------
+
+* New 'ldapfeed' source type, designed to replace 'ldapuser' source with
+  data-feed (i.e. copy based) source ideas.
+
+* New 'zmqrql' source type, similar to 'pyrorql' but using ømq instead of Pyro.
+
+* A new registry called `services` has appeared, where you can register
+  server-side `cubicweb.server.Service` child classes. Their `call` method can be
+  invoked from a web-side AppObject instance using new `self._cw.call_service`
+  method or a server-side one using `self.session.call_service`. This is a new
+  way to call server-side methods, much cleaner than monkey patching the
+  Repository class, which becomes a deprecated way to perform similar tasks.
+
+* a new `ajax-func` registry now hosts all remote functions (i.e. functions
+  callable through the `asyncRemoteExec` JS api). A convenience `ajaxfunc`
+  decorator will let you expose your python function easily without all the
+  appobject standard boilerplate. Backward compatibility is preserved.
+
+* the 'json' controller is now deprecated in favor of the 'ajax' one.
+
+* `WebRequest.build_url` can now take a __secure__ argument. When True cubicweb
+  try to generate an https url.
+
+
+User interface changes
+----------------------
+
+A new 'undohistory' view expose the undoable transactions and give access to undo
+some of them.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/3.16.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,97 @@
+What's new in CubicWeb 3.16?
+============================
+
+New functionalities
+--------------------
+
+* Add a new dataimport store (`SQLGenObjectStore`). This store enables a fast
+  import of data (entity creation, link creation) in CubicWeb, by directly
+  flushing information in SQL.  This may only be used with PostgreSQL, as it
+  requires the 'COPY FROM' command.
+
+
+API changes
+-----------
+
+* Orm: `set_attributes` and `set_relations` are unified (and
+  deprecated) in favor of `cw_set` that works in all cases.
+
+* db-api/configuration: all the external repository connection information is
+  now in an URL (see `#2521848 <http://www.cubicweb.org/2521848>`_),
+  allowing to drop specific options of pyro nameserver host, group, etc and fix
+  broken `ZMQ <http://www.zeromq.org/>`_ source. Configuration related changes:
+
+  * Dropped 'pyro-ns-host', 'pyro-instance-id', 'pyro-ns-group' from the client side
+    configuration, in favor of 'repository-uri'. **NO MIGRATION IS DONE**,
+    supposing there is no web-only configuration in the wild.
+
+  * Stop discovering the connection method through `repo_method` class attribute
+    of the configuration, varying according to the configuration class. This is
+    a first step on the way to a simpler configuration handling.
+
+  DB-API related changes:
+
+  * Stop indicating the connection method using `ConnectionProperties`.
+
+  * Drop `_cnxtype` attribute from `Connection` and `cnxtype` from
+    `Session`. The former is replaced by a `is_repo_in_memory` property
+    and the later is totaly useless.
+
+  * Turn `repo_connect` into `_repo_connect` to mark it as a private function.
+
+  * Deprecate `in_memory_cnx` which becomes useless, use `_repo_connect` instead
+    if necessary.
+
+* the "tcp://" uri scheme used for `ZMQ <http://www.zeromq.org/>`_
+  communications (in a way reminiscent of Pyro) is now named
+  "zmqpickle-tcp://", so as to make room for future zmq-based lightweight
+  communications (without python objects pickling).
+
+* Request.base_url gets a `secure=True` optional parameter that yields
+  an https url if possible, allowing hook-generated content to send
+  secure urls (e.g. when sending mail notifications)
+
+* Dataimport ucsvreader gets a new boolean `ignore_errors`
+  parameter.
+
+
+Unintrusive API changes
+-----------------------
+
+* Drop of `cubicweb.web.uicfg.AutoformSectionRelationTags.bw_tag_map`,
+  deprecated since 3.6.
+
+
+User interface changes
+----------------------
+
+* The RQL search bar has now some auto-completion support. It means
+  relation types or entity types can be suggested while typing. It is
+  an awesome improvement over the current behaviour !
+
+* The `action box` associated with `table` views (from `tableview.py`)
+  has been transformed into a nice-looking series of small tabs; it
+  means that the possible actions are immediately visible and need not
+  be discovered by clicking on an almost invisible icon on the upper
+  right.
+
+* The `uicfg` module has moved to web/views/ and ui configuration
+  objects are now selectable. This will reduce the amount of
+  subclassing and whole methods replacement usually needed to
+  customize the ui behaviour in many cases.
+
+* Remove changelog view, as neither cubicweb nor known
+  cubes/applications were properly feeding related files.
+
+
+Other changes
+-------------
+
+* 'pyrorql' sources will be automatically updated to use an URL to locate the source
+  rather than configuration option. 'zmqrql' sources were broken before this change,
+  so no upgrade is needed...
+
+* Debugging filters for Hooks and Operations have been added.
+
+* Some cubicweb-ctl commands used to show the output of `msgcat` and
+  `msgfmt`; they don't anymore.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/3.17.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,60 @@
+What's new in CubicWeb 3.17?
+============================
+
+New functionalities
+--------------------
+
+* add a command to compare db schema and file system schema
+  (see `#464991 <http://www.cubicweb.org/464991>`_)
+
+* Add CubicWebRequestBase.content with the content of the HTTP request (see #2742453)
+  (see `#2742453 <http://www.cubicweb.org/2742453>`_)
+
+* Add directive bookmark to ReST rendering
+  (see `#2545595 <http://www.cubicweb.org/ticket/2545595>`_)
+
+* Allow user defined final type
+  (see `#124342 <https://www.logilab.org/ticket/124342>`_)
+
+
+API changes
+-----------
+
+* drop typed_eid() in favour of int() (see `#2742462 <http://www.cubicweb.org/2742462>`_)
+
+* The SIOC views and adapters have been removed from CubicWeb and moved to the
+  `sioc` cube.
+
+* The web page embedding views and adapters have been removed from CubicWeb and
+  moved to the `embed` cube.
+
+* The email sending views and controllers have been removed from CubicWeb and
+  moved to the `massmailing` cube.
+
+* ``RenderAndSendNotificationView`` is deprecated in favor of
+  ``ActualNotificationOp`` the new operation use the more efficient *data*
+  idiom.
+
+* Looping task can now have a interval <= ``0``. Negative interval disable the
+  looping task entirely.
+
+* We now serve html instead of xhtml.
+  (see `#2065651 <http://www.cubicweb.org/ticket/2065651>`_)
+
+
+Deprecation
+---------------------
+
+* ``ldapuser`` have been deprecated. It'll be fully dropped in the next
+  version. If you are still using ldapuser switch to ``ldapfeed`` **NOW**!
+
+* ``hijack_user`` have been deprecated. It will be dropped soon.
+
+Deprecated Code Drops
+----------------------
+
+* The progress views and adapters have been removed from CubicWeb. These
+  classes were deprecated since 3.14.0. They are still available in the
+  `iprogress` cube.
+
+* API deprecated since 3.7 have been dropped.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/3.18.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,101 @@
+What's new in CubicWeb 3.18?
+============================
+
+The migration script does not handle sqlite nor mysql instances.
+
+
+New functionalities
+--------------------
+
+* add a security debugging tool
+  (see `#2920304 <http://www.cubicweb.org/2920304>`_)
+
+* introduce an `add` permission on attributes, to be interpreted at
+  entity creation time only and allow the implementation of complex
+  `update` rules that don't block entity creation (before that the
+  `update` attribute permission was interpreted at entity creation and
+  update time)
+
+* the primary view display controller (uicfg) now has a
+  `set_fields_order` method similar to the one available for forms
+
+* new method `ResultSet.one(col=0)` to retrive a single entity and enforce the
+  result has only one row (see `#3352314 https://www.cubicweb.org/ticket/3352314`_)
+
+* new method `RequestSessionBase.find` to look for entities
+  (see `#3361290 https://www.cubicweb.org/ticket/3361290`_)
+
+* the embedded jQuery copy has been updated to version 1.10.2, and jQuery UI to
+  version 1.10.3.
+
+* initial support for wsgi for the debug mode, available through the new
+  ``wsgi`` cubicweb-ctl command, which can use either python's builtin
+  wsgi server or the werkzeug module if present.
+
+* a ``rql-table`` directive is now available in ReST fields
+
+* cubicweb-ctl upgrade can now generate the static data resource directory
+  directly, without a manual call to gen-static-datadir.
+
+API changes
+-----------
+
+* not really an API change, but the entity permission checks are now
+  systematically deferred to an operation, instead of a) trying in a
+  hook and b) if it failed, retrying later in an operation
+
+* The default value storage for attributes is no longer String, but
+  Bytes.  This opens the road to storing arbitrary python objects, e.g.
+  numpy arrays, and fixes a bug where default values whose truth value
+  was False were not properly migrated.
+
+* `symmetric` relations are no more handled by an rql rewrite but are
+  now handled with hooks (from the `activeintegrity` category); this
+  may have some consequences for applications that do low-level database
+  manipulations or at times disable (some) hooks.
+
+* `unique together` constraints (multi-columns unicity constraints)
+  get a `name` attribute that maps the CubicWeb contraint entities to
+  corresponding backend index.
+
+* BreadCrumbEntityVComponent's open_breadcrumbs method now includes
+  the first breadcrumbs separator
+
+* entities can be compared for equality and hashed
+
+* the ``on_fire_transition`` predicate accepts a sequence of possible
+  transition names
+
+* the GROUP_CONCAT rql aggregate function no longer repeats duplicate
+  values, on the sqlite and postgresql backends
+
+Deprecation
+---------------------
+
+* ``pyrorql`` sources have been deprecated. Multisource will be fully dropped
+  in the next version. If you are still using pyrorql, switch to ``datafeed``
+  **NOW**!
+
+* the old multi-source system
+
+* `find_one_entity` and `find_entities` in favor of `find`
+  (see `#3361290 https://www.cubicweb.org/ticket/3361290`_)
+
+* the `TmpFileViewMixin` and `TmpPngView` classes (see `#3400448
+  https://www.cubicweb.org/ticket/3400448`_)
+
+Deprecated Code Drops
+----------------------
+
+* ``ldapuser`` have been dropped; use ``ldapfeed`` now
+  (see `#2936496 <http://www.cubicweb.org/2936496>`_)
+
+* action ``GotRhythm`` was removed, make sure you do not
+  import it in your cubes (even to unregister it)
+  (see `#3093362 <http://www.cubicweb.org/3093362>`_)
+
+* all 3.8 backward compat is gone
+
+* all 3.9 backward compat (including the javascript side) is gone
+
+* the ``twisted`` (web-only) instance type has been removed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/3.19.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,180 @@
+What's new in CubicWeb 3.19?
+============================
+
+New functionalities
+--------------------
+
+* implement Cross Origin Resource Sharing (CORS)
+  (see `#2491768 <http://www.cubicweb.org/2491768>`_)
+
+* system_source.create_eid can get a range of IDs, to reduce overhead of batch
+  entity creation
+
+Behaviour Changes
+-----------------
+
+* The anonymous property of Session and Connection are now computed from the
+  related user login. If it matches the ``anonymous-user`` in the config the
+  connection is anonymous. Beware that the ``anonymous-user`` config is web
+  specific. Therefore, no session may be anonymous in a repository only setup.
+
+
+New Repository Access API
+-------------------------
+
+Connection replaces Session
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A new explicit Connection object replaces Session as the main repository entry
+point. Connection holds all the necessary methods to be used server-side
+(``execute``, ``commit``, ``rollback``, ``call_service``, ``entity_from_eid``,
+etc...). One obtains a new Connection object using ``session.new_cnx()``.
+Connection objects need to have an explicit begin and end. Use them as a context
+manager to never miss an end::
+
+    with session.new_cnx() as cnx:
+        cnx.execute('INSERT Elephant E, E name "Babar"')
+        cnx.commit()
+        cnx.execute('INSERT Elephant E, E name "Celeste"')
+        cnx.commit()
+    # Once you get out of the "with" clause, the connection is closed.
+
+Using the same Connection object in multiple threads will give you access to the
+same Transaction. However, Connection objects are not thread safe (hence at your
+own risks).
+
+``repository.internal_session`` is deprecated in favor of
+``repository.internal_cnx``. Note that internal connections are now `safe` by default,
+i.e. the integrity hooks are enabled.
+
+Backward compatibility is preserved on Session.
+
+
+dbapi vs repoapi
+~~~~~~~~~~~~~~~~
+
+A new API has been introduced to replace the dbapi. It is called `repoapi`.
+
+There are three relevant functions for now:
+
+* ``repoapi.get_repository`` returns a Repository object either from an
+  URI when used as ``repoapi.get_repository(uri)`` or from a config
+  when used as ``repoapi.get_repository(config=config)``.
+
+* ``repoapi.connect(repo, login, **credentials)`` returns a ClientConnection
+  associated with the user identified by the credentials. The
+  ClientConnection is associated with its own Session that is closed
+  when the ClientConnection is closed. A ClientConnection is a
+  Connection-like object to be used client side.
+
+* ``repoapi.anonymous_cnx(repo)`` returns a ClientConnection associated
+  with the anonymous user if described in the config.
+
+
+repoapi.ClientConnection replace dbapi.Connection and company
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On the client/web side, the Request is now using a ``repoapi.ClientConnection``
+instead of a ``dbapi.connection``. The ``ClientConnection`` has multiple backward
+compatible methods to make it look like a ``dbapi.Cursor`` and ``dbapi.Connection``.
+
+Session used on the Web side are now the same than the one used Server side.
+Some backward compatibility methods have been installed on the server side Session
+to ease the transition.
+
+The authentication stack has been altered to use the ``repoapi`` instead of
+the ``dbapi``. Cubes adding new element to this stack are likely to break.
+
+Session data can be accessed using the cnx.data dictionary, while
+transaction data is available through cnx.transaction_data.  These
+replace the [gs]et_shared_data methods with optional txid kwarg.
+
+New API in tests
+~~~~~~~~~~~~~~~~
+
+All current methods and attributes used to access the repo on ``CubicWebTC`` are
+deprecated. You may now use a ``RepoAccess`` object. A ``RepoAccess`` object is
+linked to a new ``Session`` for a specified user. It is able to create
+``Connection``, ``ClientConnection`` and web side requests linked to this
+session::
+
+    access = self.new_access('babar') # create a new RepoAccess for user babar
+    with access.repo_cnx() as cnx:
+        # some work with server side cnx
+        cnx.execute(...)
+        cnx.commit()
+        cnx.execute(...)
+        cnx.commit()
+
+    with access.client_cnx() as cnx:
+        # some work with client side cnx
+        cnx.execute(...)
+        cnx.commit()
+
+    with access.web_request(elephant='babar') as req:
+        # some work with client side cnx
+        elephant_name = req.form['elephant']
+        req.execute(...)
+        req.cnx.commit()
+
+By default ``testcase.admin_access`` contains a ``RepoAccess`` object for the
+default admin session.
+
+
+API changes
+-----------
+
+* ``RepositorySessionManager.postlogin`` is now called with two arguments,
+  request and session. And this now happens before the session is linked to the
+  request.
+
+* ``SessionManager`` and ``AuthenticationManager`` now take a repo object at
+  initialization time instead of a vreg.
+
+* The ``async`` argument of ``_cw.call_service`` has been dropped. All calls are
+  now  synchronous. The zmq notification bus looks like a good replacement for
+  most async use cases.
+
+* ``repo.stats()`` is now deprecated. The same information is available through
+  a service (``_cw.call_service('repo_stats')``).
+
+* ``repo.gc_stats()`` is now deprecated. The same information is available through
+  a service (``_cw.call_service('repo_gc_stats')``).
+
+* ``repo.register_user()`` is now deprecated.  The functionality is now
+  available through a service (``_cw.call_service('register_user')``).
+
+* ``request.set_session`` no longer takes an optional ``user`` argument.
+
+* CubicwebTC does not have repo and cnx as class attributes anymore. They are
+  standard instance attributes. ``set_cnx`` and ``_init_repo`` class methods
+  become instance methods.
+
+* ``set_cnxset`` and ``free_cnxset`` are deprecated. cnxset are now
+  automatically managed.
+
+* The implementation of cascading deletion when deleting `composite`
+  entities has changed. There comes a semantic change: merely deleting
+  a composite relation does not entail any more the deletion of the
+  component side of the relation.
+
+* ``_cw.user_callback`` and ``_cw.user_rql_callback`` are deprecated.  Users
+  are encouraged to write an actual controller (e.g. using ``ajaxfunc``)
+  instead of storing a closure in the session data.
+
+* A new ``entity.cw_linkable_rql`` method provides the rql to fetch all entities
+  that are already or may be related to the current entity using the given
+  relation.
+
+
+Deprecated Code Drops
+----------------------
+
+* session.hijack_user mechanism has been dropped.
+
+* EtypeRestrictionComponent has been removed, its functionality has been
+  replaced by facets a while ago.
+
+* the old multi-source support has been removed.  Only copy-based sources
+  remain, such as datafeed or ldapfeed.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/3.20.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,78 @@
+What's new in CubicWeb 3.20
+===========================
+
+New features
+------------
+
+* virtual relations: a new ComputedRelation class can be used in
+  schema.py; its `rule` attribute is an RQL snippet that defines the new
+  relation.
+
+* computed attributes: an attribute can now be defined with a `formula`
+  argument (also an RQL snippet); it will be read-only, and updated
+  automatically.
+
+  Both of these features are described in `CWEP-002`_, and the updated
+  "Data model" chapter of the CubicWeb book.
+
+* cubicweb-ctl plugins can use the ``cubicweb.utils.admincnx`` function
+  to get a Connection object from an instance name.
+
+* new 'tornado' wsgi backend
+
+* session cookies have the HttpOnly flag, so they're no longer exposed to
+  javascript
+
+* rich text fields can be formatted as markdown
+
+* the edit controller detects concurrent editions, and raises a ValidationError
+  if an entity was modified between form generation and submission
+
+* cubicweb can use a postgresql "schema" (namespace) for its tables
+
+* "cubicweb-ctl configure" can be used to set values of the admin user
+  credentials in the sources configuration file
+
+* in debug mode, setting the _cwtracehtml parameter on a request allows tracing
+  where each bit of output is produced
+
+.. _CWEP-002: http://hg.logilab.org/review/cwep/file/tip/CWEP-002.rst
+
+
+API Changes
+-----------
+
+* ``ucsvreader()`` and ``ucsvreader_pb()`` from the ``dataimport`` module have
+  2 new keyword arguments ``delimiter`` and ``quotechar`` to replace the
+  ``separator`` and ``quote`` arguments respectively. This makes the API match
+  that of Python's ``csv.reader()``.  The old arguments are still supported
+  though deprecated.
+
+* the migration environment's ``remove_cube`` function is now called ``drop_cube``.
+
+* cubicweb.old.css is now cubicweb.css.  The previous "new"
+  cubicweb.css, along with its cubicweb.reset.css companion, have been
+  removed.
+
+* the jquery-treeview plugin was updated to its latest version
+
+
+Deprecated Code Drops
+----------------------
+
+* most of 3.10 and 3.11 backward compat is gone; this includes:
+  - CtxComponent.box_action() and CtxComponent.build_link()
+  - cubicweb.devtools.htmlparser.XMLDemotingValidator
+  - various methods and properties on Entities, replaced by cw_edited and cw_attr_cache
+  - 'commit_event' method on hooks, replaced by 'postcommit_event'
+  - server.hook.set_operation(), replaced by Operation.get_instance(...).add_data()
+  - View.div_id(), View.div_class() and View.create_url()
+  - `*VComponent` classes
+  - in forms, Field.value() and Field.help() must take the form and the field itself as arguments
+  - form.render() must get `w` as a named argument, and renderer.render() must take `w` as first argument
+  - in breadcrumbs, the optional `recurs` argument must be a set, not False
+  - cubicweb.web.views.idownloadable.{download_box,IDownloadableLineView}
+  - primary views no longer have `render_entity_summary` and `summary` methods
+  - WFHistoryVComponent's `cell_call` method is replaced by `render_body`
+  - cubicweb.dataimport.ObjectStore.add(), replaced by create_entity
+  - ManageView.{folders,display_folders}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/changes/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,13 @@
+Changes
+-------
+
+.. toctree::
+    :maxdepth: 1
+
+    3.14
+    3.15
+    3.16
+    3.17
+    3.18
+    3.19
+    3.20
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/conf.py	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,223 @@
+# -*- coding: utf-8 -*-
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+"""
+#
+# Cubicweb documentation build configuration file, created by
+# sphinx-quickstart on Fri Oct 31 09:10:36 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+from os import path as osp
+
+path = __file__
+path = osp.dirname(path)  # ./doc
+path = osp.dirname(path)  # ./
+path = osp.join(path, '__pkginfo__.py')  # ./__pkginfo__.py
+cw = {}
+execfile(path, {}, cw)
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+#sys.path.append(os.path.abspath('some/directory'))
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = [
+  'sphinx.ext.autodoc', 
+  'sphinx.ext.viewcode',
+  'logilab.common.sphinx_ext',
+  ]
+
+autoclass_content = 'both'
+
+# Add any paths that contain templates here, relative to this directory.
+#templates_path = []
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'CubicWeb'
+copyright = '2001-2014, Logilab'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '.'.join(str(n) for n in cw['numversion'][:2])
+# The full version, including alpha/beta/rc tags.
+release = cw['version']
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+unused_docs = []
+
+# List of directories, relative to source directories, that shouldn't be searched
+# for source files.
+#exclude_dirs = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+#html_style = 'sphinx-default.css'
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = '%s %s' % (project, release)
+
+html_theme_path = ['_themes']
+html_theme = 'cubicweb'
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (within the static path) to place at the top of
+# the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+html_file_suffix = '.html'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Cubicwebdoc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+  ('index', 'Cubicweb.tex', 'Cubicweb Documentation',
+   'Logilab', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
+
+#aafig_format = dict(latex='pdf', html='svg', text=None)
+
+rst_epilog = """
+.. |cubicweb| replace:: *CubicWeb*
+.. |yams| replace:: *Yams*
+.. |rql| replace:: *RQL*
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/dev/documenting.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,85 @@
+====
+Book
+====
+
+----
+Part
+----
+
+Chapter
+=======
+
+.. _Level1AnchorForLaterReference:
+
+Level 1 section
+---------------
+
+Level 2 section
+~~~~~~~~~~~~~~~
+
+Level 3 section
+```````````````
+
+
+
+*CubicWeb*
+
+
+inline directives:
+  :file:`directory/file`
+  :envvar:`AN_ENV_VARIABLE`
+  :command:`command --option arguments`
+
+  :ref:, :mod:
+
+
+.. sourcecode:: python
+
+   class SomePythonCode:
+     ...
+
+.. XXX a comment, wont be rendered
+
+
+a [foot note]_
+
+.. [foot note] the foot note content
+
+
+Boxes
+=====
+
+- warning box: 
+    .. warning::
+
+       Warning content
+- note box:
+    .. note::
+
+       Note content
+
+
+
+Cross references
+================
+
+To arbitrary section
+--------------------
+
+:ref:`identifier` ou :ref:`label <identifier>`
+
+Label required of referencing node which as no title, else the node's title will be used.
+
+
+To API objects
+--------------
+See the autodoc sphinx extension documentation. Quick overview:
+
+* ref to a class: :class:`cubicweb.devtools.testlib.AutomaticWebTest`
+
+* if you can to see only the class name in the generated documentation, add a ~:
+  :class:`~cubicweb.devtools.testlib.AutomaticWebTest`
+
+* you can also use :mod: (module), :exc: (exception), :func: (function), :meth: (method)...
+
+* syntax explained above to specify label explicitly may also be used
Binary file doc/images/03-transitions-view_en.png has changed
Binary file doc/images/archi_globale.png has changed
Binary file doc/images/archi_globale_en.png has changed
Binary file doc/images/breadcrumbs_header.png has changed
Binary file doc/images/facet_date_range.png has changed
Binary file doc/images/facet_has_image.png has changed
Binary file doc/images/facet_overview.png has changed
Binary file doc/images/facet_range.png has changed
Binary file doc/images/lax-book_00-login_en.png has changed
Binary file doc/images/lax-book_01-start_en.png has changed
Binary file doc/images/lax-book_02-cookie-values_en.png has changed
Binary file doc/images/lax-book_02-create-blog_en.png has changed
Binary file doc/images/lax-book_03-list-one-blog_en.png has changed
Binary file doc/images/lax-book_03-site-config-panel_en.png has changed
Binary file doc/images/lax-book_03-state-submitted_en.png has changed
Binary file doc/images/lax-book_03-transitions-view_en.png has changed
Binary file doc/images/lax-book_04-detail-one-blog_en.png has changed
Binary file doc/images/lax-book_05-list-two-blog_en.png has changed
Binary file doc/images/lax-book_06-add-relation-entryof_en.png has changed
Binary file doc/images/lax-book_06-main-template-logo_en.png has changed
Binary file doc/images/lax-book_07-detail-one-blogentry_en.png has changed
Binary file doc/images/lax-book_08-schema_en.png has changed
Binary file doc/images/lax-book_09-new-view-blogentry_en.png has changed
Binary file doc/images/lax-book_10-blog-with-two-entries_en.png has changed
Binary file doc/images/main_template.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/images/main_template.svg	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1036.6421"
+   height="845.07812"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="main_template.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0"
+   inkscape:export-filename="/home/auc/cw/doc/book/en/images/main_template.png"
+   inkscape:export-xdpi="60.659016"
+   inkscape:export-ydpi="60.659016">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.80355603"
+     inkscape:cx="510.91495"
+     inkscape:cy="422.53906"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="925"
+     inkscape:window-height="1168"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:snap-bbox="true" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(162.2968,90.697922)">
+    <rect
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2439"
+       width="854.37006"
+       height="698.2019"
+       x="20.307629"
+       y="-20.575344" />
+    <rect
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3301"
+       width="816.3457"
+       height="508.15628"
+       x="31.751091"
+       y="96.33345" />
+    <g
+       id="g3220"
+       transform="matrix(1.0035394,0,0,1,0.5745006,0)">
+      <rect
+         y="-89.447922"
+         x="-161.0468"
+         height="55.714287"
+         width="1031.1713"
+         id="rect3240"
+         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.50000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <text
+         id="text3264"
+         y="-51.771908"
+         x="757.85767"
+         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+         xml:space="preserve"><tspan
+           id="tspan3266"
+           y="-51.771908"
+           x="757.85767"
+           sodipodi:role="line">header</tspan></text>
+    </g>
+    <rect
+       style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3270"
+       width="167.87744"
+       height="707.71222"
+       x="-160.02441"
+       y="-24.671618" />
+    <g
+       id="g2434"
+       transform="matrix(0.975467,0,0,1,0.6942419,-3.6587365)">
+      <rect
+         y="35.365849"
+         x="29.548275"
+         height="55.714287"
+         width="842.59979"
+         id="rect3279"
+         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <text
+         id="text3281"
+         y="72.885193"
+         x="681.65283"
+         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+         xml:space="preserve"><tspan
+           id="tspan3283"
+           y="72.885193"
+           x="681.65283"
+           sodipodi:role="line">contentheader</tspan></text>
+    </g>
+    <g
+       id="g3170"
+       transform="matrix(1.0023324,0,0,1,-2.0421673,-10.976211)">
+      <rect
+         y="698.6355"
+         x="-158.28485"
+         height="55.714287"
+         width="1032.5997"
+         id="rect3285"
+         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <text
+         id="text3287"
+         y="736.52045"
+         x="770.28204"
+         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+         xml:space="preserve"><tspan
+           id="tspan3289"
+           y="736.52045"
+           x="770.28204"
+           sodipodi:role="line">footer</tspan></text>
+    </g>
+    <g
+       id="g3211" />
+    <g
+       id="g3215"
+       transform="matrix(0.9712065,0,0,1,0.7659296,-17.074106)">
+      <rect
+         style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         id="rect3291"
+         width="844.62012"
+         height="55.714287"
+         x="27.850754"
+         y="629.88562" />
+      <text
+         id="text3293"
+         y="666.60339"
+         x="692.85773"
+         style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+         xml:space="preserve"><tspan
+           id="tspan3295"
+           y="666.60339"
+           x="692.85773"
+           sodipodi:role="line">contentfooter</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:23.38711166px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="-143.67273"
+       y="20.58094"
+       id="text3297"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2432"
+         x="-143.67273"
+         y="20.58094">left column</tspan></text>
+    <text
+       transform="scale(0.9876573,1.0124969)"
+       id="text3175"
+       y="12.071429"
+       x="721.0575"
+       style="font-size:23.09845161px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       xml:space="preserve"><tspan
+         id="tspan3177"
+         y="12.071429"
+         x="721.0575"
+         sodipodi:role="line">contentcol</tspan></text>
+    <text
+       transform="scale(0.9876573,1.0124969)"
+       id="text3179"
+       y="126.27104"
+       x="701.45959"
+       style="font-size:23.09845161px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       xml:space="preserve"><tspan
+         id="tspan3181"
+         y="126.27104"
+         x="701.45959"
+         sodipodi:role="line">contentmain</tspan></text>
+  </g>
+</svg>
Binary file doc/images/main_template_layout.png has changed
Binary file doc/images/primaryview_template.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/images/primaryview_template.svg	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1036.6421"
+   height="845.07812"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="primaryview_template.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0"
+   inkscape:export-filename="/home/steph/local/fcubicweb/cubicweb/doc/book/en/images/primaryview_template.png"
+   inkscape:export-xdpi="43.451603"
+   inkscape:export-ydpi="43.451603">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.9357135"
+     inkscape:cx="518.32104"
+     inkscape:cy="337.0428"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1307"
+     inkscape:window-height="1168"
+     inkscape:window-x="0"
+     inkscape:window-y="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(162.2968,90.697922)">
+    <g
+       id="g3869"
+       transform="matrix(1,0,0,1.0373644,0,-72.039777)"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449">
+      <rect
+         y="-15.840891"
+         x="-159.08963"
+         height="770.11017"
+         width="1033.0049"
+         id="rect3301"
+         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.90144825;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <text
+         id="text3865"
+         y="19.784882"
+         x="-150.07172"
+         style="font-size:28.67479324px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+         xml:space="preserve"><tspan
+           id="tspan3867"
+           y="19.784882"
+           x="-150.07172"
+           sodipodi:role="line">contentmain</tspan></text>
+    </g>
+    <rect
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.45654476;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2383"
+       width="772.32111"
+       height="43.888428"
+       x="-131.1837"
+       y="86.559296"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
+       x="-122.69418"
+       y="115.50363"
+       id="text2385"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         x="-122.69418"
+         y="115.50363"
+         id="tspan3163">navcontenttop</tspan></text>
+    <rect
+       style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:3.06523442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3167"
+       width="770.26868"
+       height="203.16078"
+       x="-125.88269"
+       y="172.90417"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449" />
+    <text
+       xml:space="preserve"
+       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="348.26724"
+       y="205.34305"
+       id="text3169"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         x="348.26724"
+         y="205.34305"
+         id="tspan3171">render_entity_attributes()</tspan></text>
+    <rect
+       style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:3.06523442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3173"
+       width="769.93549"
+       height="237.84663"
+       x="-125.03326"
+       y="391.32156"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449" />
+    <text
+       xml:space="preserve"
+       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="360.99954"
+       y="428.38055"
+       id="text3175"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         x="360.99954"
+         y="428.38055"
+         id="tspan3177">render_entity_relations()</tspan></text>
+    <rect
+       style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:2.15903592;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3185"
+       width="178.93939"
+       height="612.36584"
+       x="667.10443"
+       y="84.64225"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449" />
+    <text
+       xml:space="preserve"
+       style="font-size:22px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
+       x="105.32364"
+       y="-810.65997"
+       id="text3187"
+       transform="matrix(0,1,-1,0,0,0)"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         id="tspan2408">render_side_boxes()</tspan></text>
+    <rect
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:3.0652349;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3191"
+       width="771.97766"
+       height="55.647793"
+       x="-127.80586"
+       y="642.0293"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="-121.22153"
+       y="674.1748"
+       id="text3181"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         x="-121.22153"
+         y="674.1748"
+         id="tspan3183">navcontentbottom</tspan></text>
+    <rect
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.68198514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3881"
+       width="986.90503"
+       height="45.800392"
+       x="-128.34428"
+       y="-31.574066"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449" />
+    <text
+       xml:space="preserve"
+       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="355.60541"
+       y="-2.7424495"
+       id="text3883"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         x="355.60541"
+         y="-2.7424495"
+         id="tspan3885">render_entity_toolbox(), render_entity_title()</tspan></text>
+    <rect
+       style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.68198514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3890"
+       width="986.90503"
+       height="45.800392"
+       x="-128.87863"
+       y="19.723684"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449" />
+    <text
+       xml:space="preserve"
+       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="565.71027"
+       y="50.135612"
+       id="text3892"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         x="565.71027"
+         y="50.135612"
+         id="tspan3894">render_entity_summary()</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="87.154541"
+       y="114.2578"
+       id="text3899"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         id="tspan3903"
+         x="87.154541"
+         y="114.2578">content_navigation_components('navcontenttop')</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+       x="88.46772"
+       y="675.71582"
+       id="text2410"
+       sodipodi:linespacing="125%"
+       inkscape:export-filename="/home/auc/src/fcw/cubicweb/doc/book/en/images/primaryview_template.png"
+       inkscape:export-xdpi="60.912449"
+       inkscape:export-ydpi="60.912449"><tspan
+         sodipodi:role="line"
+         id="tspan2412"
+         x="88.46772"
+         y="675.71582">content_navigation_components('navcontenttop')</tspan></text>
+  </g>
+</svg>
Binary file doc/images/request_session.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/images/request_session.svg	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="85.960938"
+   height="12.382812"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.3.1 r9886"
+   sodipodi:docname="request_session.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Lend"
+       style="overflow:visible;">
+      <path
+         id="path3822"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.8) rotate(180) translate(12.5,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="25.928992"
+     inkscape:cy="-185.87004"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="958"
+     inkscape:window-height="1160"
+     inkscape:window-x="0"
+     inkscape:window-y="38"
+     inkscape:window-maximized="0"
+     inkscape:snap-global="true" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-263.52249,-495.73373)">
+    <rect
+       style="fill:#ffffff;stroke:#000000;stroke-width:0.92460138;stroke-opacity:1"
+       id="rect3773"
+       width="214.15233"
+       height="184.80336"
+       x="57.578697"
+       y="366.01306" />
+    <rect
+       id="rect2985"
+       width="216.86372"
+       height="183.54575"
+       x="348.50262"
+       y="367.78079"
+       style="fill:#ffffff;stroke:#000000;stroke-width:0.55298227;stroke-opacity:1" />
+    <text
+       xml:space="preserve"
+       style="font-size:32px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="376.7869"
+       y="399.80365"
+       id="text3755"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3757"
+         x="376.7869"
+         y="399.80365">Repository</tspan></text>
+    <rect
+       style="fill:#ffffff;stroke:#000000;stroke-opacity:1"
+       id="rect3759"
+       width="144.45181"
+       height="104.04572"
+       x="237.38585"
+       y="423.03714" />
+    <text
+       xml:space="preserve"
+       style="font-size:24px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="262.63968"
+       y="470.51431"
+       id="text3761"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3763"
+         x="262.63968"
+         y="470.51431">REPOAPI</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="262.63968"
+       y="507.88998"
+       id="text3765"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3767"
+         x="262.63968"
+         y="507.88998">connection</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="419.21332"
+       y="509.91025"
+       id="text3769"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3771"
+         x="419.21332"
+         y="509.91025">session</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:32px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="102.02541"
+       y="397.78333"
+       id="text3775"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3777"
+         x="102.02541"
+         y="397.78333">Client</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="116.16754"
+       y="507.88995"
+       id="text3779"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3781"
+         x="116.16754"
+         y="507.88995">request</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="361.50729"
+       y="585.89832"
+       id="text3802"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3804"
+         x="361.50729"
+         y="585.89832">database </tspan><tspan
+         sodipodi:role="line"
+         x="361.50729"
+         y="605.89832"
+         id="tspan3806">connection</tspan></text>
+    <rect
+       style="fill:#ffffff;stroke:#000000;stroke-width:1.48014534;stroke-opacity:1"
+       id="rect3808"
+       width="192.09367"
+       height="58.095726"
+       x="365.79443"
+       y="621.50018" />
+    <text
+       xml:space="preserve"
+       style="font-size:36px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="369.5885"
+       y="662.66992"
+       id="text3810"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3812"
+         x="369.5885"
+         y="662.66992">Database</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:none"
+       d="M 197.57252,125.76645 195.76971,55.592808"
+       id="path4260"
+       inkscape:connector-type="polyline"
+       inkscape:connector-curvature="3"
+       inkscape:connection-start="#rect3808"
+       inkscape:connection-start-point="d4"
+       inkscape:connection-end="#rect2985"
+       inkscape:connection-end-point="d4"
+       transform="translate(263.52249,495.73373)" />
+  </g>
+</svg>
Binary file doc/images/server-class-diagram.png has changed
Binary file doc/images/tutos-base_blog-form_en.png has changed
Binary file doc/images/tutos-base_blog-primary-after-post-creation_en.png has changed
Binary file doc/images/tutos-base_blog-primary_en.png has changed
Binary file doc/images/tutos-base_blogs-list_en.png has changed
Binary file doc/images/tutos-base_form-generic-relations_en.png has changed
Binary file doc/images/tutos-base_index_en.png has changed
Binary file doc/images/tutos-base_login-form_en.png has changed
Binary file doc/images/tutos-base_myblog-blogentry-taggable-commentable-primary_en.png has changed
Binary file doc/images/tutos-base_myblog-community-custom-primary_en.png has changed
Binary file doc/images/tutos-base_myblog-community-default-primary_en.png has changed
Binary file doc/images/tutos-base_myblog-community-taggable-primary_en.png has changed
Binary file doc/images/tutos-base_myblog-custom-footer_en.png has changed
Binary file doc/images/tutos-base_myblog-schema_en.png has changed
Binary file doc/images/tutos-base_myblog-siteinfo_en.png has changed
Binary file doc/images/tutos-base_schema_en.png has changed
Binary file doc/images/tutos-base_siteconfig_en.png has changed
Binary file doc/images/tutos-base_user-menu_en.png has changed
Binary file doc/images/tutos-photowebsite_background-image.png has changed
Binary file doc/images/tutos-photowebsite_boxes.png has changed
Binary file doc/images/tutos-photowebsite_breadcrumbs.png has changed
Binary file doc/images/tutos-photowebsite_facets.png has changed
Binary file doc/images/tutos-photowebsite_grey-box.png has changed
Binary file doc/images/tutos-photowebsite_index-after.png has changed
Binary file doc/images/tutos-photowebsite_index-before.png has changed
Binary file doc/images/tutos-photowebsite_login-box.png has changed
Binary file doc/images/tutos-photowebsite_prevnext.png has changed
Binary file doc/images/tutos-photowebsite_ui1.png has changed
Binary file doc/images/tutos-photowebsite_ui2.png has changed
Binary file doc/images/tutos-photowebsite_ui3.png has changed
Binary file doc/images/undo_history-view_w600.png has changed
Binary file doc/images/undo_mesage_w600.png has changed
Binary file doc/images/undo_startup-link_w600.png has changed
Binary file doc/images/views-table-filter-shadow.png has changed
Binary file doc/images/views-table-filter.png has changed
Binary file doc/images/views-table-shadow.png has changed
Binary file doc/images/views-table.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,111 @@
+=====================================================
+|cubicweb| - The Semantic Web is a construction game!
+=====================================================
+
+|cubicweb| is a semantic web application framework, licensed under the LGPL,
+that empowers developers to efficiently build web applications by reusing
+components (called `cubes`) and following the well known object-oriented design
+principles.
+
+Main Features
+~~~~~~~~~~~~~
+
+* an engine driven by the explicit :ref:`data model
+  <TutosBaseCustomizingTheApplicationDataModel>` of the application,
+
+* a query language named :ref:`RQL <RQL>` similar to W3C's SPARQL,
+
+* a :ref:`selection+view <TutosBaseCustomizingTheApplicationCustomViews>`
+  mechanism for semi-automatic XHTML/XML/JSON/text generation,
+
+* a library of reusable :ref:`components <Cube>` (data model and views) that
+  fulfill common needs,
+
+* the power and flexibility of the Python_ programming language,
+
+* the reliability of SQL databases, LDAP directories, Subversion and Mercurial
+  for storage backends.
+
+Built since 2000 from an R&D effort still continued, supporting 100,000s of
+daily visits at some production sites, |cubicweb| is a proven end to end solution
+for semantic web application development that promotes quality, reusability and
+efficiency.
+
+QuickStart
+~~~~~~~~~~
+
+The impatient developer will move right away to :ref:`SetUpEnv` then to :ref:`ConfigEnv`.
+
+Social
+~~~~~~
+
+*   Chat on the `jabber forum`_
+*   Discuss on the `mailing-list`_
+*   Discover on the `blog`_
+*   Contribute on the forge_
+
+
+.. _Logilab: http://www.logilab.fr/
+.. _forge: http://www.cubicweb.org/project/
+.. _Python: http://www.python.org/
+.. _`jabber forum`: http://www.logilab.org/blogentry/6718
+.. _`mailing-list`: http://lists.cubicweb.org/mailman/listinfo/cubicweb
+.. _blog: http://www.cubicweb.org/blog/1238
+
+
+Narrative Documentation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+A.k.a. "The Book"
+
+.. toctree::
+   :maxdepth: 2
+
+   book/intro/index
+
+.. toctree::
+   :maxdepth: 3
+
+   book/devrepo/index
+   book/devweb/index
+
+.. toctree::
+   :maxdepth: 2
+
+   book/admin/index
+   book/additionnal_services/index
+   book/annexes/index
+
+Tutorial
+~~~~~~~~
+
+We present two tutorials of different levels. The blog building
+tutorial introduces one smoothly to the basic concepts.
+
+Then there is a photo gallery construction tutorial which highlights
+more advanced concepts such as unit tests, security settings,
+migration scripts.
+
+.. toctree::
+   :maxdepth: 1
+   :numbered:
+
+   tutorials/base/index
+   tutorials/advanced/index
+   tutorials/tools/windmill.rst
+   tutorials/textreports/index
+
+
+Reference documentation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. toctree::
+    :maxdepth: 1
+
+    js_api/index
+
+Indexes
+~~~~~~~
+
+* the :ref:`genindex`,
+* the :ref:`modindex`,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tools/mode_plan.py	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,50 @@
+# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#
+# This file is part of CubicWeb.
+#
+# CubicWeb is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
+"""
+>>> from mode_plan import *
+>>> ls()
+<list of directory content>
+>>> ren('A01','A03')
+rename A010-joe.en.txt to A030-joe.en.txt
+accept [y/N]?
+"""
+
+def ren(a,b):
+    names = glob.glob('%s*'%a)
+    for name in names :
+        print 'rename %s to %s' % (name, name.replace(a,b))
+    if raw_input('accept [y/N]?').lower() =='y':
+        for name in names:
+            os.system('hg mv %s %s' % (name, name.replace(a,b)))
+
+
+def ls(): print '\n'.join(sorted(os.listdir('.')))
+
+def move():
+    filenames = []
+    for name in sorted(os.listdir('.')):
+        num = name[:2]
+        if num.isdigit():
+            filenames.append( (int(num), name) )
+
+
+    #print filenames
+
+    for num, name in filenames:
+        if num >= start:
+            print 'hg mv %s %2i%s' %(name,num+1,name[2:])
--- a/doc/tools/pyjsrest.py	Mon Jul 06 17:39:35 2015 +0200
+++ b/doc/tools/pyjsrest.py	Thu Jan 08 22:11:06 2015 +0100
@@ -92,6 +92,9 @@
                 f_rst.write(rst_content)
     stream = open(osp.join(rst_dir, 'index.rst'), 'w')
     stream.write('''
+Javascript API
+==============
+
 .. toctree::
     :maxdepth: 1
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/advanced/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,29 @@
+
+.. _TutosPhotoWebSite:
+
+Building a photo gallery with |cubicweb|
+========================================
+
+Desired features
+----------------
+
+* basically a photo gallery
+
+* photo stored on the file system and displayed dynamically through a web interface
+
+* navigation through folder (album), tags, geographical zone, people on the
+  picture... using facets
+
+* advanced security (not everyone can see everything). More on this later.
+
+
+.. toctree::
+   :maxdepth: 2
+
+   part01_create-cube
+   part02_security
+   part03_bfss
+   part04_ui-base
+   part05_ui-advanced
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/advanced/part01_create-cube.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,155 @@
+.. _TutosPhotoWebSiteCubeCreation:
+
+Cube creation and schema definition
+-----------------------------------
+
+.. _adv_tuto_create_new_cube:
+
+Step 1: creating a new cube for my web site
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One note about my development environment: I wanted to use the packaged
+version of CubicWeb and cubes while keeping my cube in my user
+directory, let's say `~src/cubes`.  I achieve this by setting the
+following environment variables::
+
+  CW_CUBES_PATH=~/src/cubes
+  CW_MODE=user
+
+I can now create the cube which will hold custom code for this web
+site using::
+
+  cubicweb-ctl newcube --directory=~/src/cubes sytweb
+
+
+.. _adv_tuto_assemble_cubes:
+
+Step 2: pick building blocks into existing cubes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Almost everything I want to handle in my web-site is somehow already modelized in
+existing cubes that I'll extend for my need. So I'll pick the following cubes:
+
+* `folder`, containing the `Folder` entity type, which will be used as
+  both 'album' and a way to map file system folders. Entities are
+  added to a given folder using the `filed_under` relation.
+
+* `file`, containing `File` entity type, gallery view, and a file system import
+  utility.
+
+* `zone`, containing the `Zone` entity type for hierarchical geographical
+  zones. Entities (including sub-zones) are added to a given zone using the
+  `situated_in` relation.
+
+* `person`, containing the `Person` entity type plus some basic views.
+
+* `comment`, providing a full commenting system allowing one to comment entity types
+  supporting the `comments` relation by adding a `Comment` entity.
+
+* `tag`, providing a full tagging system as an easy and powerful way to classify
+  entities supporting the `tags` relation by linking the to `Tag` entities. This
+  will allows navigation into a large number of picture.
+
+Ok, now I'll tell my cube requires all this by editing :file:`cubes/sytweb/__pkginfo__.py`:
+
+  .. sourcecode:: python
+
+    __depends__ = {'cubicweb': '>= 3.10.0',
+                   'cubicweb-file': '>= 1.9.0',
+		   'cubicweb-folder': '>= 1.1.0',
+		   'cubicweb-person': '>= 1.2.0',
+		   'cubicweb-comment': '>= 1.2.0',
+		   'cubicweb-tag': '>= 1.2.0',
+		   'cubicweb-zone': None}
+
+Notice that you can express minimal version of the cube that should be used,
+`None` meaning whatever version available. All packages starting with 'cubicweb-'
+will be recognized as being cube, not bare python packages. You can still specify
+this explicitly using instead the `__depends_cubes__` dictionary which should
+contains cube's name without the prefix. So the example below would be written
+as:
+
+  .. sourcecode:: python
+
+    __depends__ = {'cubicweb': '>= 3.10.0'}
+    __depends_cubes__ = {'file': '>= 1.9.0',
+		         'folder': '>= 1.1.0',
+		   	 'person': '>= 1.2.0',
+		   	 'comment': '>= 1.2.0',
+		   	 'tag': '>= 1.2.0',
+		   	 'zone': None}
+
+If your cube is packaged for debian, it's a good idea to update the
+`debian/control` file at the same time, so you won't forget it.
+
+
+Step 3: glue everything together in my cube's schema
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. sourcecode:: python
+
+    from yams.buildobjs import RelationDefinition
+
+    class comments(RelationDefinition):
+	subject = 'Comment'
+	object = 'File'
+	cardinality = '1*'
+	composite = 'object'
+
+    class tags(RelationDefinition):
+	subject = 'Tag'
+	object = 'File'
+
+    class filed_under(RelationDefinition):
+	subject = 'File'
+	object = 'Folder'
+
+    class situated_in(RelationDefinition):
+	subject = 'File'
+	object = 'Zone'
+
+    class displayed_on(RelationDefinition):
+	subject = 'Person'
+	object = 'File'
+
+
+This schema:
+
+* allows to comment and tag on `File` entity type by adding the `comments` and
+  `tags` relations. This should be all we've to do for this feature since the
+  related cubes provide 'pluggable section' which are automatically displayed on
+  the primary view of entity types supporting the relation.
+
+* adds a `situated_in` relation definition so that image entities can be
+  geolocalized.
+
+* add a new relation `displayed_on` relation telling who can be seen on a
+  picture.
+
+This schema will probably have to evolve as time goes (for security handling at
+least), but since the possibility to let a schema evolve is one of CubicWeb's
+features (and goals), we won't worry about it for now and see that later when needed.
+
+
+Step 4: creating the instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now that I have a schema, I want to create an instance. To
+do so using this new 'sytweb' cube, I run::
+
+  cubicweb-ctl create sytweb sytweb_instance
+
+Hint: if you get an error while the database is initialized, you can
+avoid having to answer the questions again by running::
+
+   cubicweb-ctl db-create sytweb_instance
+
+This will use your already configured instance and start directly from the create
+database step, thus skipping questions asked by the 'create' command.
+
+Once the instance and database are fully initialized, run ::
+
+  cubicweb-ctl start sytweb_instance
+
+to start the instance, check you can connect on it, etc...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/advanced/part02_security.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,440 @@
+.. _TutosPhotoWebSiteSecurity:
+
+Security, testing and migration
+-------------------------------
+
+This part will cover various topics:
+
+* configuring security
+* migrating existing instance
+* writing some unit tests
+
+Here is the ``read`` security model I want:
+
+* folders, files, images and comments should have one of the following visibility:
+
+  - ``public``, everyone can see it
+  - ``authenticated``, only authenticated users can see it
+  - ``restricted``, only a subset of authenticated users can see it
+
+* managers (e.g. me) can see everything
+* only authenticated users can see people
+* everyone can see classifier entities, such as tag and zone
+
+Also, unless explicitly specified, the visibility of an image should be the same as
+its parent folder, as well as visibility of a comment should be the same as the
+commented entity. If there is no parent entity, the default visibility is
+``authenticated``.
+
+Regarding write security, that's much easier:
+* anonymous can't write anything
+* authenticated users can only add comment
+* managers will add the remaining stuff
+
+Now, let's implement that!
+
+Proper security in CubicWeb is done at the schema level, so you don't have to
+bother with it in views: users will only see what they can see automatically.
+
+.. _adv_tuto_security:
+
+Step 1: configuring security into the schema
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In schema, you can grant access according to groups, or to some RQL expressions:
+users get access if the expression returns some results. To implement the read
+security defined earlier, groups are not enough, we'll need some RQL expression. Here
+is the idea:
+
+* add a `visibility` attribute on Folder, File and Comment, which may be one of
+  the value explained above
+
+* add a `may_be_read_by` relation from Folder, File and Comment to users,
+  which will define who can see the entity
+
+* security propagation will be done in hook.
+
+So the first thing to do is to modify my cube's schema.py to define those
+relations:
+
+.. sourcecode:: python
+
+    from yams.constraints import StaticVocabularyConstraint
+
+    class visibility(RelationDefinition):
+	subject = ('Folder', 'File', 'Comment')
+	object = 'String'
+	constraints = [StaticVocabularyConstraint(('public', 'authenticated',
+						   'restricted', 'parent'))]
+	default = 'parent'
+	cardinality = '11' # required
+
+    class may_be_read_by(RelationDefinition):
+        __permissions__ = {
+	    'read':   ('managers', 'users'),
+	    'add':    ('managers',),
+	    'delete': ('managers',),
+	    }
+
+	subject = ('Folder', 'File', 'Comment',)
+	object = 'CWUser'
+
+We can note the following points:
+
+* we've added a new `visibility` attribute to folder, file, image and comment
+  using a `RelationDefinition`
+
+* `cardinality = '11'` means this attribute is required. This is usually hidden
+  under the `required` argument given to the `String` constructor, but we can
+  rely on this here (same thing for StaticVocabularyConstraint, which is usually
+  hidden by the `vocabulary` argument)
+
+* the `parent` possible value will be used for visibility propagation
+
+* think to secure the `may_be_read_by` permissions, else any user can add/delete it
+  by default, which somewhat breaks our security model...
+
+Now, we should be able to define security rules in the schema, based on these new
+attribute and relation. Here is the code to add to *schema.py*:
+
+.. sourcecode:: python
+
+    from cubicweb.schema import ERQLExpression
+
+    VISIBILITY_PERMISSIONS = {
+	'read':   ('managers',
+		   ERQLExpression('X visibility "public"'),
+		   ERQLExpression('X may_be_read_by U')),
+	'add':    ('managers',),
+	'update': ('managers', 'owners',),
+	'delete': ('managers', 'owners'),
+	}
+    AUTH_ONLY_PERMISSIONS = {
+	    'read':   ('managers', 'users'),
+	    'add':    ('managers',),
+	    'update': ('managers', 'owners',),
+	    'delete': ('managers', 'owners'),
+	    }
+    CLASSIFIERS_PERMISSIONS = {
+	    'read':   ('managers', 'users', 'guests'),
+	    'add':    ('managers',),
+	    'update': ('managers', 'owners',),
+	    'delete': ('managers', 'owners'),
+	    }
+
+    from cubes.folder.schema import Folder
+    from cubes.file.schema import File
+    from cubes.comment.schema import Comment
+    from cubes.person.schema import Person
+    from cubes.zone.schema import Zone
+    from cubes.tag.schema import Tag
+
+    Folder.__permissions__ = VISIBILITY_PERMISSIONS
+    File.__permissions__ = VISIBILITY_PERMISSIONS
+    Comment.__permissions__ = VISIBILITY_PERMISSIONS.copy()
+    Comment.__permissions__['add'] = ('managers', 'users',)
+    Person.__permissions__ = AUTH_ONLY_PERMISSIONS
+    Zone.__permissions__ = CLASSIFIERS_PERMISSIONS
+    Tag.__permissions__ = CLASSIFIERS_PERMISSIONS
+
+What's important in there:
+
+* `VISIBILITY_PERMISSIONS` provides read access to managers group, if
+  `visibility` attribute's value is 'public', or if user (designed by the 'U'
+  variable in the expression) is linked to the entity (the 'X' variable) through
+  the `may_be_read_by` permission
+
+* we modify permissions of the entity types we use by importing them and
+  modifying their `__permissions__` attribute
+
+* notice the `.copy()`: we only want to modify 'add' permission for `Comment`,
+  not for all entity types using `VISIBILITY_PERMISSIONS`!
+
+* the remaining part of the security model is done using regular groups:
+
+  - `users` is the group to which all authenticated users will belong
+  - `guests` is the group of anonymous users
+
+
+.. _adv_tuto_security_propagation:
+
+Step 2: security propagation in hooks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To fullfill the requirements, we have to implement::
+
+  Also, unless explicity specified, visibility of an image should be the same as
+  its parent folder, as well as visibility of a comment should be the same as the
+  commented entity.
+
+This kind of `active` rule will be done using CubicWeb's hook
+system. Hooks are triggered on database events such as addition of a new
+entity or relation.
+
+The tricky part of the requirement is in *unless explicitly specified*, notably
+because when the entity is added, we don't know yet its 'parent'
+entity (e.g. Folder of an File, File commented by a Comment). To handle such things,
+CubicWeb provides `Operation`, which allow to schedule things to do at commit time.
+
+In our case we will:
+
+* on entity creation, schedule an operation that will set default visibility
+
+* when a "parent" relation is added, propagate parent's visibility unless the
+  child already has a visibility set
+
+Here is the code in cube's *hooks.py*:
+
+.. sourcecode:: python
+
+    from cubicweb.predicates import is_instance
+    from cubicweb.server import hook
+
+    class SetVisibilityOp(hook.DataOperationMixIn, hook.Operation):
+
+	def precommit_event(self):
+	    for eid in self.get_data():
+		entity = self.session.entity_from_eid(eid)
+		if entity.visibility == 'parent':
+		    entity.cw_set(visibility=u'authenticated')
+
+    class SetVisibilityHook(hook.Hook):
+	__regid__ = 'sytweb.setvisibility'
+	__select__ = hook.Hook.__select__ & is_instance('Folder', 'File', 'Comment')
+	events = ('after_add_entity',)
+
+	def __call__(self):
+	    SetVisibilityOp.get_instance(self._cw).add_data(self.entity.eid)
+
+    class SetParentVisibilityHook(hook.Hook):
+	__regid__ = 'sytweb.setparentvisibility'
+	__select__ = hook.Hook.__select__ & hook.match_rtype('filed_under', 'comments')
+	events = ('after_add_relation',)
+
+	def __call__(self):
+	    parent = self._cw.entity_from_eid(self.eidto)
+	    child = self._cw.entity_from_eid(self.eidfrom)
+	    if child.visibility == 'parent':
+		child.cw_set(visibility=parent.visibility)
+
+Notice:
+
+* hooks are application objects, hence have selectors that should match entity or
+  relation types to which the hook applies. To match a relation type, we use the
+  hook specific `match_rtype` selector.
+
+* usage of `DataOperationMixIn`: instead of adding an operation for each added entity,
+  DataOperationMixIn allows to create a single one and to store entity's eids to be
+  processed in the transaction data. This is a good pratice to avoid heavy
+  operations manipulation cost when creating a lot of entities in the same
+  transaction.
+
+* the `precommit_event` method of the operation will be called at transaction's
+  commit time.
+
+* in a hook, `self._cw` is the repository session, not a web request as usually
+  in views
+
+* according to hook's event, you have access to different attributes on the hook
+  instance. Here:
+
+  - `self.entity` is the newly added entity on 'after_add_entity' events
+
+  - `self.eidfrom` / `self.eidto` are the eid of the subject / object entity on
+    'after_add_relation' events (you may also get the relation type using
+    `self.rtype`)
+
+The `parent` visibility value is used to tell "propagate using parent security"
+because we want that attribute to be required, so we can't use None value else
+we'll get an error before we get any chance to propagate...
+
+Now, we also want to propagate the `may_be_read_by` relation. Fortunately,
+CubicWeb provides some base hook classes for such things, so we only have to add
+the following code to *hooks.py*:
+
+.. sourcecode:: python
+
+    # relations where the "parent" entity is the subject
+    S_RELS = set()
+    # relations where the "parent" entity is the object
+    O_RELS = set(('filed_under', 'comments',))
+
+    class AddEntitySecurityPropagationHook(hook.PropagateRelationHook):
+	"""propagate permissions when new entity are added"""
+	__regid__ = 'sytweb.addentity_security_propagation'
+	__select__ = (hook.PropagateRelationHook.__select__
+		      & hook.match_rtype_sets(S_RELS, O_RELS))
+	main_rtype = 'may_be_read_by'
+	subject_relations = S_RELS
+	object_relations = O_RELS
+
+    class AddPermissionSecurityPropagationHook(hook.PropagateRelationAddHook):
+	"""propagate permissions when new entity are added"""
+	__regid__ = 'sytweb.addperm_security_propagation'
+	__select__ = (hook.PropagateRelationAddHook.__select__
+		      & hook.match_rtype('may_be_read_by',))
+	subject_relations = S_RELS
+	object_relations = O_RELS
+
+    class DelPermissionSecurityPropagationHook(hook.PropagateRelationDelHook):
+	__regid__ = 'sytweb.delperm_security_propagation'
+	__select__ = (hook.PropagateRelationDelHook.__select__
+		      & hook.match_rtype('may_be_read_by',))
+	subject_relations = S_RELS
+	object_relations = O_RELS
+
+* the `AddEntitySecurityPropagationHook` will propagate the relation
+  when `filed_under` or `comments` relations are added
+
+  - the `S_RELS` and `O_RELS` set as well as the `match_rtype_sets` selector are
+    used here so that if my cube is used by another one, it'll be able to
+    configure security propagation by simply adding relation to one of the two
+    sets.
+
+* the two others will propagate permissions changes on parent entities to
+  children entities
+
+
+.. _adv_tuto_tesing_security:
+
+Step 3: testing our security
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Security is tricky. Writing some tests for it is a very good idea. You should
+even write them first, as Test Driven Development recommends!
+
+Here is a small test case that will check the basis of our security
+model, in *test/unittest_sytweb.py*:
+
+.. sourcecode:: python
+
+    from cubicweb.devtools.testlib import CubicWebTC
+    from cubicweb import Binary
+
+    class SecurityTC(CubicWebTC):
+
+        def test_visibility_propagation(self):
+            with self.admin_access.repo_cnx() as cnx:
+                # create a user for later security checks
+                toto = self.create_user(cnx, 'toto')
+                cnx.commit()
+                # init some data using the default manager connection
+                folder = cnx.create_entity('Folder',
+                                           name=u'restricted',
+                                           visibility=u'restricted')
+                photo1 = cnx.create_entity('File',
+                                           data_name=u'photo1.jpg',
+                                           data=Binary('xxx'),
+                                           filed_under=folder)
+                cnx.commit()
+                # visibility propagation
+                self.assertEquals(photo1.visibility, 'restricted')
+                # unless explicitly specified
+                photo2 = cnx.create_entity('File',
+                                           data_name=u'photo2.jpg',
+                                           data=Binary('xxx'),
+                                           visibility=u'public',
+                                           filed_under=folder)
+                cnx.commit()
+                self.assertEquals(photo2.visibility, 'public')
+            with self.new_access('toto').repo_cnx() as cnx:
+                # test security
+                self.assertEqual(1, len(cnx.execute('File X'))) # only the public one
+                self.assertEqual(0, len(cnx.execute('Folder X'))) # restricted...
+            with self.admin_access.repo_cnx() as cnx:
+                # may_be_read_by propagation
+                folder = cnx.entity_from_eid(folder.eid)
+                folder.cw_set(may_be_read_by=toto)
+                cnx.commit()
+            with self.new_access('toto').repo_cnx() as cnx:
+                photo1 = cnx.entity_from_eid(photo1.eid)
+                self.failUnless(photo1.may_be_read_by)
+                # test security with permissions
+                self.assertEquals(2, len(cnx.execute('File X'))) # now toto has access to photo2
+                self.assertEquals(1, len(cnx.execute('Folder X'))) # and to restricted folder
+
+    if __name__ == '__main__':
+        from logilab.common.testlib import unittest_main
+        unittest_main()
+
+It's not complete, but shows most things you'll want to do in tests: adding some
+content, creating users and connecting as them in the test, etc...
+
+To run it type:
+
+.. sourcecode:: bash
+
+    $ pytest unittest_sytweb.py
+    ========================  unittest_sytweb.py  ========================
+    -> creating tables [....................]
+    -> inserting default user and default groups.
+    -> storing the schema in the database [....................]
+    -> database for instance data initialized.
+    .
+    ----------------------------------------------------------------------
+    Ran 1 test in 22.547s
+
+    OK
+
+
+The first execution is taking time, since it creates a sqlite database for the
+test instance. The second one will be much quicker:
+
+.. sourcecode:: bash
+
+    $ pytest unittest_sytweb.py
+    ========================  unittest_sytweb.py  ========================
+    .
+    ----------------------------------------------------------------------
+    Ran 1 test in 2.662s
+
+    OK
+
+If you do some changes in your schema, you'll have to force regeneration of that
+database. You do that by removing the tmpdb files before running the test: ::
+
+    $ rm data/database/tmpdb*
+
+
+.. Note::
+  pytest is a very convenient utility used to control test execution. It is available from the `logilab-common`_ package.
+
+.. _`logilab-common`: http://www.logilab.org/project/logilab-common
+
+.. _adv_tuto_migration_script:
+
+Step 4: writing the migration script and migrating the instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Prior to those changes, I created an instance, fed it with some data, so I
+don't want to create a new one, but to migrate the existing one. Let's see how to
+do that.
+
+Migration commands should be put in the cube's *migration* directory, in a
+file named file:`<X.Y.Z>_Any.py` ('Any' being there mostly for historical reasons).
+
+Here I'll create a *migration/0.2.0_Any.py* file containing the following
+instructions:
+
+.. sourcecode:: python
+
+  add_relation_type('may_be_read_by')
+  add_relation_type('visibility')
+  sync_schema_props_perms()
+
+Then I update the version number in the cube's *__pkginfo__.py* to 0.2.0. And
+that's it! Those instructions will:
+
+* update the instance's schema by adding our two new relations and update the
+  underlying database tables accordingly (the first two instructions)
+
+* update schema's permissions definition (the last instruction)
+
+
+To migrate my instance I simply type::
+
+   cubicweb-ctl upgrade sytweb_instance
+
+You'll then be asked some questions to do the migration step by step. You should say
+YES when it asks if a backup of your database should be done, so you can get back
+to initial state if anything goes wrong...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/advanced/part03_bfss.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,131 @@
+Storing images on the file-system
+---------------------------------
+
+Step 1: configuring the BytesFileSystem storage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To avoid cluttering my database, and to ease file manipulation, I don't want them
+to be stored in the database. I want to be able create File entities for some
+files on the server file system, where those file will be accessed to get
+entities data. To do so I've to set a custom :class:`BytesFileSystemStorage`
+storage for the File 'data' attribute, which hold the actual file's content.
+
+Since the function to register a custom storage needs to have a repository
+instance as first argument, we've to call it in a server startup hook. So I added
+in `cubes/sytweb/hooks.py` :
+
+.. sourcecode:: python
+
+    from os import makedirs
+    from os.path import join, exists
+
+    from cubicweb.server import hook
+    from cubicweb.server.sources import storages
+
+    class ServerStartupHook(hook.Hook):
+        __regid__ = 'sytweb.serverstartup'
+        events = ('server_startup', 'server_maintenance')
+
+        def __call__(self):
+            bfssdir = join(self.repo.config.appdatahome, 'bfss')
+            if not exists(bfssdir):
+                makedirs(bfssdir)
+                print 'created', bfssdir
+            storage = storages.BytesFileSystemStorage(bfssdir)
+            storages.set_attribute_storage(self.repo, 'File', 'data', storage)
+
+.. Note::
+
+  * how we built the hook's registry identifier (`__regid__`): you can introduce
+    'namespaces' by using there python module like naming identifiers. This is
+    especially important for hooks where you usually want a new custom hook, not
+    overriding / specializing an existant one, but the concept may be applied to
+    any application objects
+
+  * we catch two events here: "server_startup" and "server_maintenance". The first
+    is called on regular repository startup (eg, as a server), the other for
+    maintenance task such as shell or upgrade. In both cases, we need to have
+    the storage set, else we'll be in trouble...
+
+  * the path given to the storage is the place where file added through the ui
+    (or in the database before migration) will be located
+
+  * beware that by doing this, you can't anymore write queries that will try to
+    restrict on File `data` attribute. Hopefuly we don't do that usually
+    on file's content or more generally on attributes for the Bytes type
+
+Now, if you've already added some photos through the web ui, you'll have to
+migrate existing data so file's content will be stored on the file-system instead
+of the database. There is a migration command to do so, let's run it in the
+cubicweb shell (in real life, you would have to put it in a migration script as we
+have seen last time):
+
+::
+
+   $ cubicweb-ctl shell sytweb_instance
+   entering the migration python shell
+   just type migration commands or arbitrary python code and type ENTER to execute it
+   type "exit" or Ctrl-D to quit the shell and resume operation
+   >>> storage_changed('File', 'data')
+   [........................]
+
+
+That's it. Now, files added through the web ui will have their content stored on
+the file-system, and you'll also be able to import files from the file-system as
+explained in the next part.
+
+Step 2: importing some data into the instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Hey, we start to have some nice features, let us give a try to this new web
+site. For instance if I have a 'photos/201005WePyrenees' containing pictures for
+a particular event, I can import it to my web site by typing ::
+
+  $ cubicweb-ctl fsimport -F sytweb_instance photos/201005WePyrenees/
+  ** importing directory /home/syt/photos/201005WePyrenees
+  importing IMG_8314.JPG
+  importing IMG_8274.JPG
+  importing IMG_8286.JPG
+  importing IMG_8308.JPG
+  importing IMG_8304.JPG
+
+.. Note::
+  The -F option means that folders should be mapped, hence my photos will be
+  linked to a Folder entity corresponding to the file-system folder.
+
+Let's take a look at the web ui:
+
+.. image:: ../../images/tutos-photowebsite_ui1.png
+
+Nothing different, I can't see the new folder... But remember our security model!
+By default, files are only accessible to authenticated users, and I'm looking at
+the site as anonymous, e.g. not authenticated. If I login, I can now see:
+
+.. image:: ../../images/tutos-photowebsite_ui2.png
+
+Yeah, it's there! You will notice that I can see some entities as well as
+folders and images the anonymous user can't. It just works **everywhere in the
+ui** since it's handled at the repository level, thanks to our security model.
+
+Now if I click on the recently inserted folder, I can see
+
+.. image:: ../../images/tutos-photowebsite_ui3.png
+
+Great! There is even my pictures in the folder. I can know give to this folder a
+nicer name (provided I don't intend to import from it anymore, else already
+imported photos will be reimported), change permissions, title for some pictures,
+etc... Having a good content is much more difficult than having a good web site
+;)
+
+
+Conclusion
+~~~~~~~~~~
+
+We started to see here an advanced feature of our repository: the ability
+to store some parts of our data-model into a custom storage, outside the
+database. There is currently only the :class:`BytesFileSystemStorage` available,
+but you can expect to see more coming in a near future (or write your own!).
+
+Also, we can know start to feed our web-site with some nice pictures!
+The site isn't perfect (far from it actually) but it's usable, and we can
+now start using it and improve it on the way. The Incremental Cubic Way :)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/advanced/part04_ui-base.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,361 @@
+Let's make it more user friendly
+================================
+
+
+Step 1: let's improve site's usability for our visitors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The first thing I've noticed is that people to whom I send links to photos with
+some login/password authentication get lost, because they don't grasp they have
+to login by clicking on the 'authenticate' link. That's much probably because
+they only get a 404 when trying to access an unauthorized folder, and the site
+doesn't make clear that 1. you're not authenticated, 2. you could get more
+content by authenticating yourself.
+
+So, to improve this situation, I decided that I should:
+
+* make a login box appears for anonymous, so they see at a first glance a place
+  to put the login / password information I provided
+
+* customize the 404 page, proposing to login to anonymous.
+
+Here is the code, samples from my cube's `views.py` file:
+
+.. sourcecode:: python
+
+    from cubicweb.predicates import is_instance
+    from cubicweb.web import component
+    from cubicweb.web.views import error
+    from cubicweb.predicates import anonymous_user
+
+    class FourOhFour(error.FourOhFour):
+	__select__ = error.FourOhFour.__select__ & anonymous_user()
+
+	def call(self):
+	    self.w(u"<h1>%s</h1>" % self._cw._('this resource does not exist'))
+	    self.w(u"<p>%s</p>" % self._cw._('have you tried to login?'))
+
+
+    class LoginBox(component.CtxComponent):
+	"""display a box containing links to all startup views"""
+	__regid__ = 'sytweb.loginbox'
+	__select__ = component.CtxComponent.__select__ & anonymous_user()
+
+	title = _('Authenticate yourself')
+	order = 70
+
+	def render_body(self, w):
+	    cw = self._cw
+	    form = cw.vreg['forms'].select('logform', cw)
+	    form.render(w=w, table_class='', display_progress_div=False)
+
+The first class provides a new specific implementation of the default page you
+get on 404 error, to display an adapted message to anonymous user.
+
+.. Note::
+
+  Thanks to the selection mecanism, it will be selected for anoymous user,
+  since the additional `anonymous_user()` selector gives it a higher score than
+  the default, and not for authenticated since this selector will return 0 in
+  such case (hence the object won't be selectable)
+
+The second class defines a simple box, that will be displayed by default with
+boxes in the left column, thanks to default :class:`component.CtxComponent`
+selector. The HTML is written to match default CubicWeb boxes style. The code
+fetch the actual login form and render it.
+
+
+.. figure:: ../../images/tutos-photowebsite_login-box.png
+   :alt: login box / 404 screenshot
+
+   The login box and the custom 404 page for an anonymous visitor (translated in french)
+
+
+Step 2: providing a custom index page
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Another thing we can easily do to improve the site is... A nicer index page
+(e.g. the first page you get when accessing the web site)! The default one is
+quite intimidating (that should change in a near future). I will provide a much
+simpler index page that simply list available folders (e.g. photo albums in that
+site).
+
+.. sourcecode:: python
+
+    from cubicweb.web.views import startup
+
+    class IndexView(startup.IndexView):
+	def call(self, **kwargs):
+	    self.w(u'<div>\n')
+	    if self._cw.cnx.anonymous_connection:
+		self.w(u'<h4>%s</h4>\n' % self._cw._('Public Albums'))
+	    else:
+		self.w(u'<h4>%s</h4>\n' % self._cw._('Albums for %s') % self._cw.user.login)
+	    self._cw.vreg['views'].select('tree', self._cw).render(w=self.w)
+	    self.w(u'</div>\n')
+
+    def registration_callback(vreg):
+	vreg.register_all(globals().values(), __name__, (IndexView,))
+	vreg.register_and_replace(IndexView, startup.IndexView)
+
+As you can see, we override the default index view found in
+`cubicweb.web.views.startup`, geting back nothing but its identifier and selector
+since we override the top level view's `call` method.
+
+.. Note::
+
+  in that case, we want our index view to **replace** the existing one. To do so
+  we've to implements the `registration_callback` function, in which we tell to
+  register everything in the module *but* our IndexView, then we register it
+  instead of the former index view.
+
+Also, we added a title that tries to make it more evident that the visitor is
+authenticated, or not. Hopefuly people will get it now!
+
+
+.. figure:: ../../images/tutos-photowebsite_index-before.png
+   :alt: default index page screenshot
+
+   The default index page
+
+.. figure:: ../../images/tutos-photowebsite_index-after.png
+   :alt: new index page screenshot
+
+   Our simpler, less intimidating, index page (still translated in french)
+
+
+Step 3: more navigation improvments
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are still a few problems I want to solve...
+
+* Images in a folder are displayed in a somewhat random order. I would like to
+  have them ordered by file's name (which will usually, inside a given folder,
+  also result ordering photo by their date and time)
+
+* When clicking a photo from an album view, you've to get back to the gallery
+  view to go to the next photo. This is pretty annoying...
+
+* Also, when viewing an image, there is no clue about the folder to which this
+  image belongs to.
+
+I will first try to explain the ordering problem. By default, when accessing
+related entities by using the ORM's API, you should get them ordered according to
+the target's class `cw_fetch_order`. If we take a look at the file cube'schema,
+we can see:
+
+.. sourcecode:: python
+
+    class File(AnyEntity):
+	"""customized class for File entities"""
+	__regid__ = 'File'
+	fetch_attrs, cw_fetch_order = fetch_config(['data_name', 'title'])
+
+
+By default, `fetch_config` will return a `cw_fetch_order` method that will order
+on the first attribute in the list. So, we could expect to get files ordered by
+their name. But we don't.  What's up doc ?
+
+The problem is that files are related to folder using the `filed_under` relation.
+And that relation is ambiguous, eg it can lead to `File` entities, but also to
+`Folder` entities. In such case, since both entity types doesn't share the
+attribute on which we want to sort, we'll get linked entities sorted on a common
+attribute (usually `modification_date`).
+
+To fix this, we've to help the ORM. We'll do this in the method from the `ITree`
+folder's adapter, used in the folder's primary view to display the folder's
+content. Here's the code, that I've put in our cube's `entities.py` file, since
+it's more logical stuff than view stuff:
+
+.. sourcecode:: python
+
+    from cubes.folder import entities as folder
+
+    class FolderITreeAdapter(folder.FolderITreeAdapter):
+
+	def different_type_children(self, entities=True):
+	    rql = self.entity.cw_related_rql(self.tree_relation,
+					     self.parent_role, ('File',))
+	    rset = self._cw.execute(rql, {'x': self.entity.eid})
+	    if entities:
+		return list(rset.entities())
+	    return rset
+
+    def registration_callback(vreg):
+	vreg.register_and_replace(FolderITreeAdapter, folder.FolderITreeAdapter)
+
+As you can see, we simple inherit from the adapter defined in the `folder` cube,
+then we override the `different_type_children` method to give a clue to the ORM's
+`cw_related_rql` method, that is responsible to generate the rql to get entities
+related to the folder by the `filed_under` relation (the value of the
+`tree_relation` attribute).  The clue is that we only want to consider the `File`
+target entity type. By doing this, we remove the ambiguity and get back a RQL
+query that correctly order files by their `data_name` attribute.
+
+
+.. Note::
+
+    * As seen earlier, we want to **replace** the folder's `ITree` adapter by our
+      implementation, hence the custom `registration_callback` method.
+
+
+Ouf. That one was tricky...
+
+Now the easier parts. Let's start by adding some links on the file's primary view
+to see the previous / next image in the same folder. CubicWeb's provide a
+component that do exactly that. To make it appears, one have to be adaptable to
+the `IPrevNext` interface. Here is the related code sample, extracted from our
+cube's `views.py` file:
+
+.. sourcecode:: python
+
+    from cubicweb.predicates import is_instance
+    from cubicweb.web.views import navigation
+
+
+    class FileIPrevNextAdapter(navigation.IPrevNextAdapter):
+	__select__ = is_instance('File')
+
+	def previous_entity(self):
+	    rset = self._cw.execute('File F ORDERBY FDN DESC LIMIT 1 WHERE '
+				    'X filed_under FOLDER, F filed_under FOLDER, '
+				    'F data_name FDN, X data_name > FDN, X eid %(x)s',
+				    {'x': self.entity.eid})
+	    if rset:
+		return rset.get_entity(0, 0)
+
+	def next_entity(self):
+	    rset = self._cw.execute('File F ORDERBY FDN ASC LIMIT 1 WHERE '
+				    'X filed_under FOLDER, F filed_under FOLDER, '
+				    'F data_name FDN, X data_name < FDN, X eid %(x)s',
+				    {'x': self.entity.eid})
+	    if rset:
+		return rset.get_entity(0, 0)
+
+
+The `IPrevNext` interface implemented by the adapter simply consist in the
+`previous_entity` / `next_entity` methods, that should respectivly return the
+previous / next entity or `None`. We make an RQL query to get files in the same
+folder, ordered similarly (eg by their `data_name` attribute). We set
+ascendant/descendant ordering and a strict comparison with current file's name
+(the "X" variable representing the current file).
+
+Notice that this query supposes we wont have two files of the same name in the
+same folder, else things may go wrong. Fixing this is out of the scope of this
+blog. And as I would like to have at some point a smarter, context sensitive
+previous/next entity, I'll probably never fix this query (though if I had to, I
+would probably choosing to add a constraint in the schema so that we can't add
+two files of the same name in a folder).
+
+One more thing: by default, the component will be displayed below the content
+zone (the one with the white background). You can change this in the site's
+properties through the ui, but you can also change the default value in the code
+by modifying the `context` attribute of the component:
+
+.. sourcecode:: python
+
+    navigation.NextPrevNavigationComponent.context = 'navcontentbottom'
+
+.. Note::
+
+   `context` may be one of 'navtop', 'navbottom', 'navcontenttop' or
+   'navcontentbottom'; the first two being outside the main content zone, the two
+   others inside it.
+
+.. figure:: ../../images/tutos-photowebsite_prevnext.png
+   :alt: screenshot of the previous/next entity component
+
+   The previous/next entity component, at the bottom of the main content zone.
+
+Now, the only remaining stuff in my todo list is to see the file's folder. I'll use
+the standard breadcrumb component to do so. Similarly as what we've seen before, this
+component is controled by the :class:`IBreadCrumbs` interface, so we'll have to provide a custom
+adapter for `File` entity, telling the a file's parent entity is its folder:
+
+.. sourcecode:: python
+
+    from cubicweb.web.views import ibreadcrumbs
+
+    class FileIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
+	__select__ = is_instance('File')
+
+	def parent_entity(self):
+	    if self.entity.filed_under:
+		return self.entity.filed_under[0]
+
+In that case, we simply use attribute notation provided by the ORM to get the
+folder in which the current file (e.g. `self.entity`) is located.
+
+.. Note::
+
+   The :class:`IBreadCrumbs` interface is a `breadcrumbs` method, but the default
+   :class:`IBreadCrumbsAdapter` provides a default implementation for it that will look
+   at the value returned by its `parent_entity` method. It also provides a
+   default implementation for this method for entities adapting to the `ITree`
+   interface, but as our `File` doesn't, we've to provide a custom adapter.
+
+.. figure:: ../../images/tutos-photowebsite_breadcrumbs.png
+   :alt: screenshot of the breadcrumb component
+
+   The breadcrumb component when on a file entity, now displaying parent folder.
+
+
+Step 4: preparing the release and migrating the instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Now that greatly enhanced our cube, it's time to release it to upgrade production site.
+I'll probably detail that process later, but I currently simply transfer the new code
+to the server running the web site.
+
+However, I've still today some step to respect to get things done properly...
+
+First, as I've added some translatable string, I've to run: ::
+
+  $ cubicweb-ctl i18ncube sytweb
+
+To update the cube's gettext catalogs (the '.po' files under the cube's `i18n`
+directory). Once the above command is executed, I'll then update translations.
+
+To see if everything is ok on my test instance, I do: ::
+
+  $ cubicweb-ctl i18ninstance sytweb
+  $ cubicweb-ctl start -D sytweb
+
+The first command compile i18n catalogs (e.g. generates '.mo' files) for my test
+instance. The second command start it in debug mode, so I can open my browser and
+navigate through the web site to see if everything is ok...
+
+.. Note::
+
+   In the 'cubicweb-ctl i18ncube' command, `sytweb` refers to the **cube**, while
+   in the two other, it refers to the **instance** (if you can't see the
+   difference, reread CubicWeb's concept chapter !).
+
+
+Once I've checked it's ok, I simply have to bump the version number in the
+`__pkginfo__` module to trigger a migration once I'll have updated the code on
+the production site. I can check then check the migration is also going fine, by
+first restoring a dump from the production site, then upgrading my test instance.
+
+To generate a dump from the production site: ::
+
+  $ cubicweb-ctl db-dump sytweb
+  pg_dump -Fc --username=syt --no-owner --file /home/syt/etc/cubicweb.d/sytweb/backup/tmpYIN0YI/system sytweb
+  -> backup file /home/syt/etc/cubicweb.d/sytweb/backup/sytweb-2010-07-13_10-22-40.tar.gz
+
+I can now get back the dump file ('sytweb-2010-07-13_10-22-40.tar.gz') to my test
+machine (using `scp` for instance) to restore it and start migration: ::
+
+  $ cubicweb-ctl db-restore sytweb sytweb-2010-07-13_10-22-40.tar.gz
+  $ cubicweb-ctl upgrade sytweb
+
+You'll have to answer some questions, as we've seen in `an earlier post`_.
+
+Now that everything is tested, I can transfer the new code to the production
+server, `apt-get upgrade` cubicweb and its dependencies, and eventually
+upgrade the production instance.
+
+
+.. _`several improvments`: http://www.cubicweb.org/blogentry/1179899
+.. _`3.8`: http://www.cubicweb.org/blogentry/917107
+.. _`first blog of this series`: http://www.cubicweb.org/blogentry/824642
+.. _`an earlier post`: http://www.cubicweb.org/867464
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/advanced/part05_ui-advanced.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,374 @@
+Building my photos web site with |cubicweb| part V: let's make it even more user friendly
+=========================================================================================
+
+.. _uiprops:
+
+Step 1: tired of the default look?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OK... Now our site has its most desired features. But... I would like to make it look
+somewhat like *my* website. It is not www.cubicweb.org after all. Let's tackle this
+first!
+
+The first thing we can to is to change the logo. There are various way to achieve
+this. The easiest way is to put a :file:`logo.png` file into the cube's :file:`data`
+directory. As data files are looked at according to cubes order (CubicWeb
+resources coming last), that file will be selected instead of CubicWeb's one.
+
+.. Note::
+   As the location for static resources are cached, you'll have to restart
+   your instance for this to be taken into account.
+
+Though there are some cases where you don't want to use a :file:`logo.png` file.
+For instance if it's a JPEG file. You can still change the logo by defining in
+the cube's :file:`uiprops.py` file:
+
+.. sourcecode:: python
+
+   LOGO = data('logo.jpg')
+
+The uiprops machinery is used to define some static file resources,
+such as the logo, default Javascript / CSS files, as well as CSS
+properties (we'll see that later).
+
+.. Note::
+   This file is imported specifically by |cubicweb|, with a predefined name space,
+   containing for instance the `data` function, telling the file is somewhere
+   in a cube or CubicWeb's data directory.
+
+   One side effect of this is that it can't be imported as a regular python
+   module.
+
+The nice thing is that in debug mode, change to a :file:`uiprops.py` file are detected
+and then automatically reloaded.
+
+Now, as it's a photos web-site, I would like to have a photo of mine as background...
+After some trials I won't detail here, I've found a working recipe explained `here`_.
+All I've to do is to override some stuff of the default CubicWeb user interface to
+apply it as explained.
+
+The first thing to to get the ``<img/>`` tag as first element after the
+``<body>`` tag.  If you know a way to avoid this by simply specifying the image
+in the CSS, tell me!  The easiest way to do so is to override the
+:class:`HTMLPageHeader` view, since that's the one that is directly called once
+the ``<body>`` has been written. How did I find this?  By looking in the
+:mod:`cubiweb.web.views.basetemplates` module, since I know that global page
+layouts sits there. I could also have grep the "body" tag in
+:mod:`cubicweb.web.views`... Finding this was the hardest part. Now all I need is
+to customize it to write that ``img`` tag, as below:
+
+.. sourcecode:: python
+
+    class HTMLPageHeader(basetemplates.HTMLPageHeader):
+	# override this since it's the easier way to have our bg image
+	# as the first element following <body>
+	def call(self, **kwargs):
+            self.w(u'<img id="bg-image" src="%sbackground.jpg" alt="background image"/>'
+                   % self._cw.datadir_url)
+	    super(HTMLPageHeader, self).call(**kwargs)
+
+
+    def registration_callback(vreg):
+	vreg.register_all(globals().values(), __name__, (HTMLPageHeader))
+	vreg.register_and_replace(HTMLPageHeader, basetemplates.HTMLPageHeader)
+
+
+As you may have guessed, my background image is in a :file:`background.jpg` file
+in the cube's :file:`data` directory, but there are still some things to explain
+to newcomers here:
+
+* The :meth:`call` method is there the main access point of the view. It's called by
+  the view's :meth:`render` method. It is not the only access point for a view, but
+  this will be detailed later.
+
+* Calling `self.w` writes something to the output stream. Except for binary views
+  (which do not generate text), it *must* be passed an Unicode string.
+
+* The proper way to get a file in :file:`data` directory is to use the `datadir_url`
+  attribute of the incoming request (e.g. `self._cw`).
+
+I won't explain again the :func:`registration_callback` stuff, you should understand it
+now!  If not, go back to previous posts in the series :)
+
+Fine. Now all I've to do is to add a bit of CSS to get it to behave nicely (which
+is not the case at all for now). I'll put all this in a :file:`cubes.sytweb.css`
+file, stored as usual in our :file:`data` directory:
+
+.. sourcecode:: css
+
+
+    /* fixed full screen background image
+     * as explained on http://webdesign.about.com/od/css3/f/blfaqbgsize.htm
+     *
+     * syt update: set z-index=0 on the img instead of z-index=1 on div#page & co to
+     * avoid pb with the user actions menu
+     */
+    img#bg-image {
+	position: fixed;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	z-index: 0;
+    }
+
+    div#page, table#header, div#footer {
+	background: transparent;
+	position: relative;
+    }
+
+    /* add some space around the logo
+     */
+    img#logo {
+	padding: 5px 15px 0px 15px;
+    }
+
+    /* more dark font for metadata to have a chance to see them with the background
+     *  image
+     */
+    div.metadata {
+	color: black;
+    }
+
+You can see here stuff explained in the cited page, with only a slight modification
+explained in the comments, plus some additional rules to make things somewhat cleaner:
+
+* a bit of padding around the logo
+
+* darker metadata which appears by default below the content (the white frame in the page)
+
+To get this CSS file used everywhere in the site, I have to modify the :file:`uiprops.py` file
+introduced above:
+
+.. sourcecode:: python
+
+   STYLESHEETS = sheet['STYLESHEETS'] + [data('cubes.sytweb.css')]
+
+.. Note::
+   `sheet` is another predefined variable containing values defined by
+   already process `:file:`uiprops.py`` file, notably the CubicWeb's one.
+
+Here we simply want our CSS in addition to CubicWeb's base CSS files, so we
+redefine the `STYLESHEETS` variable to existing CSS (accessed through the `sheet`
+variable) with our one added. I could also have done:
+
+.. sourcecode:: python
+
+   sheet['STYLESHEETS'].append(data('cubes.sytweb.css'))
+
+But this is less interesting since we don't see the overriding mechanism...
+
+At this point, the site should start looking good, the background image being
+resized to fit the screen.
+
+.. image:: ../../images/tutos-photowebsite_background-image.png
+
+The final touch: let's customize CubicWeb's CSS to get less orange... By simply adding
+
+.. sourcecode:: python
+
+  contextualBoxTitleBg = incontextBoxTitleBg = '#AAAAAA'
+
+and reloading the page we've just seen, we know have a nice greyed box instead of
+the orange one:
+
+.. image:: ../../images/tutos-photowebsite_grey-box.png
+
+This is because CubicWeb's CSS include some variables which are
+expanded by values defined in uiprops file. In our case we controlled the
+properties of the CSS `background` property of boxes with CSS class
+`contextualBoxTitleBg` and `incontextBoxTitleBg`.
+
+
+Step 2: configuring boxes
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Boxes present to the user some ways to use the application. Let's first do a few
+user interface tweaks in our :file:`views.py` file:
+
+.. sourcecode:: python
+
+  from cubicweb.predicates import none_rset
+  from cubicweb.web.views import bookmark
+  from cubes.zone import views as zone
+  from cubes.tag import views as tag
+
+  # change bookmarks box selector so it's only displayed on startup views
+  bookmark.BookmarksBox.__select__ = bookmark.BookmarksBox.__select__ & none_rset()
+  # move zone box to the left instead of in the context frame and tweak its order
+  zone.ZoneBox.context = 'left'
+  zone.ZoneBox.order = 100
+  # move tags box to the left instead of in the context frame and tweak its order
+  tag.TagsBox.context = 'left'
+  tag.TagsBox.order = 102
+  # hide similarity box, not interested
+  tag.SimilarityBox.visible = False
+
+The idea is to move all boxes in the left column, so we get more space for the
+photos.  Now, serious things: I want a box similar to the tags box but to handle
+the `Person displayed_on File` relation. We can do this simply by adding a
+:class:`AjaxEditRelationCtxComponent` subclass to our views, as below:
+
+.. sourcecode:: python
+
+    from logilab.common.decorators import monkeypatch
+    from cubicweb import ValidationError
+    from cubicweb.web.views import uicfg, component
+    from cubicweb.web.views import basecontrollers
+
+    # hide displayed_on relation using uicfg since it will be displayed by the box below
+    uicfg.primaryview_section.tag_object_of(('*', 'displayed_on', '*'), 'hidden')
+
+    class PersonBox(component.AjaxEditRelationCtxComponent):
+	__regid__ = 'sytweb.displayed-on-box'
+	# box position
+	order = 101
+	context = 'left'
+	# define relation to be handled
+	rtype = 'displayed_on'
+	role = 'object'
+	target_etype = 'Person'
+	# messages
+	added_msg = _('person has been added')
+	removed_msg = _('person has been removed')
+	# bind to js_* methods of the json controller
+	fname_vocabulary = 'unrelated_persons'
+	fname_validate = 'link_to_person'
+	fname_remove = 'unlink_person'
+
+
+    @monkeypatch(basecontrollers.JSonController)
+    @basecontrollers.jsonize
+    def js_unrelated_persons(self, eid):
+	"""return tag unrelated to an entity"""
+	rql = "Any F + ' ' + S WHERE P surname S, P firstname F, X eid %(x)s, NOT P displayed_on X"
+	return [name for (name,) in self._cw.execute(rql, {'x' : eid})]
+
+
+    @monkeypatch(basecontrollers.JSonController)
+    def js_link_to_person(self, eid, people):
+	req = self._cw
+	for name in people:
+	    name = name.strip().title()
+	    if not name:
+		continue
+	    try:
+		firstname, surname = name.split(None, 1)
+	    except:
+		raise ValidationError(eid, {('displayed_on', 'object'): 'provide <first name> <surname>'})
+	    rset = req.execute('Person P WHERE '
+			       'P firstname %(firstname)s, P surname %(surname)s',
+			       locals())
+	    if rset:
+		person = rset.get_entity(0, 0)
+	    else:
+		person = req.create_entity('Person', firstname=firstname,
+						surname=surname)
+	    req.execute('SET P displayed_on X WHERE '
+			'P eid %(p)s, X eid %(x)s, NOT P displayed_on X',
+			{'p': person.eid, 'x' : eid})
+
+    @monkeypatch(basecontrollers.JSonController)
+    def js_unlink_person(self, eid, personeid):
+	self._cw.execute('DELETE P displayed_on X WHERE P eid %(p)s, X eid %(x)s',
+			 {'p': personeid, 'x': eid})
+
+
+You basically subclass to configure with some class attributes. The `fname_*`
+attributes give the name of methods that should be defined on the json control to
+make the AJAX part of the widget work: one to get the vocabulary, one to add a
+relation and another to delete a relation. These methods must start by a `js_`
+prefix and are added to the controller using the `@monkeypatch` decorator. In my
+case, the most complicated method is the one which adds a relation, since it
+tries to see if the person already exists, and else automatically create it,
+assuming the user entered "firstname surname".
+
+Let's see how it looks like on a file primary view:
+
+.. image:: ../../images/tutos-photowebsite_boxes.png
+
+Great, it's now as easy for me to link my pictures to people than to tag them.
+Also, visitors get a consistent display of these two pieces of information.
+
+.. Note::
+  The ui component system has been refactored in `CubicWeb 3.10`_, which also
+  introduced the :class:`AjaxEditRelationCtxComponent` class.
+
+
+Step 3: configuring facets
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The last feature we'll add today is facet configuration. If you access to the
+'/file' url, you'll see a set of 'facets' appearing in the left column. Facets
+provide an intuitive way to build a query incrementally, by proposing to the user
+various way to restrict the result set. For instance CubicWeb proposes a facet to
+restrict based on who created an entity; the tag cube proposes a facet to
+restrict based on tags; the zoe cube a facet to restrict based on geographical
+location, and so on. In that gist, I want to propose a facet to restrict based on
+the people displayed on the picture. To do so, there are various classes in the
+:mod:`cubicweb.web.facet` module which simply have to be configured using class
+attributes as we've done for the box. In our case, we'll define a subclass of
+:class:`RelationFacet`.
+
+.. Note::
+
+   Since that's ui stuff, we'll continue to add code below to our
+   :file:`views.py` file. Though we begin to have a lot of various code their, so
+   it's may be a good time to split our views module into submodules of a `view`
+   package. In our case of a simple application (glue) cube, we could start using
+   for instance the layout below: ::
+
+     views/__init__.py   # uicfg configuration, facets
+     views/layout.py     # header/footer/background stuff
+     views/components.py # boxes, adapters
+     views/pages.py      # index view, 404 view
+
+.. sourcecode:: python
+
+    from cubicweb.web import facet
+
+    class DisplayedOnFacet(facet.RelationFacet):
+	__regid__ = 'displayed_on-facet'
+	# relation to be displayed
+	rtype = 'displayed_on'
+	role = 'object'
+	# view to use to display persons
+	label_vid = 'combobox'
+
+Let's say we also want to filter according to the `visibility` attribute. This is
+even simpler as we just have to derive from the :class:`AttributeFacet` class:
+
+.. sourcecode:: python
+
+    class VisibilityFacet(facet.AttributeFacet):
+	__regid__ = 'visibility-facet'
+	rtype = 'visibility'
+
+Now if I search for some pictures on my site, I get the following facets available:
+
+.. image:: ../../images/tutos-photowebsite_facets.png
+
+.. Note::
+
+  By default a facet must be applyable to every entity in the result set and
+  provide at leat two elements of vocabulary to be displayed (for instance you
+  won't see the `created_by` facet if the same user has created all
+  entities). This may explain why you don't see yours...
+
+
+Conclusion
+~~~~~~~~~~
+
+We started to see the power behind the infrastructure provided by the
+framework, both on the pure ui (CSS, Javascript) side and on the Python side
+(high level generic classes for components, including boxes and facets). We now
+have, with a few lines of code, a full-featured web site with a personalized look.
+
+Of course we'll probably want more as time goes, but we can now
+concentrate on making good pictures, publishing albums and sharing them with
+friends...
+
+
+
+.. _`CubicWeb 3.10`: http://www.cubicweb.org/blogentry/1330518
+.. _`here`: http://webdesign.about.com/od/css3/f/blfaqbgsize.htm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/base/blog-in-five-minutes.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,70 @@
+.. -*- coding: utf-8 -*-
+
+.. _TutosBaseBlogFiveMinutes:
+
+Get a blog running in five minutes!
+-----------------------------------
+
+For Debian or Ubuntu users, first install the following packages
+(:ref:`DebianInstallation`)::
+
+    cubicweb, cubicweb-dev, cubicweb-blog
+
+Windows or Mac OS X users must install |cubicweb| from source (see
+:ref:`SourceInstallation` and :ref:`WindowsInstallation`).
+
+Then create and initialize your instance::
+
+    cubicweb-ctl create blog myblog
+
+You'll be asked a few questions, and you can keep the default answer for most of
+them. The one question you'll have to think about is the database you'll want to
+use for that instance. For a quick test, if you don't have `postgresql` installed
+and configured (see :ref:`PostgresqlConfiguration`), it's highly recommended to
+choose `sqlite` when asked for which database driver to use, since it has a much
+simple setup (no database server needed).
+
+One the process is completed (including database initialisation), you can start
+your instance by using: ::
+
+    cubicweb-ctl start -D myblog
+
+The `-D` option activates the debugging mode. Removing it will launch the instance
+as a daemon in the background, and ``cubicweb-ctl stop myblog`` will stop
+it in that case. 
+
+
+About file system permissions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Unless you installed from sources, the above commands assume that you have root
+access to the :file:`/etc/` directory. In order to initialize your instance as a
+regular user, within your home directory, you can use the :envvar:`CW_MODE`
+environment variable: ::
+
+  export CW_MODE=user
+
+then create a :file:`~/etc/cubicweb.d` directory that will hold your instances.
+
+More information about how to configure your own environment is
+available in :ref:`ResourceMode`.
+
+
+Instance parameters
+~~~~~~~~~~~~~~~~~~~
+
+If you would like to change database parameters such as the database host or the
+user name used to connect to the database, edit the `sources` file located in the
+:file:`/etc/cubicweb.d/myblog` directory.
+
+Then relaunch the database creation::
+
+     cubicweb-ctl db-create myblog
+
+Other parameters, like web server or emails parameters, can be modified in the
+:file:`/etc/cubicweb.d/myblog/all-in-one.conf` file.
+
+You'll have to restart the instance after modification in one of those files.
+
+This is it. Your blog is functional and running. Visit http://localhost:8080 and enjoy it!
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/base/conclusion.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,18 @@
+.. -*- coding: utf-8 -*-
+
+What's next?
+------------
+
+In this tutorial, we have seen that you can, right after the installation of
+|cubicweb|, build a web application in a few minutes by defining a data model as
+assembling cubes. You get a working application that you can then customize there
+and there while keeping something that works. This is important in agile
+development practices, you can right from the start of the project show things
+to customer and so take the right decision early in the process.
+
+The next steps will be to discover hooks, security, data sources, digging deeper
+into view writing and interface customisation... Yet a lot of fun stuff to
+discover! You will find more `tutorials and howtos`_ in the blog published on the
+CubicWeb.org website.
+
+.. _`tutorials and howtos`: http://www.cubicweb.org/view?rql=Any+X+ORDERBY+D+DESC+WHERE+X+is+BlogEntry%2C+T+tags+X%2C+T+name+IN+%28%22tutorial%22%2C+%22howto%22%29%2C+X+creation_date+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/base/customizing-the-application.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,539 @@
+.. -*- coding: utf-8 -*-
+
+.. _TutosBaseCustomizingTheApplication:
+
+Customizing your application
+----------------------------
+
+So far so good. The point is that usually, you won't get enough by assembling
+cubes out-of-the-box. You will want to customize them, have a personal look and
+feel, add your own data model and so on. Or maybe start from scratch?
+
+So let's get a bit deeper and start coding our own cube. In our case, we want
+to customize the blog we created to add more features to it.
+
+
+Create your own cube
+~~~~~~~~~~~~~~~~~~~~
+
+First, notice that if you've installed |cubicweb| using Debian packages, you will
+need the additional ``cubicweb-dev`` package to get the commands necessary to
+|cubicweb| development. All `cubicweb-ctl` commands are described in details in
+:ref:`cubicweb-ctl`.
+
+Once your |cubicweb| development environment is set up, you can create a new
+cube::
+
+  cubicweb-ctl newcube myblog
+
+This will create in the cubes directory (:file:`/path/to/grshell/cubes` for source
+installation, :file:`/usr/share/cubicweb/cubes` for Debian packages installation)
+a directory named :file:`blog` reflecting the structure described in
+:ref:`cubelayout`.
+
+For packages installation, you can still create new cubes in your home directory
+using the following configuration. Let's say you want to develop your new cubes
+in `~src/cubes`, then set the following environment variables: ::
+
+  CW_CUBES_PATH=~/src/cubes
+
+and then create your new cube using: ::
+
+  cubicweb-ctl newcube --directory=~/src/cubes myblog
+
+.. Note::
+
+   We previously used `myblog` as the name of our *instance*. We're now creating
+   a *cube* with the same name. Both are different things. We'll now try to
+   specify when we talk about one or another, but keep in mind this difference.
+
+
+Cube metadata
+~~~~~~~~~~~~~
+
+A simple set of metadata about your cube are stored in the :file:`__pkginfo__.py`
+file. In our case, we want to extend the blog cube, so we have to tell that our
+cube depends on this cube, by modifying the ``__depends__`` dictionary in that
+file:
+
+.. sourcecode:: python
+
+   __depends__ =  {'cubicweb': '>= 3.10.7',
+                   'cubicweb-blog': None}
+
+where the ``None`` means we do not depends on a particular version of the cube.
+
+.. _TutosBaseCustomizingTheApplicationDataModel:
+
+Extending the data model
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The data model or schema is the core of your |cubicweb| application.  It defines
+the type of content your application will handle. It is defined in the file
+:file:`schema.py` of the cube.
+
+
+Defining our model
+******************
+
+For the sake of example, let's say we want a new entity type named `Community`
+with a name, a description. A `Community` will hold several blogs.
+
+.. sourcecode:: python
+
+  from yams.buildobjs import EntityType, RelationDefinition, String, RichString
+
+  class Community(EntityType):
+      name = String(maxsize=50, required=True)
+      description = RichString()
+
+  class community_blog(RelationDefinition):
+      subject = 'Community'
+      object = 'Blog'
+      cardinality = '*?'
+      composite = 'subject'
+
+The first step is the import from the :mod:`yams` package necessary classes to build
+the schema.
+
+This file defines the following:
+
+* a `Community` has a title and a description as attributes
+
+  - the name is a string that is required and can't be longer than 50 characters
+
+  - the description is a string that is not constrained and may contains rich
+    content such as HTML or Restructured text.
+
+* a `Community` may be linked to a `Blog` using the `community_blog` relation
+
+  - ``*`` means a community may be linked to 0 to N blog, ``?`` means a blog may
+    be linked to 0 to 1 community. For completeness, remember that you can also
+    use ``+`` for 1 to N, and ``1`` for single, mandatory relation (e.g. one to one);
+
+  - this is a composite relation where `Community` (e.g. the subject of the
+    relation) is the composite. That means that if you delete a community, its
+    blog will be deleted as well.
+
+Of course, there are a lot of other data types and things such as constraints,
+permissions, etc, that may be defined in the schema, but those won't be covered
+in this tutorial.
+
+Notice that our schema refers to the `Blog` entity type which is not defined
+here.  But we know this type is available since we depend on the `blog` cube
+which is defining it.
+
+
+Applying changes to the model into our instance
+***********************************************
+
+Now the problem is that we created an instance using the `blog` cube, not our
+`myblog` cube, so if we don't do anything there is no way that we'll see anything
+changing in the instance.
+
+One easy way, as we've no really valuable data in the instance would be to trash and recreated it::
+
+  cubicweb-ctl stop myblog # or Ctrl-C in the terminal running the server in debug mode
+  cubicweb-ctl delete myblog
+  cubicweb-ctl create myblog
+  cubicweb-ctl start -D myblog
+
+Another way is to add our cube to the instance using the cubicweb-ctl shell
+facility. It's a python shell connected to the instance with some special
+commands available to manipulate it (the same as you'll have in migration
+scripts, which are not covered in this tutorial). In that case, we're interested
+in the `add_cube` command: ::
+
+  $ cubicweb-ctl stop myblog # or Ctrl-C in the terminal running the server in debug mode
+  $ cubicweb-ctl shell myblog
+  entering the migration python shell
+  just type migration commands or arbitrary python code and type ENTER to execute it
+  type "exit" or Ctrl-D to quit the shell and resume operation
+  >>> add_cube('myblog')
+  >>>
+  $ cubicweb-ctl start -D myblog
+
+The `add_cube` command is enough since it automatically updates our
+application to the cube's schema. There are plenty of other migration
+commands of a more finer grain. They are described in :ref:`migration`
+
+As explained, leave the shell by typing Ctrl-D. If you restart the instance and
+take another look at the schema, you'll see that changes to the data model have
+actually been applied (meaning database schema updates and all necessary stuff
+has been done).
+
+.. image:: ../../images/tutos-base_myblog-schema_en.png
+   :alt: the instance schema after adding our cube
+
+If you follow the 'info' link in the user pop-up menu, you'll also see that the
+instance is using blog and myblog cubes.
+
+.. image:: ../../images/tutos-base_myblog-siteinfo_en.png
+   :alt: the instance schema after adding our cube
+
+You can now add some communities, link them to blog, etc... You'll see that the
+framework provides default views for this entity type (we have not yet defined any
+view for it!), and also that the blog primary view will show the community it's
+linked to if any. All this thanks to the model driven interface provided by the
+framework.
+
+You'll then be able to redefine each of them according to your needs
+and preferences. We'll now see how to do such thing.
+
+.. _TutosBaseCustomizingTheApplicationCustomViews:
+
+Defining your views
+~~~~~~~~~~~~~~~~~~~
+
+|cubicweb| provides a lot of standard views in directory
+:file:`cubicweb/web/views/`. We already talked about 'primary' and 'list' views,
+which are views which apply to one ore more entities.
+
+A view is defined by a python class which includes:
+
+  - an identifier: all objects used to build the user interface in |cubicweb| are
+    recorded in a registry and this identifier will be used as a key in that
+    registry. There may be multiple views for the same identifier.
+
+  - a *selector*, which is a kind of filter telling how well a view suit to a
+    particular context. When looking for a particular view (e.g. given an
+    identifier), |cubicweb| computes for each available view with that identifier
+    a score which is returned by the selector. Then the view with the highest
+    score is used. The standard library of predicates is in
+    :mod:`cubicweb.predicates`.
+
+A view has a set of methods inherited from the :class:`cubicweb.view.View` class,
+though you usually don't derive directly from this class but from one of its more
+specific child class.
+
+Last but not least, |cubicweb| provides a set of default views accepting any kind
+of entities.
+
+Want a proof? Create a community as you've already done for other entity types
+through the index page, you'll then see something like that:
+
+.. image:: ../../images/tutos-base_myblog-community-default-primary_en.png
+   :alt: the default primary view for our community entity type
+
+
+If you notice the weird messages that appear in the page: those are messages
+generated for the new data model, which have no translation yet. To fix that,
+we'll have to use dedicated `cubicweb-ctl` commands:
+
+.. sourcecode: bash
+
+  cubicweb-ctl i18ncube myblog # build/update cube's message catalogs
+  # then add translation into .po file into the cube's i18n directory
+  cubicweb-ctl i18ninstance myblog # recompile instance's message catalogs
+  cubicweb-ctl restart -D myblog # instance has to be restarted to consider new catalogs
+
+You'll then be able to redefine each of them according to your needs and
+preferences. So let's see how to do such thing.
+
+Changing the layout of the application
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The layout is the general organization of the pages in the site. Views that generate
+the layout are sometimes referred to as 'templates'. They are implemented in the
+framework in the module :mod:`cubicweb.web.views.basetemplates`. By overriding
+classes in this module, you can customize whatever part you wish of the default
+layout.
+
+But notice that |cubicweb| provides many other ways to customize the
+interface, thanks to actions and components (which you can individually
+(de)activate, control their location, customize their look...) as well as
+"simple" CSS customization. You should first try to achieve your goal using such
+fine grained parametrization rather then overriding a whole template, which usually
+embeds customisation access points that you may loose in the process.
+
+But for the sake of example, let's say we want to change the generic page
+footer...  We can simply add to the module ``views`` of our cube,
+e.g. :file:`cubes/myblog/views.py`, the code below:
+
+.. sourcecode:: python
+
+  from cubicweb.web.views import basetemplates
+
+  class MyHTMLPageFooter(basetemplates.HTMLPageFooter):
+
+      def footer_content(self):
+	  self.w(u'This website has been created with <a href="http://cubicweb.org">CubicWeb</a>.')
+
+  def registration_callback(vreg):
+      vreg.register_all(globals().values(), __name__, (MyHTMLPageFooter,))
+      vreg.register_and_replace(MyHTMLPageFooter, basetemplates.HTMLPageFooter)
+
+
+* Our class inherits from the default page footer to ease getting things right,
+  but this is not mandatory.
+
+* When we want to write something to the output stream, we simply call `self.w`,
+  which *must be passed a unicode string*.
+
+* The latest function is the most exotic stuff. The point is that without it, you
+  would get an error at display time because the framework wouldn't be able to
+  choose which footer to use between :class:`HTMLPageFooter` and
+  :class:`MyHTMLPageFooter`, since both have the same selector, hence the same
+  score...  In this case, we want our footer to replace the default one, so we have
+  to define a :func:`registration_callback` function to control object
+  registration: the first instruction tells to register everything in the module
+  but the :class:`MyHTMLPageFooter` class, then the second to register it instead
+  of :class:`HTMLPageFooter`. Without this function, everything in the module is
+  registered blindly.
+
+.. Note::
+
+  When a view is modified while running in debug mode, it is not required to
+  restart the instance server. Save the Python file and reload the page in your
+  web browser to view the changes.
+
+We will now have this simple footer on every page of the site.
+
+
+Primary view customization
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The 'primary' view (i.e. any view with the identifier set to 'primary') is the one used to
+display all the information about a single entity. The standard primary view is one
+of the most sophisticated views of all. It has several customisation points, but
+its power comes with `uicfg`, allowing you to control it without having to
+subclass it.
+
+However this is a bit off-topic for this first tutorial. Let's say we simply want a
+custom primary view for my `Community` entity type, using directly the view
+interface without trying to benefit from the default implementation (you should
+do that though if you're rewriting reusable cubes; everything is described in more
+details in :ref:`primary_view`).
+
+
+So... Some code! That we'll put again in the module ``views`` of our cube.
+
+.. sourcecode:: python
+
+  from cubicweb.predicates import is_instance
+  from cubicweb.web.views import primary
+
+  class CommunityPrimaryView(primary.PrimaryView):
+      __select__ = is_instance('Community')
+
+      def cell_call(self, row, col):
+          entity = self.cw_rset.get_entity(row, col)
+          self.w(u'<h1>Welcome to the "%s" community</h1>' % entity.printable_value('name'))
+          if entity.description:
+              self.w(u'<p>%s</p>' % entity.printable_value('description'))
+
+What's going on here?
+
+* Our class inherits from the default primary view, here mainly to get the correct
+  view identifier, since we don't use any of its features.
+
+* We set on it a selector telling that it only applies when trying to display
+  some entity of the `Community` type. This is enough to get an higher score than
+  the default view for entities of this type.
+
+* View applying to entities usually have to define `cell_call` as entry point,
+  and are given `row` and `col` arguments tell to which entity in the result set
+  the view is applied. We can then get this entity from the result set
+  (`self.cw_rset`) by using the `get_entity` method.
+
+* To ease thing, we access our entity's attribute for display using its
+  printable_value method, which will handle formatting and escaping when
+  necessary. As you can see, you can also access attributes by their name on the
+  entity to get the raw value.
+
+
+You can now reload the page of the community we just created and see the changes.
+
+.. image:: ../../images/tutos-base_myblog-community-custom-primary_en.png
+   :alt: the custom primary view for our community entity type
+
+We've seen here a lot of thing you'll have to deal with to write views in
+|cubicweb|. The good news is that this is almost everything that is used to
+build higher level layers.
+
+.. Note::
+
+  As things get complicated and the volume of code in your cube increases, you can
+  of course still split your views module into a python package with subpackages.
+
+You can find more details about views and selectors in :ref:`Views`.
+
+
+Write entities to add logic in your data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+|cubicweb| provides an ORM to easily programmaticaly manipulate
+entities (just like the one we have fetched earlier by calling
+`get_entity` on a result set). By default, entity
+types are instances of the :class:`AnyEntity` class, which holds a set of
+predefined methods as well as property automatically generated for
+attributes/relations of the type it represents.
+
+You can redefine each entity to provide additional methods or whatever you want
+to help you write your application. Customizing an entity requires that your
+entity:
+
+- inherits from :class:`cubicweb.entities.AnyEntity` or any subclass
+
+- defines a :attr:`__regid__` linked to the corresponding data type of your schema
+
+You may then want to add your own methods, override default implementation of some
+method, etc...
+
+.. sourcecode:: python
+
+    from cubicweb.entities import AnyEntity, fetch_config
+
+
+    class Community(AnyEntity):
+        """customized class for Community entities"""
+        __regid__ = 'Community'
+
+        fetch_attrs, cw_fetch_order = fetch_config(['name'])
+
+        def dc_title(self):
+            return self.name
+
+        def display_cw_logo(self):
+            return 'CubicWeb' in self.description
+
+In this example:
+
+* we used convenience :func:`fetch_config` function to tell which attributes
+  should be prefetched by the ORM when looking for some related entities of this
+  type, and how they should be ordered
+
+* we overrode the standard `dc_title` method, used in various place in the interface
+  to display the entity (though in this case the default implementation would
+  have had the same result)
+
+* we implemented here a method :meth:`display_cw_logo` which tests if the blog
+  entry title contains 'CW'.  It can then be used when you're writing code
+  involving 'Community' entities in your views, hooks, etc. For instance, you can
+  modify your previous views as follows:
+
+.. sourcecode:: python
+
+
+  class CommunityPrimaryView(primary.PrimaryView):
+      __select__ = is_instance('Community')
+
+      def cell_call(self, row, col):
+          entity = self.cw_rset.get_entity(row, col)
+          self.w(u'<h1>Welcome to the "%s" community</h1>' % entity.printable_value('name'))
+          if entity.display_cw_logo():
+              self.w(u'<img src="http://www.cubicweb.org/doc/en/_static/cubicweb.png"/>')
+          if entity.description:
+              self.w(u'<p>%s</p>' % entity.printable_value('description'))
+
+Then each community whose description contains 'CW' is shown with the |cubicweb|
+logo in front of it.
+
+.. Note::
+
+  As for view, you don't have to restart your instance when modifying some entity
+  classes while your server is running in debug mode, the code will be
+  automatically reloaded.
+
+
+Extending the application by using more cubes!
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One of the goal of the |cubicweb| framework was to have truly reusable
+components. To do so, they must both behave nicely when plugged into the
+application and be easily customisable, from the data model to the user
+interface. And I think the result is pretty successful, thanks to system such as
+the selection mechanism and the choice to write views as python code which allows
+to build our page using true object oriented programming techniques, that no
+template language provides.
+
+
+A library of standard cubes is available from `CubicWeb Forge`_, to address a
+lot of common concerns such has manipulating people, files, things to do, etc. In
+our community blog case, we could be interested for instance in functionalities
+provided by the `comment` and `tag` cubes. The former provides threaded
+discussion functionalities, the latter a simple tag mechanism to classify content.
+Let's say we want to try those. We will first modify our cube's :file:`__pkginfo__.py`
+file:
+
+.. sourcecode:: python
+
+   __depends__ =  {'cubicweb': '>= 3.10.7',
+                   'cubicweb-blog': None,
+                   'cubicweb-comment': None,
+                   'cubicweb-tag': None}
+
+Now, we'll simply tell on which entity types we want to activate the 'comment'
+and 'tag' facilities by adding respectively the 'comments' and 'tags' relations on
+them in our schema (:file:`schema.py`).
+
+.. sourcecode:: python
+
+  class comments(RelationDefinition):
+      subject = 'Comment'
+      object = 'BlogEntry'
+      cardinality = '1*'
+      composite = 'object'
+
+  class tags(RelationDefinition):
+      subject = 'Tag'
+      object = ('Community', 'BlogEntry')
+
+
+So in the case above we activated comments on `BlogEntry` entities and tags on
+both `Community` and `BlogEntry`. Various views from both `comment` and `tag`
+cubes will then be automatically displayed when one of those relations is
+supported.
+
+Let's synchronize the data model as we've done earlier: ::
+
+
+  $ cubicweb-ctl stop myblog
+  $ cubicweb-ctl shell myblog
+  entering the migration python shell
+  just type migration commands or arbitrary python code and type ENTER to execute it
+  type "exit" or Ctrl-D to quit the shell and resume operation
+  >>> add_cubes(('comment', 'tag'))
+  >>>
+
+Then restart the instance. Let's look at a blog entry:
+
+.. image:: ../../images/tutos-base_myblog-blogentry-taggable-commentable-primary_en.png
+   :alt: the primary view for a blog entry with comments and tags activated
+
+As you can see, we now have a box displaying tags and a section proposing to add
+a comment and displaying existing one below the post. All this without changing
+anything in our views, thanks to the design of generic views provided by the
+framework. Though if we take a look at a community, we won't see the tags box!
+That's because by default this box try to locate itself in the left column within
+the white frame, and this column is handled by the primary view we
+hijacked. Let's change our view to make it more extensible, by keeping both our
+custom rendering but also extension points provided by the default
+implementation.
+
+
+.. sourcecode:: python
+
+  class CommunityPrimaryView(primary.PrimaryView):
+      __select__ = is_instance('Community')
+
+      def render_entity_title(self, entity):
+	  self.w(u'<h1>Welcome to the "%s" community</h1>' % entity.printable_value('name'))
+
+      def render_entity_attributes(self, entity):
+	  if entity.display_cw_logo():
+	      self.w(u'<img src="http://www.cubicweb.org/doc/en/_static/cubicweb.png"/>')
+	  if entity.description:
+	      self.w(u'<p>%s</p>' % entity.printable_value('description'))
+
+It appears now properly:
+
+.. image:: ../../images/tutos-base_myblog-community-taggable-primary_en.png
+   :alt: the custom primary view for a community entry with tags activated
+
+You can control part of the interface independently from each others, piece by
+piece. Really.
+
+
+
+.. _`CubicWeb Forge`: http://www.cubicweb.org/project
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/base/discovering-the-ui.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,161 @@
+
+.. _TutosBaseDiscoveringTheUI:
+
+Discovering the web interface
+-----------------------------
+
+You can now access your web instance to create blogs and post messages
+by visiting the URL http://localhost:8080/.
+
+By default, anonymous access is disabled, so a login form will appear. If you
+asked to allow anonymous access when initializing the instance, click on the
+'login' link in the top right hand corner. To login, you need then use the admin
+account you specified at the time you initialized the database with
+``cubicweb-ctl create``.
+
+.. image:: ../../images/tutos-base_login-form_en.png
+   :alt: the login form
+
+
+Once authenticated, you can start playing with your instance. The default index
+page looks like the following:
+
+.. image:: ../../images/tutos-base_index_en.png
+   :alt: the index page
+
+
+Minimal configuration
+~~~~~~~~~~~~~~~~~~~~~
+
+Before creating entities, let's change that 'unset title' thing that appears
+here and there. This comes from a |cubicweb| system properties. To set it,
+click on the 'site configuration link' in the pop-up menu behind your login name
+in the upper left-hand corner
+
+.. image:: ../../images/tutos-base_user-menu_en.png
+   :alt: the user pop-up menu
+
+The site title is in the 'Ui' section. Simply set it to the desired value and
+click the 'validate' button.
+
+.. image:: ../../images/tutos-base_siteconfig_en.png
+   :alt: the site configuration form
+
+You should see a 'changes applied' message. You can now go back to the
+index page by clicking on the |cubicweb| logo in the upper left-hand corner.
+
+You will much likely still see 'unset title' at this point. This is because by
+default the index page is cached. Force a refresh of the page (by typing Ctrl-R
+in Firefox for instance) and you should now see the title you entered.
+
+
+Adding entities
+~~~~~~~~~~~~~~~
+
+The ``blog`` cube defines several entity types, among them ``Blog`` which is a
+container for ``BlogEntry`` (i.e. posts) on a particular topic. We can get a
+graphical view of the schema by clicking on the 'site schema' link in the user
+pop-up menu we've already seen:
+
+.. image:: ../../images/tutos-base_schema_en.png
+   :alt: graphical view of the schema (aka data-model)
+
+Nice isn't it? Notice that this, as most other stuff we'll see in this tutorial,
+is generated by the framework according to the model of the application. In our
+case, the model defined by the ``blog`` cube.
+
+Now let us create a few of these entities.
+
+
+Add a blog
+**********
+
+Clicking on the `[+]` at the left of the 'Blog' link on the index page will lead
+you to an HTML form to create a blog.
+
+.. image:: ../../images/tutos-base_blog-form_en.png
+   :alt: the blog creation form
+
+For instance, call this new blog 'Tech-blog' and type in 'everything about
+technology' as the description , then validate the form by clicking on
+'Validate'. You will be redirected to the `primary` view of the newly created blog.
+
+.. image:: ../../images/tutos-base_blog-primary_en.png
+   :alt: the blog primary view
+
+
+Add a blog post
+***************
+
+There are several ways to add a blog entry. The simplest is to click on the 'add
+blog entry' link in the actions box on viewing the blog you have just created.
+You will then see a form to create a post, with a 'blog entry of' field preset
+to the blog we're coming from. Enter a title, some content, click the 'validate'
+button and you're done. You will be redirected to the blog primary view, though you
+now see that it contains the blog post you've just created.
+
+.. image:: ../../images/tutos-base_blog-primary-after-post-creation_en.png
+   :alt: the blog primary view after creation of a post
+
+Notice there are some new boxes that appears in the left column.
+
+You can achieve the same thing by following the same path as we did for the blog
+creation, e.g. by clicking on the `[+]` at the left of the 'Blog entry' link on
+the index page. The diffidence being that since there is no context information,
+the 'blog entry of' selector won't be preset to the blog.
+
+
+If you click on the 'modify' link of the action box, you are back to
+the form to edit the entity you just created, except that the form now
+has another section with a combo-box entitled 'add relation'. It
+provisos a generic way to edit relations which don't appears in the
+above form. Choose the relation you want to add and a second combo box
+appears where you can pick existing entities.  If there are too many
+of them, you will be offered to navigate to the target entity, that is
+go away from the form and go back to it later, once you've selected
+the entity you want to link with.
+
+.. image:: ../../images/tutos-base_form-generic-relations_en.png
+   :alt: the generic relations combo box
+
+This combo box can't appear until the entity is actually created. That's why you
+haven't seen it at creation time. You could also have hit 'Apply' instead of
+'validate' and it would have showed up.
+
+
+About ui auto-adaptation
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+One of the things that make |cubicweb| different of other frameworks is
+its automatic user interface that adapts itself according to the data being
+displayed. Let's see an example.
+
+If you go back to the home page an click on the 'Blog' link, you will be redirected
+to the primary view of the blog, the same we've seen earlier. Now, add another
+blog, go back to the index page, and click again on this link. You will see
+a very different view (namely the 'list' view).
+
+.. image:: ../../images/tutos-base_blogs-list_en.png
+   :alt: the list view when there are more than one blog to display
+
+This is because in the first case, the framework chose to use the 'primary'
+view since there was only one entity in the data to be displayed. Now that there
+are two entities, the 'list' view is more appropriate and hence is being used.
+
+There are various other places where |cubicweb| adapts to display data in the best
+way, the main being provided by the view *selection* mechanism that will be detailed
+later.
+
+
+Digging deeper
+~~~~~~~~~~~~~~
+
+By following principles explained below, you should now be able to
+create new users for your application, to configure with a finer
+grain, etc... You will notice that the index page lists a lot of types
+you don't know about. Most are built-in types provided by the framework
+to make the whole system work. You may ignore them in a first time and
+discover them as time goes.
+
+One thing that is worth playing with is the search box. It may be used in various
+way, from simple full text search to advanced queries using the :ref:`RQL` .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/base/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,48 @@
+.. -*- coding: utf-8 -*-
+
+.. _TutosBase:
+
+Building a simple blog with |cubicweb|
+======================================
+
+|cubicweb| is a semantic web application framework that favors reuse and
+object-oriented design.
+
+
+This tutorial is designed to help in your very first steps to start with
+|cubicweb|. We will tour through basic concepts such as:
+
+* getting an application running by using existing components
+* discovering the default user interface
+* basic extending and customizing the look and feel of that application
+
+More advanced concepts are covered in :ref:`TutosPhotoWebSite`.
+
+
+.. _TutosBaseVocab:
+
+Some vocabulary
+---------------
+
+|cubicweb| comes with a few words of vocabulary that you should know to
+understand what we're talking about. To follow this tutorial, you should at least
+know that:
+
+* a `cube` is a component that usually includes a model defining some data types
+  and a set of views to display them. A cube can be built by assembling other
+  cubes;
+
+* an `instance` is a specific installation of one or more cubes and includes
+  configuration files, a web server and a database.
+
+Reading :ref:`Concepts` for more vocabulary will be required at some point.
+
+Now, let's start the hot stuff!
+
+.. toctree::
+   :maxdepth: 2
+
+   blog-in-five-minutes
+   discovering-the-ui
+   customizing-the-application
+   conclusion
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,21 @@
+.. _Tutorials:
+
+---------
+Tutorials
+---------
+
+We present two tutorials of different levels. The blog building
+tutorial introduces one smoothly to the basic concepts.
+
+Then there is a photo gallery construction tutorial which highlights
+more advanced concepts such as unit tests, security settings,
+migration scripts.
+
+.. toctree::
+   :maxdepth: 1
+   :numbered:
+
+   base/index
+   advanced/index
+   tools/windmill.rst
+   textreports/index
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/textreports/index.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,13 @@
+.. -*- coding: utf-8 -*-
+
+Writing text reports with RestructuredText
+==========================================
+
+|cubicweb| offers several text formats for the RichString type used in schemas,
+including restructuredtext.
+
+Three additional restructuredtext roles are defined by |cubicweb|:
+
+.. autofunction:: cubicweb.ext.rest.eid_reference_role
+.. autofunction:: cubicweb.ext.rest.rql_role
+.. autofunction:: cubicweb.ext.rest.bookmark_role
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorials/tools/windmill.rst	Thu Jan 08 22:11:06 2015 +0100
@@ -0,0 +1,229 @@
+==========================
+Use Windmill with CubicWeb
+==========================
+
+Windmill_ implements cross browser testing, in-browser recording and playback,
+and functionality for fast accurate debugging and test environment integration.
+
+.. _Windmill: http://www.getwindmill.com/
+
+`Online features list <http://www.getwindmill.com/features>`_ is available.
+
+
+Installation
+============
+
+Windmill
+--------
+
+You have to install Windmill manually for now. If you're using Debian, there is
+no binary package (`yet <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=579109>`_).
+
+The simplest solution is to use a *setuptools/pip* command (for a clean
+environment, take a look to the `virtualenv
+<http://pypi.python.org/pypi/virtualenv>`_ project as well)::
+
+    $ pip install windmill
+    $ curl -O http://github.com/windmill/windmill/tarball/master
+
+However, the Windmill project doesn't release frequently. Our recommandation is
+to used the last snapshot of the Git repository::
+
+    $ git clone git://github.com/windmill/windmill.git HEAD
+    $ cd windmill
+    $ python setup.py develop
+
+Install instructions are `available <http://wiki.github.com/windmill/windmill/installing>`_.
+
+Be sure to have the windmill module in your PYTHONPATH afterwards::
+
+    $ python -c "import windmill"
+
+X dummy
+-------
+
+In order to reduce unecessary system load from your test machines, It's
+recommended to use X dummy server for testing the Unix web clients, you need a
+dummy video X driver (as xserver-xorg-video-dummy package in Debian) coupled
+with a light X server as `Xvfb <http://en.wikipedia.org/wiki/Xvfb>`_.
+
+    The dummy driver is a special driver available with the XFree86 DDX. To use
+    the dummy driver, simply substitue it for your normal card driver in the
+    Device section of your xorg.conf configuration file. For example, if you
+    normally uses an ati driver, then you will have a Device section with
+    Driver "ati" to let the X server know that you want it to load and use the
+    ati driver; however, for these conformance tests, you would change that
+    line to Driver "dummy" and remove any other ati specific options from the
+    Device section.
+
+    *From: http://www.x.org/wiki/XorgTesting*
+
+Then, you can run the X server with the following command ::
+
+    $ /usr/bin/X11/Xvfb :1 -ac -screen 0 1280x1024x8 -fbdir /tmp
+
+
+Windmill usage
+==============
+
+Record your use case
+--------------------
+
+- start your instance manually
+- start Windmill_ with url site as last argument (read Usage_ or use *'-h'*
+  option to find required command line arguments)
+- use the record button
+- click on save to obtain python code of your use case
+- copy the content to a new file in a *windmill* directory
+
+.. _Usage: http://wiki.github.com/windmill/windmill/running-tests
+
+If you are using firefox as client, consider the "firebug" option.
+
+If you have a running instance, you can refine the test by the *loadtest* windmill option::
+
+    $ windmill -m firebug loadtest=<test_file.py> <instance url>
+
+Or use the internal windmill shell to explore available commands::
+
+    $ windmill -m firebug shell <instance url>
+
+And enter python commands:
+
+.. sourcecode:: python
+
+    >>> load_test(<your test file>)
+    >>> run_test(<your test file>)
+
+
+
+Integrate Windmill tests into CubicWeb
+======================================
+
+Set environment
+---------------
+
+You have to create a new unit test file and a `windmill` directory and copy all
+your windmill use case into it.
+
+.. sourcecode:: python
+
+    # test_windmill.py
+
+    # Run all scenarii found in windmill directory
+    from cubicweb.devtools.cwwindmill import (CubicWebWindmillUseCase,
+                                              unittest_main)
+
+    if __name__ == '__main__':
+        unittest_main()
+
+Run your tests
+--------------
+
+You can easily run your windmill test suite through `pytest` or :mod:`unittest`.
+You have to copy a *test_windmill.py* file from :mod:`web.test`.
+
+To run your test series::
+
+    $ pytest test/test_windmill.py
+
+By default, CubicWeb will use **firefox** as the default browser and will try
+to run test instance server on localhost. In the general case, You've no need
+to change anything.
+
+Check :class:`cubicweb.devtools.cwwindmill.CubicWebWindmillUseCase` for
+Windmill configuration. You can edit windmill settings with following class attributes:
+
+* browser
+  identification string (firefox|ie|safari|chrome) (firefox by default)
+* test_dir
+  testing file path or directory (windmill directory under your unit case
+  file by default)
+* edit_test
+  load and edit test for debugging (False by default)
+
+Examples:
+
+.. sourcecode:: python
+
+    browser = 'firefox'
+    test_dir = osp.join(__file__, 'windmill')
+    edit_test = False
+
+If you want to change cubicweb test server parameters, you can check class
+variables from :class:`CubicWebServerConfig` or inherit it with overriding the
+:attr:`configcls` attribute in :class:`CubicWebServerTC` ::
+
+.. sourcecode:: python
+
+    class OtherCubicWebServerConfig(CubicWebServerConfig):
+        port = 9999
+
+    class NewCubicWebServerTC(CubicWebServerTC):
+        configcls = OtherCubicWebServerConfig
+
+For instance, CubicWeb framework windmill tests can be manually run by::
+
+    $ pytest web/test/test_windmill.py
+
+Edit your tests
+---------------
+
+You can toggle the `edit_test` variable to enable test edition.
+
+But if you are using `pytest` as test runner, use the `-i` option directly.
+The test series will be loaded and you can run assertions step-by-step::
+
+    $ pytest -i test/test_windmill.py
+
+In this case, the `firebug` extension will be loaded automatically for you.
+
+Afterwards, don't forget to save your edited test into the right file (no autosave feature).
+
+Best practises
+--------------
+
+Don't run another instance on the same port. You risk to silence some
+regressions (test runner will automatically fail in further versions).
+
+Start your use case by using an assert on the expected primary url page.
+Otherwise all your tests could fail without clear explanation of the used
+navigation.
+
+In the same location of the *test_windmill.py*, create a *windmill/* with your
+windmill recorded use cases.
+
+
+Caveats
+=======
+
+File Upload
+-----------
+
+Windmill can't do file uploads. This is a limitation of browser Javascript
+support / sandboxing, not of Windmill per se.  It would be nice if there were
+some command that would prime the Windmill HTTP proxy to add a particular file
+to the next HTTP request that comes through, so that uploads could at least be
+faked.
+
+.. http://groups.google.com/group/windmill-dev/browse_thread/thread/cf9dc969722bd6bb/01aa18fdd652f7ff?lnk=gst&q=input+type+file#01aa18fdd652f7ff
+
+.. http://davisagli.com/blog/in-browser-integration-testing-with-windmill
+
+.. http://groups.google.com/group/windmill-dev/browse_thread/thread/b7bebcc38ed30dc7
+
+
+Preferences
+===========
+
+A *.windmill/prefs.py* could be used to redefine default configuration values.
+
+.. define CubicWeb preferences in the parent test case instead with a dedicated firefox profile
+
+For managing browser extensions, read `advanced topic chapter
+<http://wiki.github.com/windmill/windmill/advanced-topics>`_.
+
+More configuration examples could be seen in *windmill/conf/global_settings.py*
+as template.
+
+