[book] Update documentation for new repoapi
authorJulien Cristau <julien.cristau@logilab.fr>
Tue, 11 Mar 2014 15:56:05 +0100
changeset 9580 abaae1496ba4
parent 9579 d5b0e1f4c5c5
child 9581 cbf4846d408a
[book] Update documentation for new repoapi Quite a few things change in 3.19: - repoapi instead of dbapi - ClientConnection / Connection / Session rework - web authentication process - test APIs Closes #3638793
devtools/testlib.py
doc/book/en/devrepo/repo/sessions.rst
doc/book/en/devrepo/testing.rst
doc/book/en/devweb/request.rst
doc/book/en/images/request_session.png
doc/book/en/images/request_session.svg
--- a/devtools/testlib.py	Fri Mar 14 11:18:15 2014 +0100
+++ b/devtools/testlib.py	Tue Mar 11 15:56:05 2014 +0100
@@ -39,8 +39,9 @@
 from logilab.common.deprecation import deprecated, class_deprecated
 from logilab.common.shellutils import getlogin
 
-from cubicweb import ValidationError, NoSelectableObject, AuthenticationError
-from cubicweb import cwconfig, dbapi, devtools, web, server, repoapi
+from cubicweb import (ValidationError, NoSelectableObject, AuthenticationError,
+                      ProgrammingError)
+from cubicweb import cwconfig, devtools, web, server, repoapi
 from cubicweb.utils import json
 from cubicweb.sobjects import notification
 from cubicweb.web import Redirect, application
@@ -156,7 +157,7 @@
 
 
 class TestCaseConnectionProxy(object):
-    """thin wrapper around `cubicweb.dbapi.Connection` context-manager
+    """thin wrapper around `cubicweb.repoapi.ClientConnection` context-manager
     used in CubicWebTC (cf. `cubicweb.devtools.testlib.CubicWebTC.login` method)
 
     It just proxies to the default connection context manager but
@@ -260,7 +261,7 @@
     * `vreg`, the vregistry
     * `schema`, self.vreg.schema
     * `config`, cubicweb configuration
-    * `cnx`, dbapi connection to the repository using an admin user
+    * `cnx`, repoapi connection to the repository using an admin user
     * `session`, server side session associated to `cnx`
     * `app`, the cubicweb publisher (for web testing)
     * `repo`, the repository object
@@ -436,7 +437,7 @@
     def rollback(self):
         try:
             self.cnx.rollback()
-        except dbapi.ProgrammingError:
+        except ProgrammingError:
             pass # connection closed
         finally:
             self.session.set_cnxset() # ensure cnxset still set after commit
@@ -667,14 +668,13 @@
 
           .. sourcecode:: python
 
-                rdef = self.schema['CWUser'].rdef('login')
                 with self.temporary_permissions(CWUser={'read': ()}):
                     ...
 
-        Usually the former will be prefered to override permissions on a
+        Usually the former will be preferred to override permissions on a
         relation definition, while the latter is well suited for entity types.
 
-        The allowed keys in the permission dictionary depends on the schema type
+        The allowed keys in the permission dictionary depend on the schema type
         (entity type / relation definition). Resulting permissions will be
         similar to `orig_permissions.update(partial_perms)`.
         """
--- a/doc/book/en/devrepo/repo/sessions.rst	Fri Mar 14 11:18:15 2014 +0100
+++ b/doc/book/en/devrepo/repo/sessions.rst	Tue Mar 11 15:56:05 2014 +0100
@@ -3,50 +3,47 @@
 Sessions
 ========
 
-Sessions are object carrying the `.execute` method to query the data
-sources.
+Sessions are objects linked to an authenticated user.  The `Session.new_cnx`
+method returns a new Connection linked to that session.
+
+Connections
+===========
 
-Kinds of sessions
------------------
+Connections provide the `.execute` method to query the data sources.
 
-There are two kinds of sessions.
+Kinds of connections
+--------------------
 
-* `normal sessions` are the most common: they are related to users and
+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 sessions` have all the powers; they are also used in only a
+* `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
 
-.. note::
-  Do not confuse the session type with their connection mode, for
-  instance : `in memory` or `pyro`.
-
-Normal sessions are typically named `_cw` in most appobjects or
+Normal connections are typically named `_cw` in most appobjects or
 sometimes just `session`.
 
-Internal sessions are available from the `Repository` object and are
+Internal connections are available from the `Repository` object and are
 to be used like this:
 
 .. sourcecode:: python
 
-   session = self.repo.internal_session()
-   try:
-       do_stuff_with(session)
-   finally:
-       session.close()
+   with self.repo.internal_cnx() as cnx:
+       do_stuff_with(cnx)
+       cnx.commit()
 
-.. warning::
-  Do not forget to close such a session after use for a session leak
-  will quickly lead to an application crash.
+Connections should always be used as context managers, to avoid leaks.
 
 Authentication and management of sessions
 -----------------------------------------
 
 The authentication process is a ballet involving a few dancers:
 
-* through its `connect` method the top-level application object (the
+* 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`
@@ -88,7 +85,7 @@
 ------------------------------
 
 Sometimes CubicWeb's out-of-the-box authentication schemes (cookie and
-http) are not sufficient. Nowadays there is a plethore of such schemes
+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.
 
@@ -154,7 +151,7 @@
 
 .. sourcecode:: python
 
- class XFooUserRetriever(authentication.LoginPasswordRetreiver):
+ class XFooUserRetriever(authentication.LoginPasswordRetriever):
      """ authenticate by the x-foo-user http header
      or just do normal login/password authentication
      """
@@ -200,7 +197,8 @@
          return 1
      return 0
 
-Full API Session
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+Full Session and Connection API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 .. autoclass:: cubicweb.server.session.Session
+.. autoclass:: cubicweb.server.session.Connection
--- a/doc/book/en/devrepo/testing.rst	Fri Mar 14 11:18:15 2014 +0100
+++ b/doc/book/en/devrepo/testing.rst	Tue Mar 11 15:56:05 2014 +0100
@@ -466,29 +466,26 @@
 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 db-api connection (cubicweb-ctl shell for
+* 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 interact with the repository through a db-api connection.
+The client interacts with the repository through a repoapi connection.
 
 
-A db-api connection is tied to a session in the repository. The connection and
+A repoapi connection is tied to a session in the repository. The connection and
 request objects are unaccessible from repository code / the session object is
-unaccessible from client code (theorically at least).
+unaccessible from client code (theoretically at least).
 
-The :mod:`cubicweb.dbapi` module provides a base request class. The web interface
-provides an extended request class.
-
-
-The `request` object provides access to all cubicweb resources, eg:
+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 db-api connection (when using req.execute, you actually call the
-  db-api);
+* 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.).
@@ -510,37 +507,32 @@
 The `_cw` attribute
 ```````````````````
 The `_cw` attribute available on every application object provides access to all
-cubicweb resources, eg:
+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 client side (eg web interface view), `_cw` is a request
+  instance.
 
-For code running on the repository side (hooks and operation), `_cw` is a session
-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 (eg notifications) or with a
-DB-API request. In the later case, see :meth:`use_web_compatible_requests` on
-:class:`Connection` instances.
+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 handle by a single request, which will
-be thrown way once the response send.
+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 handle the transaction:
+The web publisher handles the transaction:
 
 * commit / rollback is done automatically
 * you should not commit / rollback explicitly
 
-When using a raw db-api, you're on your own regarding transaction.
-
-On the other hand, db-api connection and session live from a user login to its logout.
-
-Because session lives for a long time, and database connections is a limited
-resource, we can't bound a session to its own database connection for all its
+Because a session lives for a long time, and database connections are a limited
+resource, we can't bind a session to its own database connection for all its
 lifetime. The repository handles a pool of connections (4 by default), and it's
 responsible to attribute them as needed.
 
@@ -550,13 +542,13 @@
 
 2. the repository attributes a database connection to the session
 
-3. the repository's querier execute the query
+3. the repository's querier executes the query
 
 4. this query may trigger hooks. Hooks and operation may execute some rql queries
    through `_cw.execute`. Those queries go directly to the querier, hence don't
    touch the database connection, they use the one attributed in 2.
 
-5. the repository's get the result of the query in 1. If it was a RQL read query,
+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 rollbacked.
 
@@ -567,11 +559,11 @@
 * when using a request, or code executed in hooks, this database connection
   handling is totally transparent
 
-* however, take care when writing test: you are usually faking / testing both the
-  server and the client side, so you have to decide when to use self.request() /
-  self.session. Ask yourself "where the code I want to test will be running,
-  client or repository side ?". The response is usually : use a request :)
-  However, if you really need using a session:
+* 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 /
+  RepoAccess.repo_cnx. Ask yourself "where the code I want to test will be running,
+  client or repository side ?". The response is usually : use a client connection :)
+  However, if you really need using a server-side object:
 
   - commit / rollback will free the database connection (unless explicitly told
     not to do so).
--- a/doc/book/en/devweb/request.rst	Fri Mar 14 11:18:15 2014 +0100
+++ b/doc/book/en/devweb/request.rst	Tue Mar 11 15:56:05 2014 +0100
@@ -20,8 +20,6 @@
 
   * `ie_browser`: tells if the browser belong to the Internet Explorer
     family
-  * `xhtml_browser`: tells if the browser is able to properly handle
-    XHTML (at the HTTP content_type level)
 
 * `User and identification`:
 
@@ -30,7 +28,8 @@
 
 * `Session data handling`
 
-  * `session.data` is the dictionnary of the session data; it can be manipulated like an ordinary Python dictionnary
+  * `session.data` is the dictionary of the session data; it can be
+    manipulated like an ordinary Python dictionary
 
 * `Edition` (utilities for edition control):
 
@@ -104,8 +103,7 @@
   * `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
-  * `cursor()` returns a RQL cursor on the session
-  * `execute(*args, **kwargs)`, shortcut to ``.cursor().execute()``
+  * `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*
@@ -120,14 +118,14 @@
 ```
 
 The elements we gave in overview for above are built in three layers,
-from ``cubicweb.req.RequestSessionBase``, ``cubicweb.dbapi.DBAPIRequest`` and
-``cubicweb.web.CubicWebRequestBase``.
+from ``cubicweb.req.RequestSessionBase``, ``cubicweb.repoapi.ClientConnection`` and
+``cubicweb.web.ConnectionCubicWebRequestBase``.
 
 .. autoclass:: cubicweb.req.RequestSessionBase
    :members:
 
-.. autoclass:: cubicweb.dbapi.DBAPIRequest
+.. autoclass:: cubicweb.repoapi.ClientConnection
    :members:
 
-.. autoclass:: cubicweb.web.request.CubicWebRequestBase
+.. autoclass:: cubicweb.web.request.ConnectionCubicWebRequestBase
    :members:
Binary file doc/book/en/images/request_session.png has changed
--- a/doc/book/en/images/request_session.svg	Fri Mar 14 11:18:15 2014 +0100
+++ b/doc/book/en/images/request_session.svg	Tue Mar 11 15:56:05 2014 +0100
@@ -13,7 +13,7 @@
    height="12.382812"
    id="svg2"
    version="1.1"
-   inkscape:version="0.48.1 r9760"
+   inkscape:version="0.48.3.1 r9886"
    sodipodi:docname="request_session.svg">
   <defs
      id="defs4">
@@ -48,10 +48,10 @@
      fit-margin-left="0"
      fit-margin-right="0"
      fit-margin-bottom="0"
-     inkscape:window-width="766"
-     inkscape:window-height="1151"
-     inkscape:window-x="1152"
-     inkscape:window-y="24"
+     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
@@ -62,7 +62,7 @@
         <dc:format>image/svg+xml</dc:format>
         <dc:type
            rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
+        <dc:title />
       </cc:Work>
     </rdf:RDF>
   </metadata>
@@ -113,7 +113,7 @@
          sodipodi:role="line"
          id="tspan3763"
          x="262.63968"
-         y="470.51431">DB API</tspan></text>
+         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"